types.cpp
Go to the documentation of this file.
1 
29 #include <iomanip>
31 
33 
34 namespace tesseract_collision
35 {
37 {
38  distance = std::numeric_limits<double>::max();
39  nearest_points[0].setZero();
40  nearest_points[1].setZero();
41  nearest_points_local[0].setZero();
42  nearest_points_local[1].setZero();
43  transform[0] = Eigen::Isometry3d::Identity();
44  transform[1] = Eigen::Isometry3d::Identity();
45  link_names[0] = "";
46  link_names[1] = "";
47  shape_id[0] = -1;
48  shape_id[1] = -1;
49  subshape_id[0] = -1;
50  subshape_id[1] = -1;
51  type_id[0] = 0;
52  type_id[1] = 0;
53  normal.setZero();
54  cc_time[0] = -1;
55  cc_time[1] = -1;
58  cc_transform[0] = Eigen::Isometry3d::Identity();
59  cc_transform[1] = Eigen::Isometry3d::Identity();
60  single_contact_point = false;
61 }
62 
64 {
65  bool ret_val = true;
71  ret_val &= transform[0].isApprox(rhs.transform[0]);
72  ret_val &= transform[1].isApprox(rhs.transform[1]);
73  ret_val &= (link_names == rhs.link_names);
74  ret_val &= (shape_id == rhs.shape_id);
75  ret_val &= (subshape_id == rhs.subshape_id);
76  ret_val &= (type_id == rhs.type_id);
80  ret_val &= (cc_type == rhs.cc_type);
81  ret_val &= cc_transform[0].isApprox(rhs.cc_transform[0]);
82  ret_val &= cc_transform[1].isApprox(rhs.cc_transform[1]);
83  ret_val &= (single_contact_point == rhs.single_contact_point);
84 
85  return ret_val;
86 }
87 bool ContactResult::operator!=(const ContactResult& rhs) const { return !operator==(rhs); }
88 
90 
92 {
93  bool ret_val = true;
94  ret_val &= (type == rhs.type);
95  ret_val &= (calculate_penetration == rhs.calculate_penetration);
96  ret_val &= (calculate_distance == rhs.calculate_distance);
97  ret_val &= (contact_limit == rhs.contact_limit);
98  ret_val &= (is_valid == rhs.is_valid);
99  return ret_val;
100 }
101 bool ContactRequest::operator!=(const ContactRequest& rhs) const { return !operator==(rhs); }
102 
104 {
105  assert(tesseract_common::makeOrderedLinkPair(key.first, key.second) == key);
106  ++count_;
107  auto& cv = data_[key];
108  return cv.emplace_back(std::move(result));
109 }
110 
112 {
113  assert(!results.empty());
114  assert(tesseract_common::makeOrderedLinkPair(key.first, key.second) == key);
115  count_ += static_cast<long>(results.size());
116  auto& cv = data_[key];
117  cv.reserve(cv.size() + results.size());
118  cv.insert(cv.end(), results.begin(), results.end());
119  return cv.back();
120 }
121 
123 {
124  assert(tesseract_common::makeOrderedLinkPair(key.first, key.second) == key);
125  auto& cv = data_[key];
126  count_ += (1 - static_cast<long>(cv.size()));
127  assert(count_ >= 0);
128  cv.clear();
129 
130  return cv.emplace_back(std::move(result));
131 }
132 
134 {
135  assert(tesseract_common::makeOrderedLinkPair(key.first, key.second) == key);
136  assert(!results.empty());
137  auto& cv = data_[key];
138  count_ += (static_cast<long>(results.size()) - static_cast<long>(cv.size()));
139  assert(count_ >= 0);
140  cv.clear();
141  cv.reserve(results.size());
142  cv.insert(cv.end(), results.begin(), results.end());
143  return cv.back();
144 }
145 
147  long sub_segment_index,
148  long sub_segment_last_index,
149  const std::vector<std::string>& active_link_names,
150  double segment_dt,
151  bool discrete,
153 {
154  for (auto& pair : sub_segment_results.data_)
155  {
156  assert(tesseract_common::makeOrderedLinkPair(pair.first.first, pair.first.second) == pair.first);
157  // Update cc_time and cc_type
158  for (auto& r : pair.second)
159  {
160  // Iterate over the two time values in r.cc_time
161  for (size_t j = 0; j < 2; ++j)
162  {
163  if (std::find(active_link_names.begin(), active_link_names.end(), r.link_names[j]) != active_link_names.end())
164  {
165  r.cc_time[j] = (r.cc_time[j] < 0) ?
166  (static_cast<double>(sub_segment_index) * segment_dt) :
167  (static_cast<double>(sub_segment_index) * segment_dt) + (r.cc_time[j] * segment_dt);
168  assert(r.cc_time[j] >= 0.0 && r.cc_time[j] <= 1.0);
169  if (sub_segment_index == 0 &&
172  else if (sub_segment_index == sub_segment_last_index &&
175  else
177 
178  // If discrete set cc_transform for discrete continuous
179  if (discrete)
180  r.cc_transform = r.transform;
181  }
182  }
183  }
184 
185  // Filter results
186  if (filter != nullptr)
187  filter(pair);
188 
189  if (!pair.second.empty())
190  {
191  // Add results to the full segment results
192  count_ += static_cast<long>(pair.second.size());
193  auto it = data_.find(pair.first);
194  if (it == data_.end())
195  {
196  data_.insert(pair);
197  }
198  else
199  {
200  assert(it != data_.end());
201  // Note: Must include all contacts throughout the trajectory so the optimizer has all the information
202  // to understand how to adjust the start and end state to move it out of collision. Originally tried
203  // keeping the worst case only but ran into edge cases where this does not work in the units tests.
204 
205  it->second.reserve(it->second.size() + pair.second.size());
206  it->second.insert(it->second.end(), pair.second.begin(), pair.second.end());
207  }
208  }
209  }
210 }
211 
212 long ContactResultMap::count() const { return count_; }
213 
214 std::size_t ContactResultMap::size() const
215 {
216  if (count_ == 0)
217  return 0;
218 
219  std::size_t cnt{ 0 };
220  for (const auto& pair : data_)
221  {
222  if (!pair.second.empty())
223  ++cnt;
224  }
225 
226  return cnt;
227 }
228 
229 bool ContactResultMap::empty() const { return (count_ == 0); }
230 
232 {
233  if (count_ == 0)
234  return;
235 
236  // Only clear the vectors so the capacity stays the same
237  for (auto& cv : data_)
238  cv.second.clear();
239 
240  count_ = 0;
241 }
242 
244 {
245  // Erase members that satisfy needs_removing(itr)
246  for (auto it = data_.cbegin(); it != data_.cend();)
247  it = it->second.empty() ? data_.erase(it) : std::next(it);
248 }
249 
251 {
252  data_.clear();
253  count_ = 0;
254 }
255 
257 
259 
261 
263 
265 
266 const ContactResultVector& ContactResultMap::at(const KeyType& key) const { return data_.at(key); }
267 
269 
271 {
272  v.clear();
273  v.reserve(static_cast<std::size_t>(count_));
274  for (auto& mv : data_)
275  {
276  std::move(mv.second.begin(), mv.second.end(), std::back_inserter(v));
277  mv.second.clear();
278  }
279  count_ = 0;
280 }
281 
283 {
284  v.clear();
285  v.reserve(static_cast<std::size_t>(count_));
286  for (const auto& mv : data_)
287  std::copy(mv.second.begin(), mv.second.end(), std::back_inserter(v));
288 }
289 
290 void ContactResultMap::flattenWrapperResults(std::vector<std::reference_wrapper<ContactResult>>& v)
291 {
292  v.clear();
293  v.reserve(static_cast<std::size_t>(count_));
294  for (auto& mv : data_)
295  v.insert(v.end(), mv.second.begin(), mv.second.end());
296 }
297 
298 void ContactResultMap::flattenWrapperResults(std::vector<std::reference_wrapper<const ContactResult>>& v) const
299 {
300  v.clear();
301  v.reserve(static_cast<std::size_t>(count_));
302  for (const auto& mv : data_)
303  v.insert(v.end(), mv.second.begin(), mv.second.end());
304 }
305 
307 {
308  std::size_t removed_cnt{ 0 };
309  for (auto& pair : data_)
310  {
311  std::size_t current_cnt = pair.second.size();
312  filter(pair);
313  removed_cnt += (current_cnt - pair.second.size());
314  }
315  count_ -= static_cast<long>(removed_cnt);
316  assert(count_ >= 0);
317 }
318 
320 {
321  return ((data_ == rhs.data_) && (count_ == rhs.count_));
322 }
323 bool ContactResultMap::operator!=(const ContactResultMap& rhs) const { return !operator==(rhs); }
324 
325 std::string ContactResultMap::getSummary() const
326 {
327  std::stringstream ss;
328  std::map<KeyType, std::size_t> collision_counts;
329  std::map<KeyType, double> closest_distances;
330 
331  // Initialize distances map with max values
332  for (const auto& pair : data_)
333  {
334  if (!pair.second.empty())
335  {
336  collision_counts[pair.first] = pair.second.size();
337  closest_distances[pair.first] = std::numeric_limits<double>::max();
338 
339  // Find closest distance for this pair
340  for (const auto& result : pair.second)
341  {
342  closest_distances[pair.first] = std::min(closest_distances[pair.first], result.distance);
343  }
344  }
345  }
346 
347  if (collision_counts.empty())
348  {
349  return "No collisions detected";
350  }
351 
352  auto max_element = std::max_element(collision_counts.begin(),
353  collision_counts.end(),
354  [](const auto& p1, const auto& p2) { return p1.second < p2.second; });
355 
356  ss << max_element->first.first << " - " << max_element->first.second << ": " << max_element->second
357  << " collisions, min dist: " << closest_distances[max_element->first];
358 
359  return ss.str();
360 }
361 
362 ContactTestData::ContactTestData(const std::vector<std::string>& active,
363  CollisionMarginData collision_margin_data,
364  std::shared_ptr<const tesseract_common::ContactAllowedValidator> validator,
365  ContactRequest req,
366  ContactResultMap& res)
367  : active(&active)
368  , collision_margin_data(std::move(collision_margin_data))
369  , validator(std::move(validator))
370  , req(std::move(req))
371  , res(&res)
372 {
373 }
374 
375 ContactManagerConfig::ContactManagerConfig(double default_margin) : default_margin(default_margin) {}
376 
378 {
379  if (default_margin.has_value())
380  default_margin.value() += increment;
381 
382  if (!pair_margin_data.empty())
384 }
385 
387 {
388  if (default_margin.has_value())
389  default_margin.value() *= scale;
390 
391  if (!pair_margin_data.empty())
393 }
394 
396 {
399  throw std::runtime_error("ContactManagerConfig, pair margin override type is NONE but pair collision margins "
400  "exist!");
401 
403  throw std::runtime_error("ContactManagerConfig, acm override type is NONE but allowed collision entries exist!");
404 }
405 
407 {
408  bool ret_val = true;
409  ret_val &= (default_margin == rhs.default_margin);
411  ret_val &= (pair_margin_data == rhs.pair_margin_data);
412  ret_val &= (acm == rhs.acm);
413  ret_val &= (acm_override_type == rhs.acm_override_type);
414  ret_val &= (modify_object_enabled == rhs.modify_object_enabled);
415  return ret_val;
416 }
417 bool ContactManagerConfig::operator!=(const ContactManagerConfig& rhs) const { return !operator==(rhs); }
418 
421  double longest_valid_segment_length,
422  CollisionCheckProgramType check_program_mode)
423  : contact_request(std::move(request))
424  , type(type)
425  , longest_valid_segment_length(longest_valid_segment_length)
426  , check_program_mode(check_program_mode)
427 {
428 }
429 
431 {
432  bool ret_val = true;
433  ret_val &= (contact_request == rhs.contact_request);
434  ret_val &= (type == rhs.type);
435  ret_val &=
437  ret_val &= (check_program_mode == rhs.check_program_mode);
438  return ret_val;
439 }
440 bool CollisionCheckConfig::operator!=(const CollisionCheckConfig& rhs) const { return !operator==(rhs); }
441 
443  const Eigen::VectorXd& start_state, // NOLINT
444  const Eigen::VectorXd& end_state) // NOLINT
445  : substep(substep_number), state0(start_state), state1(end_state)
446 {
447 }
448 
449 ContactTrajectorySubstepResults::ContactTrajectorySubstepResults(int substep_number, const Eigen::VectorXd& state)
450  : substep(substep_number), state0(state), state1(state)
451 {
452 }
453 
454 int ContactTrajectorySubstepResults::numContacts() const { return static_cast<int>(contacts.size()); }
455 
457 {
459  double worst_distance = std::numeric_limits<double>::max();
460  for (const auto& collision : contacts)
461  {
462  // Check if the contact vector for this pair is empty before accessing front()
463  if (!collision.second.empty() && collision.second.front().distance < worst_distance)
464  {
465  worst_distance = collision.second.front().distance;
466  worst_collision = collision.second;
467  }
468  }
469  return worst_collision;
470 }
471 
473  const Eigen::VectorXd& start_state, // NOLINT
474  const Eigen::VectorXd& end_state, // NOLINT
475  int num_substeps)
476  : step(step_number), state0(start_state), state1(end_state), total_substeps(num_substeps)
477 {
478  substeps.resize(static_cast<std::size_t>(num_substeps));
479 }
480 
481 ContactTrajectoryStepResults::ContactTrajectoryStepResults(int step_number, const Eigen::VectorXd& state)
482  : step(step_number), state0(state), state1(state), total_substeps(2)
483 {
484  substeps.resize(static_cast<std::size_t>(2));
485 }
486 
488 {
489  total_substeps = num_substeps;
490  substeps.resize(static_cast<std::size_t>(num_substeps));
491 }
492 
493 int ContactTrajectoryStepResults::numSubsteps() const { return static_cast<int>(substeps.size()); }
494 
496 {
497  int num_contacts = 0;
498  for (const auto& substep : substeps)
499  num_contacts += substep.numContacts();
500  return num_contacts;
501 }
502 
504 {
505  ContactTrajectorySubstepResults worst_substep;
506  double worst_distance = std::numeric_limits<double>::max();
507  for (const auto& substep : substeps)
508  {
509  tesseract_collision::ContactResultVector substep_worst_collision = substep.worstCollision();
510  // Check if the returned worst collision vector is empty before accessing front()
511  if (!substep_worst_collision.empty() && substep_worst_collision.front().distance < worst_distance)
512  {
513  worst_distance = substep_worst_collision.front().distance;
514  worst_substep = substep;
515  }
516  }
517  return worst_substep;
518 }
519 
521 {
522  // Get the worst substep first
524  // Then return its worst collision, which might be empty if no collisions occurred
525  return worst_s.worstCollision();
526 }
527 
529 {
530  int most_contacts = 0; // Initialize to 0 to handle the case where all substeps have 0 contacts
531  ContactTrajectorySubstepResults most_collisions_substep; // Default constructed, substep = -1
532  for (const auto& substep : substeps)
533  {
534  int current_contacts = substep.numContacts();
535  // Only update if current_contacts is strictly greater than most_contacts
536  if (current_contacts > most_contacts)
537  {
538  most_contacts = current_contacts;
539  most_collisions_substep = substep;
540  }
541  }
542  return most_collisions_substep;
543 }
544 
545 ContactTrajectoryResults::ContactTrajectoryResults(std::vector<std::string> j_names) : joint_names(std::move(j_names))
546 {
547 }
548 
549 ContactTrajectoryResults::ContactTrajectoryResults(std::vector<std::string> j_names, int num_steps)
550  : joint_names(std::move(j_names)), total_steps(num_steps)
551 {
552  steps.resize(static_cast<std::size_t>(num_steps));
553 }
554 
556 {
557  total_steps = num_steps;
558  steps.resize(static_cast<std::size_t>(num_steps));
559 }
560 
561 int ContactTrajectoryResults::numSteps() const { return static_cast<int>(steps.size()); }
562 
564 {
565  int num_contacts = 0;
566  for (const auto& step : steps)
567  num_contacts += step.numContacts();
568  return num_contacts;
569 }
570 
572 {
573  ContactTrajectoryStepResults worst_step;
574  double worst_distance = std::numeric_limits<double>::max();
575  for (const auto& step : steps)
576  {
577  tesseract_collision::ContactResultVector step_worst_collision = step.worstCollision();
578  if (!step_worst_collision.empty() && step_worst_collision.front().distance < worst_distance)
579  {
580  worst_distance = step_worst_collision.front().distance;
581  worst_step = step;
582  }
583  }
584  return worst_step;
585 }
586 
588 {
590  return worst_collision;
591 }
592 
594 {
595  int most_contacts = 0; // Initialize to 0 to handle the case where all steps have 0 contacts
596  ContactTrajectoryStepResults most_collisions_step; // Default constructed, step = -1
597  for (const auto& step : steps)
598  {
599  int current_contacts = step.numContacts();
600  // Only update if current_contacts is strictly greater than most_contacts
601  if (current_contacts > most_contacts)
602  {
603  most_contacts = current_contacts;
604  most_collisions_step = step;
605  }
606  }
607  return most_collisions_step;
608 }
609 
611 {
612  // Possible multiple contacts for every substep
613  // For every contact need to display contact distance, link1, link2
614  // For every substep with a contact need to display substep #/total, all contacts
615  // For every step need to display joint names, state0, state1, all substeps
616  // No seperation between collision lines
617  // Dashed (---) line seperating substeps
618  // Star (***) line seperating steps
619  std::stringstream ss;
620 
621  if (numContacts() == 0)
622  {
623  ss << "No contacts detected\n";
624  return ss;
625  }
626 
627  int step_details_width = 0;
628  int substep_details_width = 0;
629 
630  // First need to determine the width of every column, should be a space on either side of each
631  // Step is displayed as (step)/(total number of steps), example: 2/23
632  std::string step_title = "STEP";
633  int longest_steps_width = 2 + static_cast<int>(step_title.size());
634  int number_steps_digits = static_cast<int>(std::log10(steps.back().step)) + 1;
635  // *2 for either side, plus 1 for '/', plus 2 for spaces
636  int width_steps_display = (number_steps_digits * 2) + 3;
637  longest_steps_width = std::max(width_steps_display, longest_steps_width);
638 
639  step_details_width += longest_steps_width;
640 
641  // Joint Names can vary widely
642  std::string joint_name_title = "JOINT NAMES";
643  int longest_joint_name_width = static_cast<int>(joint_name_title.size()) + 2;
644  for (const auto& name : joint_names)
645  longest_joint_name_width = std::max(static_cast<int>(name.size()) + 2, longest_joint_name_width);
646 
647  step_details_width += longest_joint_name_width;
648 
649  // State0 and State1 we will truncate all values to be to 4 decimals of precision,
650  // important to add 1 to the length of negative values to account for the sign
651  std::string state0_title = "STATE0";
652  std::string state1_title = "STATE1";
653  int longest_state0_width = 9; // Default negative sign, number, decimal point, four places, plus space either side
654  int longest_state1_width = 9;
655  for (const auto& step : steps)
656  {
657  for (int i = 0; i < static_cast<int>(step.state0.size()); i++)
658  {
659  double state0_value = step.state0(i);
660  if (state0_value < 0)
661  {
662  state0_value *= -1;
663  }
664  int state0_number_digits_left_decimal = static_cast<int>(std::log10(state0_value)) + 1;
665  // + 4 after decimal + 2 for spaces either side + 1 for decimal
666  longest_state0_width = std::max(state0_number_digits_left_decimal + 7, longest_state0_width);
667 
668  double state1_value = step.state1(i);
669  if (state1_value < 0)
670  {
671  state1_value *= -1;
672  }
673  int state1_number_digits_left_decimal = static_cast<int>(std::log10(state1_value)) + 1;
674  // + 4 after decimal + 2 for spaces either side + 1 for decimal
675  longest_state1_width = std::max(state1_number_digits_left_decimal + 7, longest_state1_width);
676  }
677  }
678 
679  step_details_width += longest_state0_width;
680  step_details_width += longest_state1_width;
681 
682  // Substep will almost certainly be the width of substep, but still check
683  std::string substep_title = "SUBSTEP";
684  int longest_substep_width = 2 + static_cast<int>(substep_title.size());
685  for (const auto& step : steps)
686  {
687  // Check to make sure there are value, could be empty if checking for first collision
688  if (step.numSubsteps() == 0)
689  continue;
690 
691  // Substep is displayed as (substep)/(total number of substeps), example: 5/7
692  // so length will be 2*(max substep width) + 1
693  int number_digits = static_cast<int>(std::log10(step.substeps.size())) + 1;
694  int width = (2 * number_digits) + 3;
695  longest_substep_width = std::max(width, longest_substep_width);
696  }
697 
698  substep_details_width += longest_substep_width;
699 
700  // Link1 and Link2 will each be the width of the widest link name in that calumn
701  std::string link1_title = "LINK1";
702  std::string link2_title = "LINK2";
703  int longest_link1_width = static_cast<int>(link1_title.size()) + 2;
704  int longest_link2_width = static_cast<int>(link2_title.size()) + 2;
705  for (const auto& step : steps)
706  {
707  for (const auto& substep : step.substeps)
708  {
709  if (!substep.contacts.empty())
710  {
711  for (const auto& collision : substep.contacts)
712  {
713  if (collision.second.empty())
714  continue;
715  std::string link1_name = collision.second.front().link_names[0];
716  longest_link1_width = std::max(static_cast<int>(link1_name.size()) + 2, longest_link1_width);
717 
718  std::string link2_name = collision.second.front().link_names[1];
719  longest_link2_width = std::max(static_cast<int>(link2_name.size()) + 2, longest_link2_width);
720  }
721  }
722  }
723  }
724 
725  substep_details_width += longest_link1_width;
726  substep_details_width += longest_link2_width;
727 
728  // Distance will also be truncated at 4 decimal points of precision, shouldn't need more
729  // than 0.1 mm of precision
730  // Assumming "DISTANCE" is the widest text, also doesn't matter because this is the last column
731  std::string distance_title = "DISTANCE";
732  int longest_distance_width = static_cast<int>(distance_title.size()) + 2;
733 
734  substep_details_width += longest_distance_width;
735 
736  // Construct strings for displaying info on a new state and new substate
737  std::string new_step_string(static_cast<std::size_t>(step_details_width), '*');
738  new_step_string += "|";
739  new_step_string += std::string(static_cast<std::size_t>(substep_details_width), '*');
740  std::string new_substep_string(static_cast<std::size_t>(substep_details_width), '-');
741 
742  // Start making the table
743  // Start on new line to avoid offset by anythnig on previous line
744  ss << "\n";
745  // Make the header
746  ss << std::setw(longest_steps_width) << step_title << std::setw(longest_joint_name_width) << joint_name_title
747  << std::setw(longest_state0_width) << state0_title << std::setw(longest_state1_width) << state1_title << "|"
748  << std::setw(longest_substep_width) << substep_title << std::setw(longest_link1_width) << link1_title
749  << std::setw(longest_link2_width) << link2_title << std::setw(longest_distance_width) << distance_title << "\n";
750 
751  ss << new_step_string << "\n";
752 
753  for (const auto& step : steps)
754  {
755  // Check if there are contacts in this step
756  if (step.numContacts() == 0)
757  continue;
758 
759  // Create string for stating the step number, repeated on every line of this step. example: 2/23
760  std::string step_number_string = std::to_string(step.step) + "/" + std::to_string(total_steps);
761  int line_number = 0;
762  for (const auto& substep : step.substeps)
763  {
764  if (substep.contacts.empty())
765  continue;
766 
767  // Check if there are contacts in this substep
768  if (substep.numContacts() == 0)
769  continue;
770 
771  // Create string for stating the substep number, repeated on every line of this substep
772  std::string substep_string = std::to_string(substep.substep) + "/" + std::to_string(step.total_substeps);
773 
774  // Iterate over every collision in this substep
775  for (const auto& collision : substep.contacts)
776  {
777  if (collision.second.empty())
778  continue;
779  // Write the current substep string
780  ss << std::setw(longest_steps_width) << step_number_string;
781 
782  // Check if we still need to be adding to the joint state information
783  if (line_number < static_cast<int>(joint_names.size()))
784  {
785  ss << std::setprecision(4) << std::fixed;
786  ss << std::setw(longest_joint_name_width) << joint_names[static_cast<std::size_t>(line_number)];
787  ss << std::setw(longest_state0_width) << step.state0(line_number);
788  ss << std::setw(longest_state1_width) << step.state1(line_number);
789  }
790  else
791  {
792  // Add blank spaces once done writing joint states
793  ss << std::setw(longest_joint_name_width) << " " << std::setw(longest_state0_width) << " "
794  << std::setw(longest_state1_width) << " ";
795  }
796  // Add vertical bar
797  ss << "|";
798 
799  // Add specific contact information
800  ss << std::setw(longest_substep_width) << substep_string;
801  ss << std::setw(longest_link1_width) << collision.second.front().link_names[0];
802  ss << std::setw(longest_link2_width) << collision.second.front().link_names[1];
803  ss << std::setw(longest_distance_width) << collision.second.front().distance;
804  ss << "\n";
805  line_number++;
806  }
807 
808  // Make new line for seperator between substates
809  ss << std::setw(longest_steps_width) << step_number_string;
810  if (line_number < static_cast<int>(joint_names.size()))
811  {
812  ss << std::setw(longest_joint_name_width) << joint_names[static_cast<std::size_t>(line_number)];
813  ss << std::setw(longest_state0_width) << step.state0(line_number);
814  ss << std::setw(longest_state1_width) << step.state1(line_number);
815  }
816  else
817  {
818  ss << std::setw(longest_joint_name_width) << " " << std::setw(longest_state0_width) << " "
819  << std::setw(longest_state1_width) << " ";
820  }
821  ss << "|";
822  ss << new_substep_string;
823  ss << "\n";
824  line_number++;
825  }
826 
827  // Finish writing joint state if necessary
828  while (line_number < static_cast<int>(joint_names.size()))
829  {
830  ss << std::setw(longest_steps_width) << step_number_string;
831  ss << std::setw(longest_joint_name_width) << joint_names[static_cast<std::size_t>(line_number)];
832  ss << std::setw(longest_state0_width) << step.state0(line_number);
833  ss << std::setw(longest_state1_width) << step.state1(line_number);
834  ss << "|\n";
835  line_number++;
836  }
837  ss << new_step_string << "\n";
838  }
839  return ss;
840 }
841 
843 {
844  // Create a map to assign an index to each unique link name
845  std::unordered_map<std::string, std::size_t> link_index_map;
846  std::size_t index = 0;
847  for (const auto& step : steps)
848  {
849  for (const auto& substep : step.substeps)
850  {
851  for (const auto& contact_pair : substep.contacts.getContainer())
852  {
853  const auto& link_pair = contact_pair.first;
854  if (link_index_map.find(link_pair.first) == link_index_map.end())
855  {
856  link_index_map[link_pair.first] = index++;
857  }
858  if (link_index_map.find(link_pair.second) == link_index_map.end())
859  {
860  link_index_map[link_pair.second] = index++;
861  }
862  }
863  }
864  }
865 
866  // Create a matrix to store the collision counts
867  std::size_t size = link_index_map.size();
868  std::vector<std::vector<int>> collision_matrix(size, std::vector<int>(size, 0));
869 
870  // Populate the matrix with collision counts
871  for (const auto& step : steps)
872  {
873  for (const auto& substep : step.substeps)
874  {
875  for (const auto& contact_pair : substep.contacts.getContainer())
876  {
877  const auto& link_pair = contact_pair.first;
878  std::size_t row = link_index_map[link_pair.first];
879  std::size_t col = link_index_map[link_pair.second];
880  collision_matrix[row][col]++;
881  collision_matrix[col][row]++;
882  }
883  }
884  }
885 
886  // Create a string stream to store the matrix
887  std::stringstream ss;
888 
889  if (link_index_map.empty())
890  {
891  ss << "No contacts detected\n";
892  return ss;
893  }
894 
895  // Determine the maximum width for the link name column
896  std::size_t max_link_name_length = 0;
897  for (const auto& entry : link_index_map)
898  max_link_name_length = std::max(entry.first.size(), max_link_name_length);
899 
900  // Adjust the width to have some extra space after the longest link name
901  const int column_width = static_cast<int>(max_link_name_length) + 2;
902 
903  // Prepare the header row
904  ss << std::setw(column_width + 5) << " "
905  << "|";
906  for (std::size_t i = 0; i < link_index_map.size(); ++i)
907  {
908  ss << std::setw(5) << i << "|";
909  }
910  ss << "\n";
911 
912  // Prepare the separator row
913  ss << std::setw(column_width + 5) << " "
914  << "|";
915  for (std::size_t i = 0; i < link_index_map.size(); ++i)
916  {
917  ss << std::setw(5) << "-----"
918  << "|";
919  }
920  ss << "\n";
921 
922  // Prepare the data rows
923  std::vector<std::string> link_names(link_index_map.size());
924  for (const auto& entry : link_index_map)
925  {
926  link_names[entry.second] = entry.first;
927  }
928 
929  for (std::size_t i = 0; i < link_names.size(); ++i)
930  {
931  ss << std::setw(5) << i << std::setw(column_width) << link_names[i] << "|";
932  for (std::size_t j = 0; j < link_names.size(); ++j)
933  {
934  if (i == j)
935  break;
936 
937  ss << std::setw(5) << collision_matrix[i][j] << "|";
938  }
939  ss << "\n";
940  }
941 
942  return ss;
943 }
944 
945 } // namespace tesseract_collision
tesseract_collision::ContactResultMap::empty
bool empty() const
Check if results are present.
Definition: types.cpp:229
tesseract_collision::ContactResultMap::end
ConstIteratorType end() const
returns an iterator to the end
Definition: types.cpp:260
tesseract_collision::ContactManagerConfig::validate
void validate() const
Check for errors and throw exception if they exist.
Definition: types.cpp:395
tesseract_collision::CollisionCheckConfig::operator==
bool operator==(const CollisionCheckConfig &rhs) const
Definition: types.cpp:430
tesseract_collision::ContactTrajectorySubstepResults::numContacts
int numContacts() const
Definition: types.cpp:454
tesseract_collision::ContactManagerConfig
Contains parameters used to configure a contact manager before a series of contact checks.
Definition: types.h:420
tesseract_collision::ContactRequest::calculate_distance
bool calculate_distance
This enables the calculation of distance data if two objects are within the contact threshold.
Definition: types.h:309
tesseract_collision::ContactResult::cc_time
std::array< double, 2 > cc_time
This is between 0 and 1 indicating the point of contact.
Definition: types.h:111
tesseract_collision::ContactRequest::operator==
bool operator==(const ContactRequest &rhs) const
Definition: types.cpp:91
tesseract_collision::ContactTrajectoryStepResults::total_substeps
int total_substeps
Definition: types.h:555
tesseract_collision::ContactTrajectoryResults::resize
void resize(int num_steps)
Definition: types.cpp:555
tesseract_common::AllowedCollisionMatrix::getAllAllowedCollisions
const AllowedCollisionEntries & getAllAllowedCollisions() const
types.h
Tesseracts Collision Forward Declarations.
tesseract_collision::ContactResultMap::count_
long count_
Definition: types.h:296
tesseract_collision::ContactResultMap::setContactResult
ContactResult & setContactResult(const KeyType &key, ContactResult result)
Set contact results for the provided key.
Definition: types.cpp:122
tesseract_collision::ContactResult::shape_id
std::array< int, 2 > shape_id
The two shapes that are in contact. Each link can be made up of multiple shapes.
Definition: types.h:94
tesseract_collision::ContactResultMap::addInterpolatedCollisionResults
void addInterpolatedCollisionResults(ContactResultMap &sub_segment_results, long sub_segment_index, long sub_segment_last_index, const std::vector< std::string > &active_link_names, double segment_dt, bool discrete, const ContactResultMap::FilterFn &filter=nullptr)
This processes interpolated contact results by updating the cc_time and cc_type and then adds the res...
Definition: types.cpp:146
tesseract_collision::CollisionCheckConfig::CollisionCheckConfig
CollisionCheckConfig(ContactRequest request=ContactRequest(), CollisionEvaluatorType type=CollisionEvaluatorType::DISCRETE, double longest_valid_segment_length=0.005, CollisionCheckProgramType check_program_mode=CollisionCheckProgramType::ALL)
Definition: types.cpp:419
tesseract_common::CollisionMarginPairData::getCollisionMargins
const PairsCollisionMarginData & getCollisionMargins() const
tesseract_collision::ContactTrajectoryStepResults::mostCollisionsSubstep
ContactTrajectorySubstepResults mostCollisionsSubstep() const
Definition: types.cpp:528
tesseract_collision::ContactRequest::ContactRequest
ContactRequest(ContactTestType type=ContactTestType::ALL)
Definition: types.cpp:89
tesseract_collision::ContactTrajectoryResults::mostCollisionsStep
ContactTrajectoryStepResults mostCollisionsStep() const
Definition: types.cpp:593
tesseract_collision::ContactResultMap::size
std::size_t size() const
Get the size of the map.
Definition: types.cpp:214
tesseract_common::almostEqualRelativeAndAbs
bool almostEqualRelativeAndAbs(const Eigen::Ref< const Eigen::VectorXd > &v1, const Eigen::Ref< const Eigen::VectorXd > &v2, const Eigen::Ref< const Eigen::VectorXd > &max_diff, const Eigen::Ref< const Eigen::VectorXd > &max_rel_diff)
tesseract_collision::ContactResultMap::addContactResult
ContactResult & addContactResult(const KeyType &key, ContactResult result)
Add contact results for the provided key.
Definition: types.cpp:103
tesseract_collision::ContactResultMap::getSummary
std::string getSummary() const
Get a brief summary of the most frequently colliding link pair.
Definition: types.cpp:325
tesseract_common::CollisionMarginPairData::empty
bool empty() const
tesseract_collision::ContactRequest::type
ContactTestType type
This controls the exit condition for the contact test type.
Definition: types.h:303
tesseract_collision::ContactTrajectoryResults::numContacts
int numContacts() const
Definition: types.cpp:563
tesseract_collision::ContactTrajectoryResults::collisionFrequencyPerLink
std::stringstream collisionFrequencyPerLink() const
Definition: types.cpp:842
tesseract_collision::ContactResult::normal
Eigen::Vector3d normal
The normal vector to move the two objects out of contact in world coordinates.
Definition: types.h:109
tesseract_collision::ContinuousCollisionType::CCType_Time1
@ CCType_Time1
tesseract_collision::ContactManagerConfig::incrementMargins
void incrementMargins(double increment)
Increment all margins by input amount. Useful for inflating or reducing margins.
Definition: types.cpp:377
tesseract_collision::ContactRequest::operator!=
bool operator!=(const ContactRequest &rhs) const
Definition: types.cpp:101
TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
#define TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
tesseract_collision::ContactResultVector
tesseract_common::AlignedVector< ContactResult > ContactResultVector
Definition: types.h:136
tesseract_collision::ContactTrajectoryStepResults::substeps
std::vector< ContactTrajectorySubstepResults > substeps
Definition: types.h:551
tesseract_collision::ContactTestData::ContactTestData
EIGEN_MAKE_ALIGNED_OPERATOR_NEW ContactTestData()=default
tesseract_collision::ContactResultMap::clear
void clear()
This is a consurvative clear.
Definition: types.cpp:231
tesseract_collision::ContactTrajectoryStepResults::numContacts
int numContacts() const
Definition: types.cpp:495
tesseract_collision::ContactTrajectoryResults::total_steps
int total_steps
Definition: types.h:593
tesseract_collision::ContactRequest::contact_limit
long contact_limit
This is used if the ContactTestType is set to LIMITED, where the test will exit when number of contac...
Definition: types.h:313
tesseract_collision::ContactTrajectoryResults::worstCollision
tesseract_collision::ContactResultVector worstCollision() const
Definition: types.cpp:587
tesseract_common::CollisionMarginData
tesseract_collision::ContactResultMap::FilterFn
std::function< void(PairType &)> FilterFn
Definition: types.h:165
tesseract_collision::ContactResultMap::filter
void filter(const FilterFn &filter)
Filter out results using the provided function.
Definition: types.cpp:306
tesseract_collision::CollisionCheckConfig::type
CollisionEvaluatorType type
Specifies the type of collision check to be performed. Default: DISCRETE.
Definition: types.h:480
tesseract_collision::ContactResultMap::getContainer
const ContainerType & getContainer() const
Get the underlying container.
Definition: types.cpp:256
tesseract_collision::ContactManagerConfig::modify_object_enabled
std::unordered_map< std::string, bool > modify_object_enabled
Each key is an object name. Objects will be enabled/disabled based on the value. Objects that aren't ...
Definition: types.h:440
tesseract_collision::ContactResultMap::flattenMoveResults
void flattenMoveResults(ContactResultVector &v)
Definition: types.cpp:270
tesseract_collision::ContactManagerConfig::operator!=
bool operator!=(const ContactManagerConfig &rhs) const
Definition: types.cpp:417
tesseract_collision::CollisionCheckConfig::check_program_mode
CollisionCheckProgramType check_program_mode
Secifies the mode used when collision checking program/trajectory. Default: ALL.
Definition: types.h:486
tesseract_collision::ContinuousCollisionType::CCType_Between
@ CCType_Between
tesseract_collision::ContactResultMap::at
const ContactResultVector & at(const KeyType &key) const
access specified element with bounds checking
Definition: types.cpp:266
tesseract_collision::ContactResultMap::flattenWrapperResults
void flattenWrapperResults(std::vector< std::reference_wrapper< ContactResult >> &v)
Definition: types.cpp:290
tesseract_collision::ContactTrajectoryStepResults::ContactTrajectoryStepResults
EIGEN_MAKE_ALIGNED_OPERATOR_NEW ContactTrajectoryStepResults()=default
tesseract_collision::ContactResultMap::ConstIteratorType
typename tesseract_common::AlignedMap< KeyType, MappedType >::const_iterator ConstIteratorType
Definition: types.h:163
tesseract_collision::ContactManagerConfig::scaleMargins
void scaleMargins(double scale)
Scale all margins by input value.
Definition: types.cpp:386
name
std::string name
tesseract_collision::ContactResult::subshape_id
std::array< int, 2 > subshape_id
Some shapes like octomap and mesh have subshape (boxes and triangles)
Definition: types.h:96
tesseract_collision::ContactResult::operator!=
bool operator!=(const ContactResult &rhs) const
Definition: types.cpp:87
tesseract_collision::ContactManagerConfig::ContactManagerConfig
ContactManagerConfig()=default
tesseract_collision::ContactResultMap
This structure hold contact results for link pairs.
Definition: types.h:155
tesseract_collision::ContactTrajectoryStepResults::resize
void resize(int num_substeps)
Definition: types.cpp:487
tesseract_collision::ContactResultMap::release
void release()
Fully clear all internal data.
Definition: types.cpp:250
tesseract_collision::ContactTrajectoryStepResults::worstCollision
tesseract_collision::ContactResultVector worstCollision() const
Definition: types.cpp:520
tesseract_collision::ContactResultMap::ContainerType
tesseract_common::AlignedMap< KeyType, MappedType > ContainerType
Definition: types.h:161
tesseract_collision::CollisionCheckConfig::contact_request
ContactRequest contact_request
ContactRequest that will be used for this check. Default test type: ALL.
Definition: types.h:477
tesseract_collision::ContactManagerConfig::default_margin
std::optional< double > default_margin
override the default contact margin
Definition: types.h:426
tesseract_collision::ContactTrajectorySubstepResults
The ContactTrajectorySubstepResults struct is the lowest level struct for tracking contacts in a traj...
Definition: types.h:497
tesseract_collision::CollisionCheckConfig
This is a high level structure containing common information that collision checking utilities need....
Definition: types.h:469
tesseract_collision::ContactTrajectoryResults::ContactTrajectoryResults
EIGEN_MAKE_ALIGNED_OPERATOR_NEW ContactTrajectoryResults()=default
tesseract_collision::ContactResultMap::data_
ContainerType data_
Definition: types.h:295
tesseract_collision::ContinuousCollisionType::CCType_None
@ CCType_None
tesseract_collision::ContactTrajectoryStepResults::numSubsteps
int numSubsteps() const
Definition: types.cpp:493
tesseract_collision::ContactTrajectoryResults::worstStep
ContactTrajectoryStepResults worstStep() const
Definition: types.cpp:571
tesseract_collision::ContactTrajectorySubstepResults::contacts
tesseract_collision::ContactResultMap contacts
Definition: types.h:513
tesseract_collision::ContactResultMap::KeyType
std::pair< std::string, std::string > KeyType
Definition: types.h:159
tesseract_collision::ContactRequest::is_valid
std::shared_ptr< const ContactResultValidator > is_valid
This provides a user defined function approve/reject contact results.
Definition: types.h:316
tesseract_collision::ContactResult::type_id
std::array< int, 2 > type_id
A user defined type id that is added to the contact shapes.
Definition: types.h:90
r
S r
tesseract_collision::ContactResultMap::operator!=
bool operator!=(const ContactResultMap &rhs) const
Definition: types.cpp:323
TESSERACT_COMMON_IGNORE_WARNINGS_POP
Definition: create_convex_hull.cpp:37
tesseract_collision::ContactResultMap::operator==
bool operator==(const ContactResultMap &rhs) const
Definition: types.cpp:319
tesseract_collision::ContactResult::clear
void clear()
reset to default values
Definition: types.cpp:36
tesseract_common::CollisionMarginPairData::incrementMargins
void incrementMargins(double increment)
contact_result_validator.h
Contact result validator.
tesseract_collision::ContinuousCollisionType::CCType_Time0
@ CCType_Time0
tesseract_collision::CollisionEvaluatorType
CollisionEvaluatorType
High level descriptor used in planners and utilities to specify what kind of collision check is desir...
Definition: types.h:366
tesseract_common::CollisionMarginPairData::scaleMargins
void scaleMargins(double scale)
tesseract_collision::ContactTrajectoryResults::trajectoryCollisionResultsTable
std::stringstream trajectoryCollisionResultsTable() const
Definition: types.cpp:610
tesseract_collision::ContactManagerConfig::pair_margin_override_type
CollisionMarginPairOverrideType pair_margin_override_type
Identify how the collision margin pair data should be applied to the contact manager.
Definition: types.h:429
tesseract_collision::ContactTrajectoryResults::numSteps
int numSteps() const
Definition: types.cpp:561
tesseract_collision::ContactResultMap::cend
ConstIteratorType cend() const
returns an iterator to the end
Definition: types.cpp:264
tesseract_collision::CollisionCheckProgramType
CollisionCheckProgramType
The mode used to check program.
Definition: types.h:381
tesseract_collision::ContactResultMap::find
ConstIteratorType find(const KeyType &key) const
Definition: types.cpp:268
tesseract_collision::ContactResult::distance
EIGEN_MAKE_ALIGNED_OPERATOR_NEW double distance
The distance between two links.
Definition: types.h:88
tesseract_collision::ContactTestType
ContactTestType
Definition: types.h:66
type
type
tesseract_collision::ContactResult::cc_transform
std::array< Eigen::Isometry3d, 2 > cc_transform
The transform of link in world coordinates at its desired final location. Note: This is not the locat...
Definition: types.h:120
tesseract_collision::ContactResultMap::shrinkToFit
void shrinkToFit()
Remove map entries with no contact results.
Definition: types.cpp:243
tesseract_collision::ContactManagerConfig::operator==
bool operator==(const ContactManagerConfig &rhs) const
Definition: types.cpp:406
tesseract_collision::ContactResultMap::count
long count() const
Get the total number of contact results storted.
Definition: types.cpp:212
tesseract_collision::ContactResultMap::cbegin
ConstIteratorType cbegin() const
returns an iterator to the beginning
Definition: types.cpp:262
tesseract_common::makeOrderedLinkPair
LinkNamesPair makeOrderedLinkPair(const std::string &link_name1, const std::string &link_name2)
tesseract_collision::ContactResult::transform
std::array< Eigen::Isometry3d, 2 > transform
The transform of link in world coordinates.
Definition: types.h:102
tesseract_collision::ContactTrajectoryStepResults
The ContactTrajectoryStepResults struct is the second level struct for tracking contacts in a traject...
Definition: types.h:524
tesseract_collision::ContactTrajectoryResults::joint_names
std::vector< std::string > joint_names
Definition: types.h:592
tesseract_collision::ContactTrajectoryStepResults::worstSubstep
ContactTrajectorySubstepResults worstSubstep() const
Definition: types.cpp:503
tesseract_collision::ContactTrajectorySubstepResults::ContactTrajectorySubstepResults
EIGEN_MAKE_ALIGNED_OPERATOR_NEW ContactTrajectorySubstepResults()=default
tesseract_collision::ContactResult::single_contact_point
bool single_contact_point
Some collision checkers only provide a single contact point for a given pair. This is used to indicat...
Definition: types.h:125
tesseract_collision::ContactManagerConfig::pair_margin_data
CollisionMarginPairData pair_margin_data
Stores collision margin pair data.
Definition: types.h:431
tesseract_collision::ContactResult::operator==
bool operator==(const ContactResult &rhs) const
Definition: types.cpp:63
tesseract_collision::ContactResult::nearest_points
std::array< Eigen::Vector3d, 2 > nearest_points
The nearest point on both links in world coordinates.
Definition: types.h:98
tesseract_collision
Definition: bullet_cast_bvh_manager.h:48
tesseract_collision::ContactResultMap::begin
ConstIteratorType begin() const
returns an iterator to the beginning
Definition: types.cpp:258
tesseract_collision::ContactManagerConfig::acm
tesseract_common::AllowedCollisionMatrix acm
Additional AllowedCollisionMatrix to consider for this collision check.
Definition: types.h:434
tesseract_collision::ContactResult::nearest_points_local
std::array< Eigen::Vector3d, 2 > nearest_points_local
The nearest point on both links in local(link) coordinates.
Definition: types.h:100
tesseract_collision::ACMOverrideType::NONE
@ NONE
Do not apply AllowedCollisionMatrix.
tesseract_collision::ContactResultMap::flattenCopyResults
void flattenCopyResults(ContactResultVector &v) const
Definition: types.cpp:282
tesseract_collision::ContactTrajectoryResults::steps
std::vector< ContactTrajectoryStepResults > steps
Definition: types.h:591
tesseract_collision::ContactResultMap::MappedType
ContactResultVector MappedType
Definition: types.h:160
tesseract_collision::ContactResult::link_names
std::array< std::string, 2 > link_names
The two links that are in contact.
Definition: types.h:92
tesseract_collision::ContactResult
Definition: types.h:81
tesseract_collision::CollisionCheckConfig::operator!=
bool operator!=(const CollisionCheckConfig &rhs) const
Definition: types.cpp:440
tesseract_collision::ContactRequest
The ContactRequest struct.
Definition: types.h:300
tesseract_collision::ContactResult::cc_type
std::array< ContinuousCollisionType, 2 > cc_type
The type of continuous contact.
Definition: types.h:113
tesseract_collision::ContactManagerConfig::acm_override_type
ACMOverrideType acm_override_type
Specifies how to combine the ContactAllowedValidator from acm with the one preset in the contact mana...
Definition: types.h:436
tesseract_collision::ContactRequest::calculate_penetration
bool calculate_penetration
This enables the calculation of penetration contact data if two objects are in collision.
Definition: types.h:306
tesseract_collision::CollisionCheckConfig::longest_valid_segment_length
double longest_valid_segment_length
Longest valid segment to use if type supports lvs. Default: 0.005.
Definition: types.h:483
tesseract_collision::ContactTrajectorySubstepResults::worstCollision
tesseract_collision::ContactResultVector worstCollision() const
Definition: types.cpp:456
tesseract_common::CollisionMarginPairOverrideType::NONE
@ NONE


tesseract_collision
Author(s): Levi Armstrong
autogenerated on Sun May 18 2025 03:01:52