diff --git a/include/mujoco/experimental/usd/mjcPhysics/sceneAPI.h b/include/mujoco/experimental/usd/mjcPhysics/sceneAPI.h index 86386f95..f499536a 100644 --- a/include/mujoco/experimental/usd/mjcPhysics/sceneAPI.h +++ b/include/mujoco/experimental/usd/mjcPhysics/sceneAPI.h @@ -1361,6 +1361,410 @@ class MjcPhysicsSceneAPI : public UsdAPISchemaBase { UsdAttribute CreateIslandFlagAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely = false) const; + public: + // --------------------------------------------------------------------- // + // AUTOLIMITS + // --------------------------------------------------------------------- // + /// This attribute affects the behavior of attributes such as "limited" (on + /// MjcJointAPI), "forcelimited" "ctrllimited", and "actlimited" (on + /// MjcActuator). If True, these attributes are unnecessary and their value + /// will be inferred from the presence of their corresponding "range" + /// attribute. If False, no such inference will happen: For a joint to be + /// limited, both limited=True and range:min/max must be specified. In this + /// mode, it is an error to specify a range without a limit. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform bool mjc:compiler:autoLimits = 1` | + /// | C++ Type | bool | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Bool | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetAutoLimitsAttr() const; + + /// See GetAutoLimitsAttr(), 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 CreateAutoLimitsAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // BOUNDMASS + // --------------------------------------------------------------------- // + /// This attribute imposes a lower bound on the mass of each body except for + /// the world body. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform double mjc:compiler:boundMass = 0` | + /// | C++ Type | double | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Double | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetBoundMassAttr() const; + + /// See GetBoundMassAttr(), 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 CreateBoundMassAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // BOUNDINERTIA + // --------------------------------------------------------------------- // + /// This attribute imposes a lower bound on the diagonal inertia components of + /// each body except for the world body. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform double mjc:compiler:boundInertia = 0` | + /// | C++ Type | double | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Double | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetBoundInertiaAttr() const; + + /// See GetBoundInertiaAttr(), 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 CreateBoundInertiaAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // SETTOTALMASS + // --------------------------------------------------------------------- // + /// If this value is positive, the compiler will scale the masses and inertias + /// of all bodies in the model, so that the total mass equals the value + /// specified here. The world body has mass 0 and does not participate in any + /// mass-related computations. This scaling is performed last, after all other + /// operations affecting the body mass and inertia. The same scaling operation + /// can be applied at runtime to the compiled mjModel with the function + /// mj_setTotalmass. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform double mjc:compiler:setTotalMass = -1` | + /// | C++ Type | double | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Double | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetSetTotalMassAttr() const; + + /// See GetSetTotalMassAttr(), 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 CreateSetTotalMassAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // USETHREAD + // --------------------------------------------------------------------- // + /// If this is True, the model compiler will run in multi-threaded mode. + /// Currently multi-threading is used for computing the length ranges of + /// actuators and for parallel loading of meshes. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform bool mjc:compiler:useThread = 1` | + /// | C++ Type | bool | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Bool | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetUseThreadAttr() const; + + /// See GetUseThreadAttr(), 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 CreateUseThreadAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // BALANCEINERTIA + // --------------------------------------------------------------------- // + /// A valid diagonal inertia matrix must satisfy A+B>=C for all permutations + /// of the three diagonal elements. Some poorly designed models violate this + /// constraint, which will normally result in a compile error. If this + /// attribute is set to "true", the compiler will silently set all three + /// diagonal elements to their average value whenever the above condition is + /// violated. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform bool mjc:compiler:balanceInertia = 0` | + /// | C++ Type | bool | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Bool | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetBalanceInertiaAttr() const; + + /// See GetBalanceInertiaAttr(), 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 CreateBalanceInertiaAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // ANGLE + // --------------------------------------------------------------------- // + /// This attribute specifies whether the angles in mjcPhysics attributes have + /// units of degrees or radians if not otherwise noted. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform token mjc:compiler:angle = "degree"` | + /// | C++ Type | TfToken | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Token | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + /// | \ref MjcPhysicsTokens "Allowed Values" | degree, radian | + MJCPHYSICS_API + UsdAttribute GetAngleAttr() const; + + /// See GetAngleAttr(), 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 CreateAngleAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // FITAABB + // --------------------------------------------------------------------- // + /// The compiler is able to replace a mesh with a geometric primitive fitted + /// to that mesh. If this attribute is True, the fitting procedure uses the + /// axis-aligned bounding box (AABB) of the mesh. Otherwise it uses the + /// equivalent-inertia box of the mesh. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform bool mjc:compiler:fitAABB = 0` | + /// | C++ Type | bool | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Bool | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetFitAABBAttr() const; + + /// See GetFitAABBAttr(), 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 CreateFitAABBAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // FUSESTATIC + // --------------------------------------------------------------------- // + /// This attribute controls a compiler optimization feature where static + /// bodies are fused with their parent, and any elements defined in those + /// bodies are reassigned to the parent. Static bodies are fused with their + /// parent unless + /// + /// * They are referenced by another element in the model. + /// + /// * They contain a site which is referenced by a force or torque sensor. + /// + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform bool mjc:compiler:fuseStatic = 0` | + /// | C++ Type | bool | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Bool | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetFuseStaticAttr() const; + + /// See GetFuseStaticAttr(), 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 CreateFuseStaticAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // INERTIAFROMGEOM + // --------------------------------------------------------------------- // + /// This attribute controls the automatic inference of body masses and + /// inertias from geoms attached to the body. If this setting is "false", no + /// automatic inference is performed. In that case each body must have + /// explicitly defined mass and inertia with the inertial element, or else a + /// compile error will be generated. If this setting is "true", the mass and + /// inertia of each body will be inferred from the geoms attached to it, + /// overriding any values specified with the inertial element. The default + /// setting "auto" means that masses and inertias are inferred automatically + /// only when the inertial element is missing in the body definition. One + /// reason to set this attribute to "true" instead of "auto" is to override + /// inertial data imported from a poorly designed model. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform token mjc:compiler:inertiaFromGeom = "auto"` | + /// | C++ Type | TfToken | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Token | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + /// | \ref MjcPhysicsTokens "Allowed Values" | false, true, auto | + MJCPHYSICS_API + UsdAttribute GetInertiaFromGeomAttr() const; + + /// See GetInertiaFromGeomAttr(), 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 CreateInertiaFromGeomAttr( + VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // ALIGNFREE + // --------------------------------------------------------------------- // + /// This attribute toggles the default behaviour of an optimization that + /// applies to bodies with a free joint and no child bodies. When True, the + /// body frame and free joint will automatically be aligned with inertial + /// frame, which leads to both faster and more stable simulation. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform bool mjc:compiler:alignFree = 0` | + /// | C++ Type | bool | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Bool | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetAlignFreeAttr() const; + + /// See GetAlignFreeAttr(), 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 CreateAlignFreeAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // INERTIAGROUPRANGEMIN + // --------------------------------------------------------------------- // + /// This attribute specifies the maximum of the geom group range that is used + /// to infer body masses and inertias (when such inference is enabled). The + /// group attribute of geom is an integer. If this integer falls in the range + /// specified here, the collider will be used in the inertial computation, + /// otherwise it will be ignored. Note that the world body does not + /// participate in the inertial computations, so any geoms attached to it are + /// automatically ignored. Therefore it is not necessary to adjust this + /// attribute and the geom-specific groups so as to exclude world geoms from + /// the inertial computation. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform int mjc:compiler:inertiaGroupRange:min = 0` | + /// | C++ Type | int | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Int | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetInertiaGroupRangeMinAttr() const; + + /// See GetInertiaGroupRangeMinAttr(), 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 CreateInertiaGroupRangeMinAttr( + VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // INERTIAGROUPRANGEMAX + // --------------------------------------------------------------------- // + /// This attribute specifies the maximum of the geom group range that is used + /// to infer body masses and inertias (when such inference is enabled). The + /// group attribute of geom is an integer. If this integer falls in the range + /// specified here, the geom will be used in the inertial computation, + /// otherwise it will be ignored. This feature is useful in models that have + /// redundant sets of geoms for collision and visualization. Note that the + /// world body does not participate in the inertial computations, so any geoms + /// attached to it are automatically ignored. Therefore it is not necessary to + /// adjust this attribute and the geom-specific groups so as to exclude world + /// geoms from the inertial computation. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform int mjc:compiler:inertiaGroupRange:max = 5` | + /// | C++ Type | int | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Int | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetInertiaGroupRangeMaxAttr() const; + + /// See GetInertiaGroupRangeMaxAttr(), 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 CreateInertiaGroupRangeMaxAttr( + VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + + public: + // --------------------------------------------------------------------- // + // SAVEINERTIAL + // --------------------------------------------------------------------- // + /// If True, the compiler will save explicit inertial clauses for all bodies. + /// + /// | || + /// | -- | -- | + /// | Declaration | `uniform bool mjc:compiler:saveInertial = 0` | + /// | C++ Type | bool | + /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Bool | + /// | \ref SdfVariability "Variability" | SdfVariabilityUniform | + MJCPHYSICS_API + UsdAttribute GetSaveInertialAttr() const; + + /// See GetSaveInertialAttr(), 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 CreateSaveInertialAttr(VtValue const &defaultValue = VtValue(), + bool writeSparsely = false) const; + public: // ===================================================================== // // Feel free to add custom code below this line, it will be preserved by diff --git a/include/mujoco/experimental/usd/mjcPhysics/tokens.h b/include/mujoco/experimental/usd/mjcPhysics/tokens.h index ad97d3c1..1de2afb3 100644 --- a/include/mujoco/experimental/usd/mjcPhysics/tokens.h +++ b/include/mujoco/experimental/usd/mjcPhysics/tokens.h @@ -60,8 +60,9 @@ struct MjcPhysicsTokensType { const TfToken affine; /// \brief "auto" /// - /// Fallback value for MjcPhysicsSceneAPI::GetJacobianAttr(), Fallback value - /// for MjcPhysicsActuator::GetMjcActLimitedAttr(), Fallback value for + /// Fallback value for MjcPhysicsSceneAPI::GetInertiaFromGeomAttr(), Fallback + /// value for MjcPhysicsSceneAPI::GetJacobianAttr(), Fallback value for + /// MjcPhysicsActuator::GetMjcActLimitedAttr(), Fallback value for /// MjcPhysicsActuator::GetMjcCtrlLimitedAttr(), Fallback value for /// MjcPhysicsActuator::GetMjcForceLimitedAttr(), Fallback value for /// MjcPhysicsJointAPI::GetMjcActuatorfrclimitedAttr(), This token represents @@ -76,6 +77,10 @@ struct MjcPhysicsTokensType { /// /// Possible value for MjcPhysicsMeshCollisionAPI::GetInertiaAttr() const TfToken convex; + /// \brief "degree" + /// + /// Fallback value for MjcPhysicsSceneAPI::GetAngleAttr() + const TfToken degree; /// \brief "dense" /// /// Possible value for MjcPhysicsSceneAPI::GetJacobianAttr(), This token @@ -97,8 +102,9 @@ struct MjcPhysicsTokensType { const TfToken exact; /// \brief "false" /// - /// Possible value for MjcPhysicsActuator::GetMjcActLimitedAttr(), Possible - /// value for MjcPhysicsActuator::GetMjcCtrlLimitedAttr(), Possible value for + /// Possible value for MjcPhysicsSceneAPI::GetInertiaFromGeomAttr(), Possible + /// value for MjcPhysicsActuator::GetMjcActLimitedAttr(), Possible value for + /// MjcPhysicsActuator::GetMjcCtrlLimitedAttr(), Possible value for /// MjcPhysicsActuator::GetMjcForceLimitedAttr(), Possible value for /// MjcPhysicsJointAPI::GetMjcActuatorfrclimitedAttr() const TfToken false_; @@ -184,6 +190,62 @@ struct MjcPhysicsTokensType { /// /// MjcPhysicsActuator const TfToken mjcBiasType; + /// \brief "mjc:compiler:alignFree" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerAlignFree; + /// \brief "mjc:compiler:angle" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerAngle; + /// \brief "mjc:compiler:autoLimits" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerAutoLimits; + /// \brief "mjc:compiler:balanceInertia" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerBalanceInertia; + /// \brief "mjc:compiler:boundInertia" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerBoundInertia; + /// \brief "mjc:compiler:boundMass" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerBoundMass; + /// \brief "mjc:compiler:fitAABB" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerFitAABB; + /// \brief "mjc:compiler:fuseStatic" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerFuseStatic; + /// \brief "mjc:compiler:inertiaFromGeom" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerInertiaFromGeom; + /// \brief "mjc:compiler:inertiaGroupRange:max" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerInertiaGroupRangeMax; + /// \brief "mjc:compiler:inertiaGroupRange:min" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerInertiaGroupRangeMin; + /// \brief "mjc:compiler:saveInertial" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerSaveInertial; + /// \brief "mjc:compiler:setTotalMass" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerSetTotalMass; + /// \brief "mjc:compiler:useThread" + /// + /// MjcPhysicsSceneAPI + const TfToken mjcCompilerUseThread; /// \brief "mjc:condim" /// /// MjcPhysicsCollisionAPI @@ -595,6 +657,10 @@ struct MjcPhysicsTokensType { /// Fallback value for MjcPhysicsSceneAPI::GetConeAttr(), This token /// represents the pyramidal contact friction cone type. const TfToken pyramidal; + /// \brief "radian" + /// + /// Possible value for MjcPhysicsSceneAPI::GetAngleAttr() + const TfToken radian; /// \brief "rk4" /// /// Possible value for MjcPhysicsSceneAPI::GetIntegratorAttr(), This token @@ -611,8 +677,9 @@ struct MjcPhysicsTokensType { const TfToken sparse; /// \brief "true" /// - /// Possible value for MjcPhysicsActuator::GetMjcActLimitedAttr(), Possible - /// value for MjcPhysicsActuator::GetMjcCtrlLimitedAttr(), Possible value for + /// Possible value for MjcPhysicsSceneAPI::GetInertiaFromGeomAttr(), Possible + /// value for MjcPhysicsActuator::GetMjcActLimitedAttr(), Possible value for + /// MjcPhysicsActuator::GetMjcCtrlLimitedAttr(), Possible value for /// MjcPhysicsActuator::GetMjcForceLimitedAttr(), Possible value for /// MjcPhysicsJointAPI::GetMjcActuatorfrclimitedAttr() const TfToken true_; diff --git a/src/experimental/usd/mjcPhysics/generatedSchema.usda b/src/experimental/usd/mjcPhysics/generatedSchema.usda index f0bbb966..a2d759ef 100644 --- a/src/experimental/usd/mjcPhysics/generatedSchema.usda +++ b/src/experimental/usd/mjcPhysics/generatedSchema.usda @@ -7,6 +7,69 @@ class "MjcSceneAPI" ( doc = "API providing global simulation options for MuJoCo." ) { + uniform bool mjc:compiler:alignFree = 0 ( + displayName = "Align Free" + doc = "This attribute toggles the default behaviour of an optimization that applies to bodies with a free joint and no child bodies. When True, the body frame and free joint will automatically be aligned with inertial frame, which leads to both faster and more stable simulation." + ) + uniform token mjc:compiler:angle = "degree" ( + allowedTokens = ["degree", "radian"] + displayName = "Angle" + doc = "This attribute specifies whether the angles in mjcPhysics attributes have units of degrees or radians if not otherwise noted." + ) + uniform bool mjc:compiler:autoLimits = 1 ( + displayName = "Automatic Limits" + doc = 'This attribute affects the behavior of attributes such as "limited" (on MjcJointAPI), "forcelimited" "ctrllimited", and "actlimited" (on MjcActuator). If True, these attributes are unnecessary and their value will be inferred from the presence of their corresponding "range" attribute. If False, no such inference will happen: For a joint to be limited, both limited=True and range:min/max must be specified. In this mode, it is an error to specify a range without a limit.' + ) + uniform bool mjc:compiler:balanceInertia = 0 ( + displayName = "Balance Inertia" + doc = 'A valid diagonal inertia matrix must satisfy A+B>=C for all permutations of the three diagonal elements. Some poorly designed models violate this constraint, which will normally result in a compile error. If this attribute is set to "true", the compiler will silently set all three diagonal elements to their average value whenever the above condition is violated.' + ) + uniform double mjc:compiler:boundInertia = 0 ( + displayName = "Bound Inertia" + doc = "This attribute imposes a lower bound on the diagonal inertia components of each body except for the world body." + ) + uniform double mjc:compiler:boundMass = 0 ( + displayName = "Bound Mass" + doc = "This attribute imposes a lower bound on the mass of each body except for the world body." + ) + uniform bool mjc:compiler:fitAABB = 0 ( + displayName = "Fit AABB" + doc = "The compiler is able to replace a mesh with a geometric primitive fitted to that mesh. If this attribute is True, the fitting procedure uses the axis-aligned bounding box (AABB) of the mesh. Otherwise it uses the equivalent-inertia box of the mesh." + ) + uniform bool mjc:compiler:fuseStatic = 0 ( + displayName = "Fuse Static" + doc = """This attribute controls a compiler optimization feature where static bodies are fused with their parent, and any elements defined in those bodies are reassigned to the parent. Static bodies are fused with their parent unless + +* They are referenced by another element in the model. + +* They contain a site which is referenced by a force or torque sensor. +""" + ) + uniform token mjc:compiler:inertiaFromGeom = "auto" ( + allowedTokens = ["false", "true", "auto"] + displayName = "Inertia From Geom" + doc = 'This attribute controls the automatic inference of body masses and inertias from geoms attached to the body. If this setting is "false", no automatic inference is performed. In that case each body must have explicitly defined mass and inertia with the inertial element, or else a compile error will be generated. If this setting is "true", the mass and inertia of each body will be inferred from the geoms attached to it, overriding any values specified with the inertial element. The default setting "auto" means that masses and inertias are inferred automatically only when the inertial element is missing in the body definition. One reason to set this attribute to "true" instead of "auto" is to override inertial data imported from a poorly designed model.' + ) + uniform int mjc:compiler:inertiaGroupRange:max = 5 ( + displayName = "Inertia Group Range Max" + doc = "This attribute specifies the maximum of the geom group range that is used to infer body masses and inertias (when such inference is enabled). The group attribute of geom is an integer. If this integer falls in the range specified here, the geom will be used in the inertial computation, otherwise it will be ignored. This feature is useful in models that have redundant sets of geoms for collision and visualization. Note that the world body does not participate in the inertial computations, so any geoms attached to it are automatically ignored. Therefore it is not necessary to adjust this attribute and the geom-specific groups so as to exclude world geoms from the inertial computation." + ) + uniform int mjc:compiler:inertiaGroupRange:min = 0 ( + displayName = "Inertia Group Range Min" + doc = "This attribute specifies the maximum of the geom group range that is used to infer body masses and inertias (when such inference is enabled). The group attribute of geom is an integer. If this integer falls in the range specified here, the collider will be used in the inertial computation, otherwise it will be ignored. Note that the world body does not participate in the inertial computations, so any geoms attached to it are automatically ignored. Therefore it is not necessary to adjust this attribute and the geom-specific groups so as to exclude world geoms from the inertial computation." + ) + uniform bool mjc:compiler:saveInertial = 0 ( + displayName = "Save Inertial" + doc = "If True, the compiler will save explicit inertial clauses for all bodies." + ) + uniform double mjc:compiler:setTotalMass = -1 ( + displayName = "Set Total Mass" + doc = "If this value is positive, the compiler will scale the masses and inertias of all bodies in the model, so that the total mass equals the value specified here. The world body has mass 0 and does not participate in any mass-related computations. This scaling is performed last, after all other operations affecting the body mass and inertia. The same scaling operation can be applied at runtime to the compiled mjModel with the function mj_setTotalmass." + ) + uniform bool mjc:compiler:useThread = 1 ( + displayName = "Use Thread" + doc = "If this is True, the model compiler will run in multi-threaded mode. Currently multi-threading is used for computing the length ranges of actuators and for parallel loading of meshes." + ) uniform bool mjc:flag:actuation = 1 ( displayName = "Actuation Forces Toggle" doc = "Enables all standard computations related to actuator forces, including actuator dynamics." diff --git a/src/experimental/usd/mjcPhysics/sceneAPI.cpp b/src/experimental/usd/mjcPhysics/sceneAPI.cpp index 455190a7..700c1c2f 100644 --- a/src/experimental/usd/mjcPhysics/sceneAPI.cpp +++ b/src/experimental/usd/mjcPhysics/sceneAPI.cpp @@ -615,6 +615,162 @@ UsdAttribute MjcPhysicsSceneAPI::CreateIslandFlagAttr( /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); } +UsdAttribute MjcPhysicsSceneAPI::GetAutoLimitsAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerAutoLimits); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateAutoLimitsAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerAutoLimits, SdfValueTypeNames->Bool, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetBoundMassAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerBoundMass); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateBoundMassAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerBoundMass, SdfValueTypeNames->Double, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetBoundInertiaAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerBoundInertia); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateBoundInertiaAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerBoundInertia, SdfValueTypeNames->Double, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetSetTotalMassAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerSetTotalMass); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateSetTotalMassAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerSetTotalMass, SdfValueTypeNames->Double, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetUseThreadAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerUseThread); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateUseThreadAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerUseThread, SdfValueTypeNames->Bool, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetBalanceInertiaAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerBalanceInertia); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateBalanceInertiaAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerBalanceInertia, SdfValueTypeNames->Bool, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetAngleAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerAngle); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateAngleAttr(VtValue const &defaultValue, + bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerAngle, SdfValueTypeNames->Token, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetFitAABBAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerFitAABB); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateFitAABBAttr(VtValue const &defaultValue, + bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerFitAABB, SdfValueTypeNames->Bool, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetFuseStaticAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerFuseStatic); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateFuseStaticAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerFuseStatic, SdfValueTypeNames->Bool, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetInertiaFromGeomAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerInertiaFromGeom); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateInertiaFromGeomAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerInertiaFromGeom, SdfValueTypeNames->Token, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetAlignFreeAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerAlignFree); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateAlignFreeAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerAlignFree, SdfValueTypeNames->Bool, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetInertiaGroupRangeMinAttr() const { + return GetPrim().GetAttribute( + MjcPhysicsTokens->mjcCompilerInertiaGroupRangeMin); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateInertiaGroupRangeMinAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerInertiaGroupRangeMin, SdfValueTypeNames->Int, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetInertiaGroupRangeMaxAttr() const { + return GetPrim().GetAttribute( + MjcPhysicsTokens->mjcCompilerInertiaGroupRangeMax); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateInertiaGroupRangeMaxAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerInertiaGroupRangeMax, SdfValueTypeNames->Int, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + +UsdAttribute MjcPhysicsSceneAPI::GetSaveInertialAttr() const { + return GetPrim().GetAttribute(MjcPhysicsTokens->mjcCompilerSaveInertial); +} + +UsdAttribute MjcPhysicsSceneAPI::CreateSaveInertialAttr( + VtValue const &defaultValue, bool writeSparsely) const { + return UsdSchemaBase::_CreateAttr( + MjcPhysicsTokens->mjcCompilerSaveInertial, SdfValueTypeNames->Bool, + /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely); +} + namespace { static inline TfTokenVector _ConcatenateAttributeNames( const TfTokenVector &left, const TfTokenVector &right) { @@ -679,6 +835,20 @@ const TfTokenVector &MjcPhysicsSceneAPI::GetSchemaAttributeNames( MjcPhysicsTokens->mjcFlagInvdiscrete, MjcPhysicsTokens->mjcFlagMulticcd, MjcPhysicsTokens->mjcFlagIsland, + MjcPhysicsTokens->mjcCompilerAutoLimits, + MjcPhysicsTokens->mjcCompilerBoundMass, + MjcPhysicsTokens->mjcCompilerBoundInertia, + MjcPhysicsTokens->mjcCompilerSetTotalMass, + MjcPhysicsTokens->mjcCompilerUseThread, + MjcPhysicsTokens->mjcCompilerBalanceInertia, + MjcPhysicsTokens->mjcCompilerAngle, + MjcPhysicsTokens->mjcCompilerFitAABB, + MjcPhysicsTokens->mjcCompilerFuseStatic, + MjcPhysicsTokens->mjcCompilerInertiaFromGeom, + MjcPhysicsTokens->mjcCompilerAlignFree, + MjcPhysicsTokens->mjcCompilerInertiaGroupRangeMin, + MjcPhysicsTokens->mjcCompilerInertiaGroupRangeMax, + MjcPhysicsTokens->mjcCompilerSaveInertial, }; static TfTokenVector allNames = _ConcatenateAttributeNames( UsdAPISchemaBase::GetSchemaAttributeNames(true), localNames); diff --git a/src/experimental/usd/mjcPhysics/schema.usda b/src/experimental/usd/mjcPhysics/schema.usda index f0669d95..48e93689 100644 --- a/src/experimental/usd/mjcPhysics/schema.usda +++ b/src/experimental/usd/mjcPhysics/schema.usda @@ -509,6 +509,125 @@ class "MjcSceneAPI" displayName = "Constraint Island Discovery Toggle" doc = """Enables the discovery of constraint islands.""" ) + + uniform bool mjc:compiler:autoLimits = True ( + customData = { + string apiName = "AutoLimits" + } + displayName = "Automatic Limits" + doc = """This attribute affects the behavior of attributes such as "limited" (on MjcJointAPI), "forcelimited" "ctrllimited", and "actlimited" (on MjcActuator). If True, these attributes are unnecessary and their value will be inferred from the presence of their corresponding "range" attribute. If False, no such inference will happen: For a joint to be limited, both limited=True and range:min/max must be specified. In this mode, it is an error to specify a range without a limit.""" + ) + + uniform double mjc:compiler:boundMass = 0.0 ( + customData = { + string apiName = "BoundMass" + } + displayName = "Bound Mass" + doc = """This attribute imposes a lower bound on the mass of each body except for the world body.""" + ) + + uniform double mjc:compiler:boundInertia = 0.0 ( + customData = { + string apiName = "BoundInertia" + } + displayName = "Bound Inertia" + doc = """This attribute imposes a lower bound on the diagonal inertia components of each body except for the world body.""" + ) + + uniform double mjc:compiler:setTotalMass = -1.0 ( + customData = { + string apiName = "SetTotalMass" + } + displayName = "Set Total Mass" + doc = """If this value is positive, the compiler will scale the masses and inertias of all bodies in the model, so that the total mass equals the value specified here. The world body has mass 0 and does not participate in any mass-related computations. This scaling is performed last, after all other operations affecting the body mass and inertia. The same scaling operation can be applied at runtime to the compiled mjModel with the function mj_setTotalmass.""" + ) + + uniform bool mjc:compiler:useThread = True ( + customData = { + string apiName = "UseThread" + } + displayName = "Use Thread" + doc = """If this is True, the model compiler will run in multi-threaded mode. Currently multi-threading is used for computing the length ranges of actuators and for parallel loading of meshes.""" + ) + + uniform bool mjc:compiler:balanceInertia = False ( + customData = { + string apiName = "BalanceInertia" + } + displayName = "Balance Inertia" + doc = """A valid diagonal inertia matrix must satisfy A+B>=C for all permutations of the three diagonal elements. Some poorly designed models violate this constraint, which will normally result in a compile error. If this attribute is set to "true", the compiler will silently set all three diagonal elements to their average value whenever the above condition is violated.""" + ) + + uniform token mjc:compiler:angle = "degree" ( + allowedTokens = ["degree", "radian"] + customData = { + string apiName = "Angle" + } + displayName = "Angle" + doc = """This attribute specifies whether the angles in mjcPhysics attributes have units of degrees or radians if not otherwise noted.""" + ) + + uniform bool mjc:compiler:fitAABB = False ( + customData = { + string apiName = "FitAABB" + } + displayName = "Fit AABB" + doc = """The compiler is able to replace a mesh with a geometric primitive fitted to that mesh. If this attribute is True, the fitting procedure uses the axis-aligned bounding box (AABB) of the mesh. Otherwise it uses the equivalent-inertia box of the mesh.""" + ) + + uniform bool mjc:compiler:fuseStatic = False ( + customData = { + string apiName = "FuseStatic" + } + displayName = "Fuse Static" + doc = """This attribute controls a compiler optimization feature where static bodies are fused with their parent, and any elements defined in those bodies are reassigned to the parent. Static bodies are fused with their parent unless + +* They are referenced by another element in the model. + +* They contain a site which is referenced by a force or torque sensor. +""" + ) + + uniform token mjc:compiler:inertiaFromGeom = "auto" ( + allowedTokens = ["false", "true", "auto"] + customData = { + string apiName = "InertiaFromGeom" + } + displayName = "Inertia From Geom" + doc = """This attribute controls the automatic inference of body masses and inertias from geoms attached to the body. If this setting is "false", no automatic inference is performed. In that case each body must have explicitly defined mass and inertia with the inertial element, or else a compile error will be generated. If this setting is "true", the mass and inertia of each body will be inferred from the geoms attached to it, overriding any values specified with the inertial element. The default setting "auto" means that masses and inertias are inferred automatically only when the inertial element is missing in the body definition. One reason to set this attribute to "true" instead of "auto" is to override inertial data imported from a poorly designed model.""" + ) + + uniform bool mjc:compiler:alignFree = False ( + customData = { + string apiName = "AlignFree" + } + displayName = "Align Free" + doc = """This attribute toggles the default behaviour of an optimization that applies to bodies with a free joint and no child bodies. When True, the body frame and free joint will automatically be aligned with inertial frame, which leads to both faster and more stable simulation.""" + ) + + uniform int mjc:compiler:inertiaGroupRange:min = 0 ( + customData = { + string apiName = "InertiaGroupRangeMin" + } + displayName = "Inertia Group Range Min" + doc = """This attribute specifies the maximum of the geom group range that is used to infer body masses and inertias (when such inference is enabled). The group attribute of geom is an integer. If this integer falls in the range specified here, the collider will be used in the inertial computation, otherwise it will be ignored. Note that the world body does not participate in the inertial computations, so any geoms attached to it are automatically ignored. Therefore it is not necessary to adjust this attribute and the geom-specific groups so as to exclude world geoms from the inertial computation.""" + ) + + uniform int mjc:compiler:inertiaGroupRange:max = 5 ( + customData = { + string apiName = "InertiaGroupRangeMax" + } + displayName = "Inertia Group Range Max" + doc = """This attribute specifies the maximum of the geom group range that is used to infer body masses and inertias (when such inference is enabled). The group attribute of geom is an integer. If this integer falls in the range specified here, the geom will be used in the inertial computation, otherwise it will be ignored. This feature is useful in models that have redundant sets of geoms for collision and visualization. Note that the world body does not participate in the inertial computations, so any geoms attached to it are automatically ignored. Therefore it is not necessary to adjust this attribute and the geom-specific groups so as to exclude world geoms from the inertial computation.""" + ) + + uniform bool mjc:compiler:saveInertial = False ( + customData = { + string apiName = "SaveInertial" + } + displayName = "Save Inertial" + doc = """If True, the compiler will save explicit inertial clauses for all bodies.""" + ) } class "MjcSiteAPI" diff --git a/src/experimental/usd/mjcPhysics/tokens.cpp b/src/experimental/usd/mjcPhysics/tokens.cpp index db19379a..26c22669 100644 --- a/src/experimental/usd/mjcPhysics/tokens.cpp +++ b/src/experimental/usd/mjcPhysics/tokens.cpp @@ -21,6 +21,7 @@ MjcPhysicsTokensType::MjcPhysicsTokensType() auto_("auto", TfToken::Immortal), cg("cg", TfToken::Immortal), convex("convex", TfToken::Immortal), + degree("degree", TfToken::Immortal), dense("dense", TfToken::Immortal), elliptic("elliptic", TfToken::Immortal), euler("euler", TfToken::Immortal), @@ -46,6 +47,24 @@ MjcPhysicsTokensType::MjcPhysicsTokensType() mjcArmature("mjc:armature", TfToken::Immortal), mjcBiasPrm("mjc:biasPrm", TfToken::Immortal), mjcBiasType("mjc:biasType", TfToken::Immortal), + mjcCompilerAlignFree("mjc:compiler:alignFree", TfToken::Immortal), + mjcCompilerAngle("mjc:compiler:angle", TfToken::Immortal), + mjcCompilerAutoLimits("mjc:compiler:autoLimits", TfToken::Immortal), + mjcCompilerBalanceInertia("mjc:compiler:balanceInertia", + TfToken::Immortal), + mjcCompilerBoundInertia("mjc:compiler:boundInertia", TfToken::Immortal), + mjcCompilerBoundMass("mjc:compiler:boundMass", TfToken::Immortal), + mjcCompilerFitAABB("mjc:compiler:fitAABB", TfToken::Immortal), + mjcCompilerFuseStatic("mjc:compiler:fuseStatic", TfToken::Immortal), + mjcCompilerInertiaFromGeom("mjc:compiler:inertiaFromGeom", + TfToken::Immortal), + mjcCompilerInertiaGroupRangeMax("mjc:compiler:inertiaGroupRange:max", + TfToken::Immortal), + mjcCompilerInertiaGroupRangeMin("mjc:compiler:inertiaGroupRange:min", + TfToken::Immortal), + mjcCompilerSaveInertial("mjc:compiler:saveInertial", TfToken::Immortal), + mjcCompilerSetTotalMass("mjc:compiler:setTotalMass", TfToken::Immortal), + mjcCompilerUseThread("mjc:compiler:useThread", TfToken::Immortal), mjcCondim("mjc:condim", TfToken::Immortal), mjcCrankLength("mjc:crankLength", TfToken::Immortal), mjcCtrl("mjc:ctrl", TfToken::Immortal), @@ -150,6 +169,7 @@ MjcPhysicsTokensType::MjcPhysicsTokensType() none("none", TfToken::Immortal), pgs("pgs", TfToken::Immortal), pyramidal("pyramidal", TfToken::Immortal), + radian("radian", TfToken::Immortal), rk4("rk4", TfToken::Immortal), shell("shell", TfToken::Immortal), sparse("sparse", TfToken::Immortal), @@ -167,6 +187,7 @@ MjcPhysicsTokensType::MjcPhysicsTokensType() auto_, cg, convex, + degree, dense, elliptic, euler, @@ -192,6 +213,20 @@ MjcPhysicsTokensType::MjcPhysicsTokensType() mjcArmature, mjcBiasPrm, mjcBiasType, + mjcCompilerAlignFree, + mjcCompilerAngle, + mjcCompilerAutoLimits, + mjcCompilerBalanceInertia, + mjcCompilerBoundInertia, + mjcCompilerBoundMass, + mjcCompilerFitAABB, + mjcCompilerFuseStatic, + mjcCompilerInertiaFromGeom, + mjcCompilerInertiaGroupRangeMax, + mjcCompilerInertiaGroupRangeMin, + mjcCompilerSaveInertial, + mjcCompilerSetTotalMass, + mjcCompilerUseThread, mjcCondim, mjcCrankLength, mjcCtrl, @@ -293,6 +328,7 @@ MjcPhysicsTokensType::MjcPhysicsTokensType() none, pgs, pyramidal, + radian, rk4, shell, sparse, diff --git a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc index 28c68f65..9ff49905 100644 --- a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc +++ b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc @@ -655,6 +655,72 @@ class ModelWriter { for (const auto &[token, flag] : disable_flags) { create_flag_attr(token, flag, false); } + + + // Compiler attributes + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + MjcPhysicsTokens->mjcCompilerAutoLimits, + (bool)spec_->compiler.autolimits); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Double, + MjcPhysicsTokens->mjcCompilerBoundMass, + spec_->compiler.boundmass); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Double, + MjcPhysicsTokens->mjcCompilerBoundInertia, + spec_->compiler.boundinertia); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Double, + MjcPhysicsTokens->mjcCompilerSetTotalMass, + spec_->compiler.settotalmass); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + MjcPhysicsTokens->mjcCompilerUseThread, + (bool)spec_->compiler.usethread); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + MjcPhysicsTokens->mjcCompilerBalanceInertia, + (bool)spec_->compiler.balanceinertia); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Token, + MjcPhysicsTokens->mjcCompilerAngle, + spec_->compiler.degree ? MjcPhysicsTokens->degree:MjcPhysicsTokens->radian); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + MjcPhysicsTokens->mjcCompilerFitAABB, + (bool)spec_->compiler.fitaabb); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + MjcPhysicsTokens->mjcCompilerFuseStatic, + (bool)spec_->compiler.fusestatic); + + pxr::TfToken inertiafromgeom_token = MjcPhysicsTokens->auto_; + if (spec_->compiler.inertiafromgeom == + mjINERTIAFROMGEOM_TRUE) { // mjINERTIA_TRUE + inertiafromgeom_token = MjcPhysicsTokens->true_; + } else if (spec_->compiler.inertiafromgeom == + mjINERTIAFROMGEOM_FALSE) { // mjINERTIA_FALSE + inertiafromgeom_token = MjcPhysicsTokens->false_; + } + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Token, + MjcPhysicsTokens->mjcCompilerInertiaFromGeom, + inertiafromgeom_token); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + MjcPhysicsTokens->mjcCompilerAlignFree, + (bool)spec_->compiler.alignfree); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Int, + MjcPhysicsTokens->mjcCompilerInertiaGroupRangeMin, + spec_->compiler.inertiagrouprange[0]); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Int, + MjcPhysicsTokens->mjcCompilerInertiaGroupRangeMax, + spec_->compiler.inertiagrouprange[1]); + + WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + MjcPhysicsTokens->mjcCompilerSaveInertial, + (bool)spec_->compiler.saveinertial); } void WriteMeshes() { diff --git a/src/experimental/usd/usd_to_mjspec.cc b/src/experimental/usd/usd_to_mjspec.cc index ff3c57ef..f44bb84e 100644 --- a/src/experimental/usd/usd_to_mjspec.cc +++ b/src/experimental/usd/usd_to_mjspec.cc @@ -520,6 +520,102 @@ void ParseUsdPhysicsScene(mjSpec* spec, bool island_flag; mjc_physics_scene.GetIslandFlagAttr().Get(&island_flag); spec->option.enableflags |= (island_flag ? mjENBL_ISLAND : 0); + + // Compiler attributes + auto auto_limits_attr = mjc_physics_scene.GetAutoLimitsAttr(); + if (auto_limits_attr.HasAuthoredValue()) { + bool autolimits; + auto_limits_attr.Get(&autolimits); + spec->compiler.autolimits = autolimits; + } + + auto use_thread_attr = mjc_physics_scene.GetUseThreadAttr(); + if (use_thread_attr.HasAuthoredValue()) { + bool use_thread; + use_thread_attr.Get(&use_thread); + spec->compiler.usethread = use_thread; + } + + auto balance_inertia_attr = mjc_physics_scene.GetBalanceInertiaAttr(); + if (balance_inertia_attr.HasAuthoredValue()) { + bool balanceinertia; + balance_inertia_attr.Get(&balanceinertia); + spec->compiler.balanceinertia = balanceinertia; + } + + auto angle_attr = mjc_physics_scene.GetAngleAttr(); + if (angle_attr.HasAuthoredValue()) { + pxr::TfToken angle; + angle_attr.Get(&angle); + spec->compiler.degree = angle == MjcPhysicsTokens->degree; + } + + auto fit_aabb_attr = mjc_physics_scene.GetFitAABBAttr(); + if (fit_aabb_attr.HasAuthoredValue()) { + bool fitaabb; + fit_aabb_attr.Get(&fitaabb); + spec->compiler.fitaabb = fitaabb; + } + + auto fuse_static_attr = mjc_physics_scene.GetFuseStaticAttr(); + if (fuse_static_attr.HasAuthoredValue()) { + bool fusestatic; + fuse_static_attr.Get(&fusestatic); + spec->compiler.fusestatic = fusestatic; + } + + auto inertia_from_geom_attr = mjc_physics_scene.GetInertiaFromGeomAttr(); + if (inertia_from_geom_attr.HasAuthoredValue()) { + pxr::TfToken inertiafromgeom; + inertia_from_geom_attr.Get(&inertiafromgeom); + if (inertiafromgeom == MjcPhysicsTokens->auto_) { + spec->compiler.inertiafromgeom = mjINERTIAFROMGEOM_AUTO; + } else if(inertiafromgeom == MjcPhysicsTokens->false_) { + spec->compiler.inertiafromgeom = mjINERTIAFROMGEOM_FALSE; + } else if(inertiafromgeom == MjcPhysicsTokens->true_){ + spec->compiler.inertiafromgeom = mjINERTIAFROMGEOM_TRUE; + } else { + mju_warning("Invalid inertiafromgeom token: %s", + inertiafromgeom.GetText()); + } + } + + auto align_free_attr = mjc_physics_scene.GetAlignFreeAttr(); + if (align_free_attr.HasAuthoredValue()) { + bool alignfree; + align_free_attr.Get(&alignfree); + spec->compiler.alignfree = alignfree; + } + + auto inertia_group_range_min_attr = + mjc_physics_scene.GetInertiaGroupRangeMinAttr(); + auto inertia_group_range_max_attr = + mjc_physics_scene.GetInertiaGroupRangeMaxAttr(); + if (inertia_group_range_min_attr.HasAuthoredValue() && + inertia_group_range_max_attr.HasAuthoredValue()) { + int inertiagrouprangemin; + inertia_group_range_min_attr.Get(&inertiagrouprangemin); + int inertiagrouprangemax; + inertia_group_range_max_attr.Get(&inertiagrouprangemax); + spec->compiler.inertiagrouprange[0] = inertiagrouprangemin; + spec->compiler.inertiagrouprange[1] = inertiagrouprangemax; + } else if (inertia_group_range_min_attr.HasAuthoredValue() || + inertia_group_range_max_attr.HasAuthoredValue()) { + mju_warning( + "Only one of inertiaGroupRangeMin and inertiaGroupRangeMax was " + "authored, ignoring both."); + } + + auto save_inertial_attr = mjc_physics_scene.GetSaveInertialAttr(); + if (save_inertial_attr.HasAuthoredValue()) { + bool saveinertial; + save_inertial_attr.Get(&saveinertial); + spec->compiler.saveinertial = saveinertial; + } + + mjc_physics_scene.GetBoundMassAttr().Get(&spec->compiler.boundmass); + mjc_physics_scene.GetBoundInertiaAttr().Get(&spec->compiler.boundinertia); + mjc_physics_scene.GetSetTotalMassAttr().Get(&spec->compiler.settotalmass); } void ParseUsdPhysicsMassAPIForBody(mjsBody* body, diff --git a/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc b/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc index f5066232..e2423ef1 100644 --- a/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc +++ b/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc @@ -83,7 +83,6 @@ PXR_NAMESPACE_CLOSE_SCOPE namespace mujoco { namespace usd { -namespace { using pxr::MjcPhysicsSiteAPI; using pxr::MjcPhysicsTokens; @@ -1628,8 +1627,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsActuator) { auto stage = OpenStageWithPhysics(xml); EXPECT_PRIM_VALID(stage, "/test/Actuators/general"); - EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", - pxr::MjcPhysicsActuator); + EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", pxr::MjcPhysicsActuator); EXPECT_REL_HAS_TARGET(stage, "/test/Actuators/general.mjc:target", "/test/body/site"); EXPECT_REL_HAS_TARGET(stage, "/test/Actuators/general.mjc:refSite", @@ -1637,10 +1635,8 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsActuator) { ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:group", 123); ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:ctrlLimited", pxr::MjcPhysicsTokens->true_); - ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:ctrlRange:min", - 0.0); - ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:ctrlRange:max", - 1.0); + ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:ctrlRange:min", 0.0); + ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:ctrlRange:max", 1.0); ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:forceLimited", pxr::MjcPhysicsTokens->true_); ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:forceRange:min", @@ -1649,10 +1645,8 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsActuator) { 3.0); ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:actLimited", pxr::MjcPhysicsTokens->false_); - ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:actRange:min", - 4.0); - ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:actRange:max", - 5.0); + ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:actRange:min", 4.0); + ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:actRange:max", 5.0); ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:lengthRange:min", 6.0); ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:lengthRange:max", @@ -1696,12 +1690,10 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsPositionActuator) { auto stage = OpenStageWithPhysics(xml); EXPECT_PRIM_VALID(stage, "/test/Actuators/position"); - EXPECT_PRIM_IS_A(stage, "/test/Actuators/position", - pxr::MjcPhysicsActuator); + 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); + ExpectAttributeEqual(stage, "/test/Actuators/position.mjc:inheritRange", 1.0); } TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsJointActuator) { @@ -1726,8 +1718,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsJointActuator) { auto stage = OpenStageWithPhysics(xml); EXPECT_PRIM_VALID(stage, "/test/Actuators/general"); - EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", - pxr::MjcPhysicsActuator); + EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", pxr::MjcPhysicsActuator); EXPECT_REL_HAS_TARGET(stage, "/test/Actuators/general.mjc:target", "/test/axle/rod/rod_hinge"); } @@ -1751,8 +1742,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsBodyActuator) { auto stage = OpenStageWithPhysics(xml); EXPECT_PRIM_VALID(stage, "/test/Actuators/general"); - EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", - pxr::MjcPhysicsActuator); + EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", pxr::MjcPhysicsActuator); EXPECT_REL_HAS_TARGET(stage, "/test/Actuators/general.mjc:target", "/test/body"); } @@ -1780,14 +1770,12 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsSliderCrankActuator) { auto stage = OpenStageWithPhysics(xml); EXPECT_PRIM_VALID(stage, "/test/Actuators/general"); - EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", - pxr::MjcPhysicsActuator); + EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", pxr::MjcPhysicsActuator); EXPECT_REL_HAS_TARGET(stage, "/test/Actuators/general.mjc:target", "/test/body/crank"); EXPECT_REL_HAS_TARGET(stage, "/test/Actuators/general.mjc:sliderSite", "/test/body/slider"); - ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:crankLength", - 1.23); + ExpectAttributeEqual(stage, "/test/Actuators/general.mjc:crankLength", 1.23); } TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsJointAPI) { @@ -2226,6 +2214,58 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsKeyframe) { ExpectAttributeEqual(stage, "/test/Keyframes/Keyframe.mjc:qpos", pxr::VtDoubleArray({3}), pxr::UsdTimeCode(2.0)); } -} // namespace + +TEST_F(MjcfSdfFileFormatPluginTest, TestCompilerOptions) { + static constexpr char xml[] = R"( + + + +)"; + auto stage = OpenStageWithPhysics(xml); + + EXPECT_PRIM_VALID(stage, "/test/PhysicsScene"); + + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:autoLimits", + true); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:boundMass", 1.2); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:boundInertia", + 3.4); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:setTotalMass", + 5.6); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:useThread", + false); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:balanceInertia", + true); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:angle", + MjcPhysicsTokens->radian); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:fitAABB", true); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:fuseStatic", + true); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:inertiaFromGeom", + MjcPhysicsTokens->true_); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:alignFree", + true); + ExpectAttributeEqual( + stage, "/test/PhysicsScene.mjc:compiler:inertiaGroupRange:min", 1); + ExpectAttributeEqual( + stage, "/test/PhysicsScene.mjc:compiler:inertiaGroupRange:max", 6); + ExpectAttributeEqual(stage, "/test/PhysicsScene.mjc:compiler:saveInertial", + true); +} + } // namespace usd } // namespace mujoco