From 3e1dffc286deb5c3578e8ef1163a782b31774965 Mon Sep 17 00:00:00 2001 From: devshahofficial Date: Thu, 16 Jul 2026 15:00:57 -0700 Subject: [PATCH] Fix attached tendon wrap model pointers --- src/user/user_objects.cc | 3 ++- test/user/user_api_test.cc | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/user/user_objects.cc b/src/user/user_objects.cc index 726036a6..ad557e57 100644 --- a/src/user/user_objects.cc +++ b/src/user/user_objects.cc @@ -6451,8 +6451,9 @@ void mjCTendon::CopyFromSpec() { material_ = spec_material_; userdata_ = spec_userdata_; - // clear precompiled + // propagate model pointer to wraps and clear precompiled for (int i=0; i < path.size(); i++) { + path[i]->model = model; if (path[i]->Type() == mjWRAP_CYLINDER) { path[i]->spec.type = mjWRAP_SPHERE; } diff --git a/test/user/user_api_test.cc b/test/user/user_api_test.cc index fe784a13..84227907 100644 --- a/test/user/user_api_test.cc +++ b/test/user/user_api_test.cc @@ -1283,6 +1283,20 @@ TEST_F(MujocoTest, AttachSpatialTendonWithoutSidesite) { mjs_findElement(parent, mjOBJ_TENDON, "tendon_without_sidesite_child"), NotNull()); + mjsTendon* tendon = mjs_asTendon( + mjs_findElement(parent, mjOBJ_TENDON, "tendon_with_sidesite_child")); + ASSERT_THAT(tendon, NotNull()); + ASSERT_EQ(mjs_getWrapNum(tendon), 3); + + EXPECT_EQ(mjs_getWrapTarget(mjs_getWrap(tendon, 0)), + mjs_findElement(parent, mjOBJ_SITE, "site_A_child")); + EXPECT_EQ(mjs_getWrapTarget(mjs_getWrap(tendon, 1)), + mjs_findElement(parent, mjOBJ_GEOM, "wrap_geom_child")); + EXPECT_EQ(mjs_getWrapTarget(mjs_getWrap(tendon, 2)), + mjs_findElement(parent, mjOBJ_SITE, "site_B_child")); + EXPECT_EQ(mjs_getWrapSideSite(mjs_getWrap(tendon, 1)), + mjs_asSite(mjs_findElement(parent, mjOBJ_SITE, "side_site_child"))); + mjModel* model = mj_compile(parent, nullptr); ASSERT_THAT(model, NotNull()) << mjs_getError(parent); EXPECT_EQ(model->ntendon, 2);