Add inheritrange attribute to mjcPhysics MjcActuator

PiperOrigin-RevId: 783363012
Change-Id: I7d0476aae70c3acc3ed4808a8741b7eb12948dba
This commit is contained in:
Sam Haves
2025-07-15 09:29:28 -07:00
committed by Copybara-Service
parent 5e666635f6
commit cdf5bcb693
9 changed files with 98 additions and 1 deletions
@@ -763,6 +763,40 @@ class MjcPhysicsActuator : public UsdTyped {
UsdAttribute CreateMjcActEarlyAttr(VtValue const &defaultValue = VtValue(),
bool writeSparsely = false) const;
public:
// --------------------------------------------------------------------- //
// MJCINHERITRANGE
// --------------------------------------------------------------------- //
/// Automatically set the actuators ctrlrange to match the transmission
/// targets range. The default value means disabled. A positive value X sets
/// the ctrlrange around the midpoint of the target range, scaled by X. For
/// example if the target joint has range of [0, 1], then a value of 1.0 will
/// set ctrlrange to [0, 1]; values of 0.8 and 1.2 will set the ctrlrange to
/// [0.1, 0.9] and [-0.1, 1.1], respectively. Values smaller than 1 are useful
/// for not hitting the limits; values larger than 1 are useful for
/// maintaining control authority at the limits (being able to push on them).
/// This attribute is exclusive with ctrlrange and available only for joint
/// and tendon transmissions which have range defined.
///
/// | ||
/// | -- | -- |
/// | Declaration | `uniform double mjc:inheritRange = 0` |
/// | C++ Type | double |
/// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Double |
/// | \ref SdfVariability "Variability" | SdfVariabilityUniform |
MJCPHYSICS_API
UsdAttribute GetMjcInheritRangeAttr() const;
/// See GetMjcInheritRangeAttr(), and also
/// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
/// If specified, author \p defaultValue as the attribute's default,
/// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
/// the default for \p writeSparsely is \c false.
MJCPHYSICS_API
UsdAttribute CreateMjcInheritRangeAttr(
VtValue const &defaultValue = VtValue(),
bool writeSparsely = false) const;
public:
// --------------------------------------------------------------------- //
// MJCTARGET
@@ -353,6 +353,10 @@ struct MjcPhysicsTokensType {
///
/// MjcPhysicsMeshCollisionAPI
const TfToken mjcInertia;
/// \brief "mjc:inheritRange"
///
/// MjcPhysicsActuator
const TfToken mjcInheritRange;
/// \brief "mjc:jointInParent"
///
/// MjcPhysicsActuator
+12 -1
View File
@@ -332,6 +332,17 @@ UsdAttribute MjcPhysicsActuator::CreateMjcActEarlyAttr(
/* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely);
}
UsdAttribute MjcPhysicsActuator::GetMjcInheritRangeAttr() const {
return GetPrim().GetAttribute(MjcPhysicsTokens->mjcInheritRange);
}
UsdAttribute MjcPhysicsActuator::CreateMjcInheritRangeAttr(
VtValue const &defaultValue, bool writeSparsely) const {
return UsdSchemaBase::_CreateAttr(
MjcPhysicsTokens->mjcInheritRange, SdfValueTypeNames->Double,
/* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely);
}
UsdRelationship MjcPhysicsActuator::GetMjcTargetRel() const {
return GetPrim().GetRelationship(MjcPhysicsTokens->mjcTarget);
}
@@ -385,7 +396,7 @@ const TfTokenVector &MjcPhysicsActuator::GetSchemaAttributeNames(
MjcPhysicsTokens->mjcDynType, MjcPhysicsTokens->mjcGainType,
MjcPhysicsTokens->mjcBiasType, MjcPhysicsTokens->mjcDynPrm,
MjcPhysicsTokens->mjcGainPrm, MjcPhysicsTokens->mjcBiasPrm,
MjcPhysicsTokens->mjcActEarly,
MjcPhysicsTokens->mjcActEarly, MjcPhysicsTokens->mjcInheritRange,
};
static TfTokenVector allNames = _ConcatenateAttributeNames(
UsdTyped::GetSchemaAttributeNames(true), localNames);
@@ -358,6 +358,9 @@ class MjcActuator "MjcActuator" (
displayName = "Group"
doc = "Integer MuJoCo group to which the transmission belongs."
)
uniform double mjc:inheritRange = 0 (
doc = "Automatically set the actuators ctrlrange to match the transmission targets range. The default value means disabled. A positive value X sets the ctrlrange around the midpoint of the target range, scaled by X. For example if the target joint has range of [0, 1], then a value of 1.0 will set ctrlrange to [0, 1]; values of 0.8 and 1.2 will set the ctrlrange to [0.1, 0.9] and [-0.1, 1.1], respectively. Values smaller than 1 are useful for not hitting the limits; values larger than 1 are useful for maintaining control authority at the limits (being able to push on them). This attribute is exclusive with ctrlrange and available only for joint and tendon transmissions which have range defined."
)
uniform bool mjc:jointInParent = 0 (
doc = "If true and applied to ball and free joints, the 3d rotation axis given by gear is defined in the parent frame (which is the world frame for free joints) rather than the child frame."
)
@@ -668,10 +668,12 @@ class MjcActuator "MjcActuator"
doc = "If true, the control input to this actuator is automatically clamped to ctrlrange at runtime. If false, control input clamping is disabled. If 'auto' and autolimits is set in compiler, control clamping will automatically be set to true if ctrlrange is defined without explicitly setting this attribute to 'true'. Note that control input clamping can also be globally disabled with the clampctrl attribute of option/flag."
allowedTokens = ["false", "true", "auto"]
)
uniform token mjc:forceLimited = "auto" (
doc = "If true, the force output of this actuator is automatically clamped to forcerange at runtime. If false, force clamping is disabled. If 'auto' and autolimits is set in compiler, force clamping will automatically be set to true if forcerange is defined without explicitly setting this attribute to 'true'."
allowedTokens = ["false", "true", "auto"]
)
uniform token mjc:actLimited = "auto" (
doc = "If true, the internal state (activation) associated with this actuator is automatically clamped to actrange at runtime. If false, activation clamping is disabled. If 'auto' and autolimits is set in compiler, activation clamping will automatically be set to true if actrange is defined without explicitly setting this attribute to 'true'. See the Activation clamping section for more details."
allowedTokens = ["false", "true", "auto"]
@@ -765,6 +767,10 @@ class MjcActuator "MjcActuator"
uniform bool mjc:actEarly = False (
doc = "If true, force computation will use the next value of the activation variable rather than the current one. Setting this flag reduces the delay between the control and accelerations by one time-step."
)
uniform double mjc:inheritRange = 0 (
doc = "Automatically set the actuators ctrlrange to match the transmission targets range. The default value means disabled. A positive value X sets the ctrlrange around the midpoint of the target range, scaled by X. For example if the target joint has range of [0, 1], then a value of 1.0 will set ctrlrange to [0, 1]; values of 0.8 and 1.2 will set the ctrlrange to [0.1, 0.9] and [-0.1, 1.1], respectively. Values smaller than 1 are useful for not hitting the limits; values larger than 1 are useful for maintaining control authority at the limits (being able to push on them). This attribute is exclusive with ctrlrange and available only for joint and tendon transmissions which have range defined."
)
}
@@ -88,6 +88,7 @@ MjcPhysicsTokensType::MjcPhysicsTokensType()
mjcGear("mjc:gear", TfToken::Immortal),
mjcGroup("mjc:group", TfToken::Immortal),
mjcInertia("mjc:inertia", TfToken::Immortal),
mjcInheritRange("mjc:inheritRange", TfToken::Immortal),
mjcJointInParent("mjc:jointInParent", TfToken::Immortal),
mjcLengthRangeMax("mjc:lengthRange:max", TfToken::Immortal),
mjcLengthRangeMin("mjc:lengthRange:min", TfToken::Immortal),
@@ -233,6 +234,7 @@ MjcPhysicsTokensType::MjcPhysicsTokensType()
mjcGear,
mjcGroup,
mjcInertia,
mjcInheritRange,
mjcJointInParent,
mjcLengthRangeMax,
mjcLengthRangeMin,
@@ -1180,6 +1180,9 @@ class ModelWriter {
WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Bool,
MjcPhysicsTokens->mjcActEarly,
(bool)actuator->actearly);
WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Double,
MjcPhysicsTokens->mjcInheritRange,
actuator->inheritrange);
WriteUniformAttribute(
actuator_path, pxr::SdfValueTypeNames->DoubleArray,
+5
View File
@@ -853,6 +853,11 @@ void ParseMjcPhysicsActuator(mjSpec* spec,
mj_act->actearly = (int)act_early;
}
auto inherit_range_attr = tran.GetMjcInheritRangeAttr();
if (act_early_attr.HasAuthoredValue()) {
act_early_attr.Get(&mj_act->inheritrange);
}
auto ref_site_rel = tran.GetMjcRefSiteRel();
if (ref_site_rel.HasAuthoredTargets()) {
pxr::SdfPathVector targets;
@@ -1675,6 +1675,35 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsActuator) {
pxr::VtDoubleArray{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}});
}
TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsPositionActuator) {
static constexpr char xml[] = R"(
<mujoco model="test">
<worldbody>
<body name="body">
<geom name="box" type="box" size=".05 .05 .05" density="1234"/>
<joint name="hinge" range="12 34"/>
</body>
</worldbody>
<actuator>
<position
name="position"
joint="hinge"
inheritrange="1"
/>
</actuator>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
EXPECT_PRIM_VALID(stage, "/test/Actuators/position");
EXPECT_PRIM_IS_A(stage, "/test/Actuators/position",
pxr::MjcPhysicsActuator);
EXPECT_REL_HAS_TARGET(stage, "/test/Actuators/position.mjc:target",
"/test/body/hinge");
ExpectAttributeEqual(stage, "/test/Actuators/position.mjc:inheritRange",
1.0);
}
TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsJointActuator) {
static constexpr char xml[] = R"(
<mujoco model="test">