Skip to content

Commit c95d4e9

Browse files
committed
[parsing] Add a very bad mesh test for mujoco parser
This tests the error path in the parser when even falling back to convex hull can't save us. Fix one control flow path bug in the parser found by this new test.
1 parent 5dc9745 commit c95d4e9

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

multibody/parsing/detail_mujoco_parser.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,7 @@ class MujocoParser {
984984
if (!M_GGo_G.IsPhysicallyValid()) {
985985
Error(*node, fmt::format("geom {} {}", geom.name,
986986
M_GGo_G.CriticizeNotPhysicallyValid()));
987+
return geom;
987988
}
988989

989990
// Shift spatial inertia from Go to Bo and express it in the B frame.

multibody/parsing/test/detail_mujoco_parser_test.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,41 @@ TEST_F(MujocoParserTest, BadMeshSpatialInertiaFallback) {
772772
// that we're using it (and not choking).
773773
}
774774

775+
// Some meshes are so broken that even falling back to a convex hull can't save
776+
// us. Verify we get a useful error message.
777+
TEST_F(MujocoParserTest, BadMeshSpatialInertiaTotalFail) {
778+
// This obj is known to produce a negative volume in CalcSpatialInertia().
779+
const RlocationOrError rlocation = FindRunfile(
780+
"drake/multibody/parsing/test/neg_volume.obj");
781+
ASSERT_EQ(rlocation.error, "");
782+
const geometry::Mesh bad_mesh(rlocation.abspath, 1.0);
783+
784+
// We know the spatial inertia is bad because CalcSpatialInertia()
785+
// throws. Keep this confirmation that the mesh in question truly is **bad**.
786+
DRAKE_EXPECT_THROWS_MESSAGE(CalcSpatialInertia(bad_mesh, 1.0),
787+
".*volume.*is -1.*");
788+
789+
std::string xml = fmt::format(R"""(
790+
<mujoco model="test">
791+
<asset>
792+
<mesh name="box" file="{}"/> </asset>
793+
<worldbody>
794+
<body name="body1">
795+
<geom name="box_geom" type="mesh" mesh="box"/>
796+
</body>
797+
</worldbody>
798+
</mujoco>
799+
)""", rlocation.abspath);
800+
801+
EXPECT_NO_THROW(AddModelFromString(xml, "test"));
802+
EXPECT_THAT(TakeWarning(), MatchesRegex(".*volume.*is -1.*"));
803+
EXPECT_THAT(TakeWarning(), MatchesRegex(".*fallback.*"));
804+
// Note: These errors are reported as a result of attempted fallback to a
805+
// convex hull.
806+
EXPECT_THAT(TakeError(), MatchesRegex(".*even.*convex hull.*"));
807+
EXPECT_THAT(TakeError(), MatchesRegex(".*IsPhysicallyValid.*"));
808+
}
809+
775810
TEST_F(MujocoParserTest, MeshFileRelativePathFromFile) {
776811
const std::string file = FindResourceOrThrow(
777812
"drake/multibody/parsing/test/box_package/mjcfs/box.xml");

multibody/parsing/test/neg_volume.obj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# An adversarially bad mesh that produces a negative volume in
2+
# CalcSpatialInertia(). The single triangle has an implied normal pointing
3+
# toward the origin.
4+
5+
v 1 0 0
6+
v 1 2 0
7+
v 1 0 3
8+
f 3 2 1

0 commit comments

Comments
 (0)