Skip to content

Commit 53ad1b4

Browse files
authored
Implement a condensed summary for ContactTrajectoryResults (#1205)
1 parent 4e483d6 commit 53ad1b4

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

tesseract_collision/core/include/tesseract_collision/core/types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,8 @@ struct ContactTrajectoryResults
632632

633633
std::stringstream collisionFrequencyPerLink() const;
634634

635+
std::stringstream condensedSummary() const;
636+
635637
std::vector<ContactTrajectoryStepResults> steps;
636638
std::vector<std::string> joint_names;
637639
int total_steps = 0;

tesseract_collision/core/src/types.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,4 +1023,62 @@ std::stringstream ContactTrajectoryResults::collisionFrequencyPerLink() const
10231023
return ss;
10241024
}
10251025

1026+
std::stringstream ContactTrajectoryResults::condensedSummary() const
1027+
{
1028+
std::stringstream ss;
1029+
1030+
if (numContacts() == 0)
1031+
{
1032+
ss << "No contacts detected\n";
1033+
return ss;
1034+
}
1035+
1036+
ss << "Contact(s) found: \n";
1037+
ss << "Format: Step: [link_a, link_b] @ distance\n";
1038+
1039+
// Iterate through each step to find the first collision per step
1040+
for (const auto& step : steps)
1041+
{
1042+
if (step.numContacts() == 0)
1043+
continue;
1044+
1045+
// Find the first collision in this step
1046+
bool found_first_collision = false;
1047+
for (const auto& substep : step.substeps)
1048+
{
1049+
if (substep.contacts.empty() || substep.numContacts() == 0)
1050+
continue;
1051+
1052+
// Get the first collision pair from this substep
1053+
for (const auto& collision_pair : substep.contacts.getContainer())
1054+
{
1055+
if (collision_pair.second.empty())
1056+
continue;
1057+
1058+
// Calculate the step with substep decimal
1059+
auto step_with_substep = static_cast<double>(step.step);
1060+
if (step.total_substeps > 0)
1061+
{
1062+
step_with_substep += static_cast<double>(substep.substep) / static_cast<double>(step.total_substeps);
1063+
}
1064+
1065+
// Get the first contact result from this collision pair
1066+
const auto& first_contact = collision_pair.second.front();
1067+
1068+
// Format: "14.4: [link_a, link_b]->0.001"
1069+
ss << "Step " << std::fixed << std::setprecision(1) << step_with_substep << ": [" << first_contact.link_names[0]
1070+
<< ", " << first_contact.link_names[1] << "] @ " << std::setprecision(4) << first_contact.distance << "\n";
1071+
1072+
found_first_collision = true;
1073+
break;
1074+
}
1075+
1076+
if (found_first_collision)
1077+
break;
1078+
}
1079+
}
1080+
1081+
return ss;
1082+
}
1083+
10261084
} // namespace tesseract_collision

tesseract_collision/test/collision_core_unit.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,23 @@ TEST(TesseractCoreUnit, ContactTrajectoryResultsUnit) // NOLINT
15331533

15341534
EXPECT_TRUE(static_cast<bool>(results));
15351535
EXPECT_FALSE(freq_ss.str().find("No contacts detected") != std::string::npos);
1536+
1537+
// Test condensed summary method
1538+
EXPECT_NO_THROW(results.condensedSummary());
1539+
1540+
std::stringstream condensed_ss = results.condensedSummary();
1541+
EXPECT_FALSE(condensed_ss.str().empty());
1542+
EXPECT_FALSE(condensed_ss.str().find("No contacts detected") != std::string::npos);
1543+
1544+
// Check that the condensed summary contains expected format: "step.substep: [link1, link2]->distance"
1545+
std::string condensed_output = condensed_ss.str();
1546+
std::cout << "Condensed Summary Output:\n" << condensed_output;
1547+
1548+
// Should contain "0.0: [link1, link2]" for first collision at step 0, substep 0
1549+
EXPECT_TRUE(condensed_output.find("0.0: [link1, link2]") != std::string::npos);
1550+
1551+
// Should contain "1.3: [link3, link4]" for first collision at step 1, substep 1 (1/3 = 0.3, so 1.3)
1552+
EXPECT_TRUE(condensed_output.find("1.3: [link3, link4]") != std::string::npos);
15361553
}
15371554

15381555
// Test with no contacts
@@ -1564,6 +1581,13 @@ TEST(TesseractCoreUnit, ContactTrajectoryResultsUnit) // NOLINT
15641581
EXPECT_FALSE(freq_ss.str().empty());
15651582
EXPECT_TRUE(freq_ss.str().find("No contacts detected") != std::string::npos);
15661583

1584+
// Test condensed summary method with no contacts
1585+
EXPECT_NO_THROW(results.condensedSummary());
1586+
1587+
std::stringstream condensed_ss = results.condensedSummary();
1588+
EXPECT_FALSE(condensed_ss.str().empty());
1589+
EXPECT_TRUE(condensed_ss.str().find("No contacts detected") != std::string::npos);
1590+
15671591
EXPECT_FALSE(static_cast<bool>(results));
15681592
}
15691593

0 commit comments

Comments
 (0)