From f434578d3031dcc94b62023f781ce645e554d0fa Mon Sep 17 00:00:00 2001 From: Sam Haves Date: Thu, 29 Jan 2026 08:50:04 -0800 Subject: [PATCH] USD decoder improvements: Support actuators targeting tendons and improve side site index handling. Adds support for mjTRN_TENDON actuators in the USD decoder. Modifies the tendon path parsing to correctly handle side site indices, allowing -1 to signify no side site for a given path element. PiperOrigin-RevId: 862755621 Change-Id: I18b13b160e3d1c27945d0972a69012d6307131e9 --- plugin/usd_decoder/usd_decoder.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugin/usd_decoder/usd_decoder.cc b/plugin/usd_decoder/usd_decoder.cc index 3a2ac958..07071a76 100644 --- a/plugin/usd_decoder/usd_decoder.cc +++ b/plugin/usd_decoder/usd_decoder.cc @@ -1067,7 +1067,7 @@ void ParseMjcPhysicsTendon(mjSpec* spec, const pxr::MjcPhysicsTendon& tendon) { std::string side_site_name = ""; if (!side_site_indices.empty()) { int side_site_index = side_site_indices[i]; - if (side_site_index >= side_site_paths.size()) { + if (side_site_index > 0 && side_site_index >= side_site_paths.size()) { mju_warning( "Tendon %s has side site index %d but only %lu side sites, " "skipping.", @@ -1075,7 +1075,9 @@ void ParseMjcPhysicsTendon(mjSpec* spec, const pxr::MjcPhysicsTendon& tendon) { side_site_paths.size()); return; } - side_site_name = side_site_paths[side_site_index].GetAsString(); + if (side_site_index >= 0) { + side_site_name = side_site_paths[side_site_index].GetAsString(); + } } wrap = mjs_wrapGeom(mj_tendon, wrap_target.GetAsString().c_str(), side_site_name.c_str()); @@ -1294,6 +1296,8 @@ void ParseMjcPhysicsActuator(mjSpec* spec, mj_act->trntype = mjTRN_BODY; } else if (target_prim.HasAPI()) { mj_act->trntype = slider_crank ? mjTRN_SLIDERCRANK : mjTRN_SITE; + } else if (target_prim.IsA()) { + mj_act->trntype = mjTRN_TENDON; } else { mju_warning("Actuator %s has an invalid target type, skipping.", prim.GetPath().GetAsString().c_str());