Update USD support in MuJoCo to Newton USD schemas v0.4.0.
See changelog for more info. PiperOrigin-RevId: 960284190 Change-Id: I89a84b1efbc22c89ee99db7436851ef27a325176
This commit is contained in:
committed by
Copybara-Service
parent
63b779042c
commit
39e4458806
@@ -107,6 +107,24 @@ Bug fixes
|
||||
stretch force itself is unchanged. This affects the implicit integrators and the implicit effective metric, so
|
||||
flexes using ``elastic2d="stretch"`` integrate slightly differently. Bending-only flexes are unaffected.
|
||||
|
||||
OpenUSD
|
||||
^^^^^^^
|
||||
|
||||
- Upgraded Newton USD schemas support to version 0.4.0:
|
||||
- ``NewtonJointAPI`` (``newton:armature``, ``newton:damping``, ``newton:friction``) deprecates the ``MjcJointAPI``
|
||||
equivalent ``mjc:armature``, ``mjc:damping``, and ``mjc:frictionloss`` attributes.
|
||||
- ``NewtonMassAPI`` (``newton:massModel``, ``newton:inertia``) deprecates the ``MjcCollisionAPI``
|
||||
equivalent ``mjc:shellinertia`` and ``MjcMeshCollisionAPI`` ``mjc:inertia`` attributes. This completes the
|
||||
deprecation of all ``MjcMeshCollisionAPI`` attributes, slating it for removal in a future release.
|
||||
- Added support for ``NewtonSiteAPI`` to declare sites, ``MjcSiteAPI`` auto applies this schema, but remains
|
||||
as an extension for the ``mjc:group`` attribute.
|
||||
- Added support for ``NewtonMaterialAPI`` (``newton:contactAdhesion``, ``newton:torsionalFriction``,
|
||||
``newton:rollingFriction``). This deprecates ``MjcMaterialAPI`` which will be removed in a future release.
|
||||
- Added support for ``NewtonMimicAPI`` (``newton:mimicJoint``, ``newton:mimicCoef0``, ``newton:mimicCoef1``) as a
|
||||
base for ``MjcEqualityJointAPI``, this deprecates the ``mjc:coef0`` and ``mjc:coef1`` attributes and the
|
||||
``mjc:target`` relationship.
|
||||
- Added support for ``NewtonArticulationRootAPI`` (``newton:jointsAddMobility``).
|
||||
|
||||
Version 3.11.0 (July 27, 2026)
|
||||
------------------------------
|
||||
|
||||
|
||||
@@ -172,6 +172,8 @@ class MjcPhysicsCollisionAPI : public UsdAPISchemaBase {
|
||||
// --------------------------------------------------------------------- //
|
||||
// SHELLINERTIA
|
||||
// --------------------------------------------------------------------- //
|
||||
/// DEPRECATED: Use NewtonMassAPI's newton:massModel = "shell" instead.
|
||||
///
|
||||
/// Enables handling of the inertia assuming mass is concentrated on the
|
||||
/// surface.
|
||||
///
|
||||
|
||||
@@ -546,6 +546,8 @@ class MjcPhysicsJointAPI : public UsdAPISchemaBase {
|
||||
// --------------------------------------------------------------------- //
|
||||
// MJCARMATURE
|
||||
// --------------------------------------------------------------------- //
|
||||
/// DEPRECATED: Use newton:armature instead.
|
||||
///
|
||||
/// Additional inertia associated with movement of the joint that is not due
|
||||
/// to body mass. This added inertia is usually due to a rotor (a.k.a
|
||||
/// armature) spinning faster than the joint itself due to a geared
|
||||
@@ -577,6 +579,8 @@ class MjcPhysicsJointAPI : public UsdAPISchemaBase {
|
||||
// --------------------------------------------------------------------- //
|
||||
// MJCDAMPING
|
||||
// --------------------------------------------------------------------- //
|
||||
/// DEPRECATED: Use newton:damping instead.
|
||||
///
|
||||
/// Damping applied to all degrees of freedom created by this joint. Unlike
|
||||
/// friction loss which is computed by the constraint solver, damping is
|
||||
/// simply a force linear in velocity. It is included in the passive forces.
|
||||
@@ -606,6 +610,8 @@ class MjcPhysicsJointAPI : public UsdAPISchemaBase {
|
||||
// --------------------------------------------------------------------- //
|
||||
// MJCFRICTIONLOSS
|
||||
// --------------------------------------------------------------------- //
|
||||
/// DEPRECATED: Use newton:friction instead.
|
||||
///
|
||||
/// Friction loss due to dry friction. This value is the same for all degrees
|
||||
/// of freedom created by this joint. Semantically friction loss does not make
|
||||
/// sense for free joints, but the compiler allows it. To enable friction
|
||||
|
||||
@@ -153,6 +153,9 @@ class MjcPhysicsMeshCollisionAPI : public UsdAPISchemaBase {
|
||||
// --------------------------------------------------------------------- //
|
||||
// INERTIA
|
||||
// --------------------------------------------------------------------- //
|
||||
/// DEPRECATED: Use NewtonMassAPI's newton:massModel or UsdPhysics's
|
||||
/// physics:approximation instead.
|
||||
///
|
||||
/// Controls how a mesh is used when mass and inertia are inferred from
|
||||
/// geometry.
|
||||
///
|
||||
|
||||
@@ -25,16 +25,20 @@
|
||||
#include <mujoco/experimental/usd/mjcPhysics/siteAPI.h>
|
||||
#include <mujoco/experimental/usd/mjcPhysics/tendon.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "third_party/mujoco/plugin/usd_decoder/newton_tokens.h"
|
||||
#include <pxr/usd/sdf/path.h>
|
||||
#include <pxr/usd/usd/common.h>
|
||||
#include <pxr/usd/usd/primRange.h>
|
||||
#include <pxr/usd/usdGeom/gprim.h>
|
||||
#include <pxr/usd/usdGeom/xformCache.h>
|
||||
#include <pxr/usd/usdPhysics/articulationRootAPI.h>
|
||||
#include <pxr/usd/usdPhysics/collisionAPI.h>
|
||||
#include <pxr/usd/usdPhysics/joint.h>
|
||||
#include <pxr/usd/usdPhysics/rigidBodyAPI.h>
|
||||
#include <pxr/usd/usdPhysics/scene.h>
|
||||
|
||||
using mujoco::NewtonTokens;
|
||||
|
||||
bool GetJointBodies(const pxr::UsdPhysicsJoint& joint, pxr::SdfPath* from,
|
||||
pxr::SdfPath* to) {
|
||||
// Grab the default prim path
|
||||
@@ -106,7 +110,8 @@ ExtractedPrims ExtractPrims(pxr::UsdStageRefPtr stage) {
|
||||
for (auto it = range.begin(); it != range.end(); ++it) {
|
||||
pxr::UsdPrim prim = *it;
|
||||
|
||||
bool is_body = prim.HasAPI<pxr::UsdPhysicsRigidBodyAPI>();
|
||||
bool is_body = prim.HasAPI<pxr::UsdPhysicsRigidBodyAPI>() ||
|
||||
prim.HasAPI<pxr::UsdPhysicsArticulationRootAPI>();
|
||||
bool resets = xform_cache.GetResetXformStack(prim);
|
||||
// Only update (push/pop) the owner stack for bodies (becomes new owner) and
|
||||
// resetXformStack (reset owner to world).
|
||||
@@ -155,7 +160,8 @@ ExtractedPrims ExtractPrims(pxr::UsdStageRefPtr stage) {
|
||||
}
|
||||
}
|
||||
|
||||
if (prim.HasAPI<pxr::MjcPhysicsSiteAPI>()) {
|
||||
if (prim.HasAPI(NewtonTokens->NewtonSiteAPI) ||
|
||||
prim.HasAPI<pxr::MjcPhysicsSiteAPI>()) {
|
||||
current_node->sites.push_back(prim_path);
|
||||
// Sites should not have children.
|
||||
it.PruneChildren();
|
||||
@@ -248,9 +254,10 @@ std::unique_ptr<Node> BuildKinematicTree(const pxr::UsdStageRefPtr stage) {
|
||||
// nodes.
|
||||
extraction.nodes[to_idx]->joints.push_back(joint.GetPath());
|
||||
|
||||
// If the joint has MjcPhysicsEqualityJointAPI, also add it to constraints
|
||||
// If the joint has NewtonMimicAPI or MjcPhysicsEqualityJointAPI, also add it to constraints
|
||||
// so that ParseConstraint is called to create the equality constraint.
|
||||
if (joint.GetPrim().HasAPI<pxr::MjcPhysicsEqualityJointAPI>()) {
|
||||
if (joint.GetPrim().HasAPI(NewtonTokens->NewtonMimicAPI) ||
|
||||
joint.GetPrim().HasAPI<pxr::MjcPhysicsEqualityJointAPI>()) {
|
||||
extraction.nodes[to_idx]->constraints.push_back(joint.GetPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2025 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "third_party/mujoco/plugin/usd_decoder/newton_tokens.h"
|
||||
#include <pxr/base/tf/staticTokens.h>
|
||||
#include <pxr/pxr.h>
|
||||
|
||||
PXR_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
TF_DEFINE_PUBLIC_TOKENS(NewtonTokens, NEWTON_TOKENS);
|
||||
|
||||
PXR_NAMESPACE_CLOSE_SCOPE
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2025 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Shared static tokens for Newton USD Schemas.
|
||||
|
||||
#ifndef MUJOCO_PLUGIN_USD_DECODER_NEWTON_TOKENS_H_
|
||||
#define MUJOCO_PLUGIN_USD_DECODER_NEWTON_TOKENS_H_
|
||||
|
||||
#include <pxr/base/tf/staticTokens.h>
|
||||
#include <pxr/pxr.h>
|
||||
|
||||
PXR_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
// clang-format off
|
||||
#define NEWTON_TOKENS \
|
||||
((NewtonMaterialAPI, "NewtonMaterialAPI")) \
|
||||
((NewtonMeshCollisionAPI, "NewtonMeshCollisionAPI")) \
|
||||
((NewtonJointAPI, "NewtonJointAPI")) \
|
||||
((NewtonMassAPI, "NewtonMassAPI")) \
|
||||
((NewtonSiteAPI, "NewtonSiteAPI")) \
|
||||
((NewtonMimicAPI, "NewtonMimicAPI")) \
|
||||
((NewtonCollisionAPI, "NewtonCollisionAPI")) \
|
||||
((NewtonArticulationRootAPI, "NewtonArticulationRootAPI")) \
|
||||
((newtonMassModel, "newton:massModel")) \
|
||||
((newtonMaxSolverIterations, "newton:maxSolverIterations")) \
|
||||
((newtonTimeStepsPerSecond, "newton:timeStepsPerSecond")) \
|
||||
((newtonGravityEnabled, "newton:gravityEnabled")) \
|
||||
((newtonContactMargin, "newton:contactMargin")) \
|
||||
((newtonContactGap, "newton:contactGap")) \
|
||||
((newtonMaxHullVertices, "newton:maxHullVertices")) \
|
||||
((newtonTorsionalFriction, "newton:torsionalFriction")) \
|
||||
((newtonRollingFriction, "newton:rollingFriction")) \
|
||||
((newtonArmature, "newton:armature")) \
|
||||
((newtonDamping, "newton:damping")) \
|
||||
((newtonFriction, "newton:friction")) \
|
||||
((newtonMimicJoint, "newton:mimicJoint")) \
|
||||
((newtonMimicCoef0, "newton:mimicCoef0")) \
|
||||
((newtonMimicCoef1, "newton:mimicCoef1")) \
|
||||
((newtonInertia, "newton:inertia")) \
|
||||
((newtonContactAdhesion, "newton:contactAdhesion")) \
|
||||
((newtonJointsAddMobility, "newton:jointsAddMobility")) \
|
||||
((newtonSelfCollisionEnabled, "newton:selfCollisionEnabled"))
|
||||
// clang-format on
|
||||
|
||||
TF_DECLARE_PUBLIC_TOKENS(NewtonTokens, NEWTON_TOKENS);
|
||||
|
||||
PXR_NAMESPACE_CLOSE_SCOPE
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
using pxr::NewtonTokens;
|
||||
|
||||
} // namespace mujoco
|
||||
|
||||
#endif // MUJOCO_PLUGIN_USD_DECODER_NEWTON_TOKENS_H_
|
||||
@@ -74,38 +74,23 @@
|
||||
#include <pxr/usd/usdPhysics/joint.h>
|
||||
#include <pxr/usd/usdPhysics/massAPI.h>
|
||||
#include <pxr/usd/usdPhysics/materialAPI.h>
|
||||
#include <pxr/usd/usdPhysics/meshCollisionAPI.h>
|
||||
#include <pxr/usd/usdPhysics/prismaticJoint.h>
|
||||
#include <pxr/usd/usdPhysics/revoluteJoint.h>
|
||||
#include <pxr/usd/usdPhysics/rigidBodyAPI.h>
|
||||
#include <pxr/usd/usdPhysics/scene.h>
|
||||
#include <pxr/usd/usdPhysics/sphericalJoint.h>
|
||||
#include <pxr/usd/usdPhysics/tokens.h>
|
||||
#include <pxr/usd/usdShade/material.h>
|
||||
#include "third_party/mujoco/plugin/usd_decoder/newton_tokens.h"
|
||||
#include <pxr/usd/usdShade/materialBindingAPI.h>
|
||||
|
||||
using pxr::MjcPhysicsTokens;
|
||||
using pxr::TfToken;
|
||||
using mujoco::NewtonTokens;
|
||||
template <typename T>
|
||||
using TfStaticData = pxr::TfStaticData<T>;
|
||||
|
||||
// clang-format off
|
||||
TF_DEFINE_PRIVATE_TOKENS(kNewtonTokens,
|
||||
((NewtonMaterialAPI, "NewtonMaterialAPI"))
|
||||
((NewtonMeshCollisionAPI, "NewtonMeshCollisionAPI"))
|
||||
((newtonMaxSolverIterations, "newton:maxSolverIterations"))
|
||||
((newtonTimeStepsPerSecond, "newton:timeStepsPerSecond"))
|
||||
((newtonGravityEnabled, "newton:gravityEnabled"))
|
||||
((newtonContactMargin, "newton:contactMargin"))
|
||||
((newtonContactGap, "newton:contactGap"))
|
||||
((newtonMaxHullVertices, "newton:maxHullVertices"))
|
||||
((newtonTorsionalFriction, "newton:torsionalFriction"))
|
||||
((newtonRollingFriction, "newton:rollingFriction"))
|
||||
((newtonMimicJoint, "newton:mimicJoint"))
|
||||
((newtonMimicCoef0, "newton:mimicCoef0"))
|
||||
((newtonMimicCoef1, "newton:mimicCoef1"))
|
||||
((NewtonMimicAPI, "NewtonMimicAPI"))
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
struct UsdCaches {
|
||||
pxr::UsdGeomXformCache xform_cache;
|
||||
pxr::UsdShadeMaterialBindingAPI::BindingsCache bindings_cache;
|
||||
@@ -489,21 +474,21 @@ void ParseUsdPhysicsScene(mjSpec* spec,
|
||||
// Parse Newton scene attributes if present (works for Newton-only files)
|
||||
pxr::UsdPrim scene_prim = physics_scene.GetPrim();
|
||||
auto newton_iterations = scene_prim.GetAttribute(
|
||||
kNewtonTokens->newtonMaxSolverIterations);
|
||||
NewtonTokens->newtonMaxSolverIterations);
|
||||
if (newton_iterations && newton_iterations.HasAuthoredValue()) {
|
||||
int val;
|
||||
newton_iterations.Get(&val);
|
||||
if (val >= 0) spec->option.iterations = val;
|
||||
}
|
||||
auto newton_timesteps = scene_prim.GetAttribute(
|
||||
kNewtonTokens->newtonTimeStepsPerSecond);
|
||||
NewtonTokens->newtonTimeStepsPerSecond);
|
||||
if (newton_timesteps && newton_timesteps.HasAuthoredValue()) {
|
||||
int val;
|
||||
newton_timesteps.Get(&val);
|
||||
if (val > 0) spec->option.timestep = 1.0 / val;
|
||||
}
|
||||
auto newton_gravity = scene_prim.GetAttribute(
|
||||
kNewtonTokens->newtonGravityEnabled);
|
||||
NewtonTokens->newtonGravityEnabled);
|
||||
if (newton_gravity && newton_gravity.HasAuthoredValue()) {
|
||||
bool enabled;
|
||||
newton_gravity.Get(&enabled);
|
||||
@@ -904,6 +889,16 @@ void ParseUsdPhysicsMassAPIForBody(mjsBody* body,
|
||||
diag_inertia_attr.Get(&diag_inertia);
|
||||
SetDoubleArrFromGfVec3d(body->inertia, diag_inertia);
|
||||
}
|
||||
|
||||
auto newton_inertia_attr =
|
||||
mass_api.GetPrim().GetAttribute(NewtonTokens->newtonInertia);
|
||||
if (newton_inertia_attr && newton_inertia_attr.HasAuthoredValue()) {
|
||||
pxr::VtDoubleArray inertia;
|
||||
newton_inertia_attr.Get(&inertia);
|
||||
if (inertia.size() == 6) {
|
||||
std::copy(inertia.begin(), inertia.end(), body->fullinertia);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParseUsdPhysicsMassAPIForGeom(mjsGeom* geom,
|
||||
@@ -923,15 +918,40 @@ void ParseUsdPhysicsMassAPIForGeom(mjsGeom* geom,
|
||||
}
|
||||
}
|
||||
|
||||
void ParseMjcPhysicsCollisionAPI(
|
||||
mjsGeom* geom, const pxr::MjcPhysicsCollisionAPI& collision_api) {
|
||||
auto shell_inertia_attr = collision_api.GetShellInertiaAttr();
|
||||
if (shell_inertia_attr.HasAuthoredValue()) {
|
||||
void ParseNewtonMassAPIForGeom(mjsGeom* geom, const pxr::UsdPrim& prim) {
|
||||
auto shell_inertia_attr =
|
||||
prim.GetAttribute(MjcPhysicsTokens->mjcShellinertia);
|
||||
auto newton_mass_model_attr =
|
||||
prim.GetAttribute(NewtonTokens->newtonMassModel);
|
||||
|
||||
bool shell_inertia_authored =
|
||||
shell_inertia_attr && shell_inertia_attr.HasAuthoredValue();
|
||||
bool newton_mass_model_authored =
|
||||
newton_mass_model_attr && newton_mass_model_attr.HasAuthoredValue();
|
||||
|
||||
if (shell_inertia_authored) {
|
||||
bool shell_inertia;
|
||||
shell_inertia_attr.Get(&shell_inertia);
|
||||
geom->typeinertia = shell_inertia ? mjtGeomInertia::mjINERTIA_SHELL
|
||||
: mjtGeomInertia::mjINERTIA_VOLUME;
|
||||
mju_warning(
|
||||
"Prim '%s' uses deprecated mjc:shellinertia. "
|
||||
"Please migrate to NewtonMassAPI's newton:massModel.",
|
||||
prim.GetPath().GetText());
|
||||
} else if (newton_mass_model_authored) {
|
||||
pxr::TfToken mass_model;
|
||||
newton_mass_model_attr.Get(&mass_model);
|
||||
if (mass_model == MjcPhysicsTokens->shell) {
|
||||
geom->typeinertia = mjtGeomInertia::mjINERTIA_SHELL;
|
||||
} else {
|
||||
geom->typeinertia = mjtGeomInertia::mjINERTIA_VOLUME;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParseMjcPhysicsCollisionAPI(
|
||||
mjsGeom* geom, const pxr::MjcPhysicsCollisionAPI& collision_api) {
|
||||
ParseNewtonMassAPIForGeom(geom, collision_api.GetPrim());
|
||||
|
||||
auto group_attr = collision_api.GetGroupAttr();
|
||||
if (group_attr.HasAuthoredValue()) {
|
||||
@@ -1006,8 +1026,8 @@ void ParseMjcPhysicsCollisionAPI(
|
||||
// Newton collision fallback: newton:contactMargin + newton:contactGap -> margin, gap
|
||||
if (!mjc_margin_authored || !mjc_gap_authored) {
|
||||
pxr::UsdPrim prim = collision_api.GetPrim();
|
||||
auto newton_margin = prim.GetAttribute(kNewtonTokens->newtonContactMargin);
|
||||
auto newton_gap = prim.GetAttribute(kNewtonTokens->newtonContactGap);
|
||||
auto newton_margin = prim.GetAttribute(NewtonTokens->newtonContactMargin);
|
||||
auto newton_gap = prim.GetAttribute(NewtonTokens->newtonContactGap);
|
||||
float n_margin = 0, n_gap = 0;
|
||||
bool has_newton_margin = newton_margin && newton_margin.HasAuthoredValue();
|
||||
bool has_newton_gap = newton_gap && newton_gap.HasAuthoredValue();
|
||||
@@ -1025,7 +1045,14 @@ void ParseMjcPhysicsCollisionAPI(
|
||||
void ParseMjcPhysicsMeshCollisionAPI(
|
||||
mjsMesh* mesh, const pxr::MjcPhysicsMeshCollisionAPI& mesh_collision_api) {
|
||||
auto inertia_attr = mesh_collision_api.GetInertiaAttr();
|
||||
if (inertia_attr.HasAuthoredValue()) {
|
||||
auto newton_mass_model_attr =
|
||||
mesh_collision_api.GetPrim().GetAttribute(NewtonTokens->newtonMassModel);
|
||||
|
||||
bool inertia_authored = inertia_attr.HasAuthoredValue();
|
||||
bool newton_mass_model_authored =
|
||||
newton_mass_model_attr && newton_mass_model_attr.HasAuthoredValue();
|
||||
|
||||
if (inertia_authored) {
|
||||
pxr::TfToken inertia;
|
||||
inertia_attr.Get(&inertia);
|
||||
if (inertia == MjcPhysicsTokens->shell) {
|
||||
@@ -1037,11 +1064,41 @@ void ParseMjcPhysicsMeshCollisionAPI(
|
||||
} else {
|
||||
mesh->inertia = mjtMeshInertia::mjMESH_INERTIA_LEGACY;
|
||||
}
|
||||
mju_warning(
|
||||
"Prim '%s' uses deprecated mjc:inertia. "
|
||||
"Please migrate to NewtonMassAPI's newton:massModel.",
|
||||
mesh_collision_api.GetPrim().GetPath().GetText());
|
||||
} else {
|
||||
pxr::TfToken mass_model;
|
||||
bool is_shell = false;
|
||||
if (newton_mass_model_authored) {
|
||||
newton_mass_model_attr.Get(&mass_model);
|
||||
if (mass_model == MjcPhysicsTokens->shell) {
|
||||
mesh->inertia = mjtMeshInertia::mjMESH_INERTIA_SHELL;
|
||||
is_shell = true;
|
||||
} else {
|
||||
mesh->inertia = mjtMeshInertia::mjMESH_INERTIA_EXACT;
|
||||
}
|
||||
}
|
||||
|
||||
// MuJoCo does not support shell inertia computation of convex
|
||||
// representation.
|
||||
if (!is_shell) {
|
||||
pxr::UsdPhysicsMeshCollisionAPI usd_mesh_api(
|
||||
mesh_collision_api.GetPrim());
|
||||
pxr::TfToken approx;
|
||||
usd_mesh_api.GetApproximationAttr().Get(&approx);
|
||||
if (approx == pxr::UsdPhysicsTokens->convexHull) {
|
||||
mesh->inertia = mjtMeshInertia::mjMESH_INERTIA_CONVEX;
|
||||
} else {
|
||||
mesh->inertia = mjtMeshInertia::mjMESH_INERTIA_EXACT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto maxhullvert_attr = mesh_collision_api.GetMaxHullVertAttr();
|
||||
auto newton_maxhull = mesh_collision_api.GetPrim().GetAttribute(
|
||||
kNewtonTokens->newtonMaxHullVertices);
|
||||
NewtonTokens->newtonMaxHullVertices);
|
||||
if (maxhullvert_attr.HasAuthoredValue()) {
|
||||
maxhullvert_attr.Get(&mesh->maxhullvert);
|
||||
if (!newton_maxhull || !newton_maxhull.HasAuthoredValue()) {
|
||||
@@ -1726,25 +1783,72 @@ void ParseMjcPhysicsJointAPI(mjsJoint* mj_joint,
|
||||
mj_joint->springref = springref;
|
||||
}
|
||||
|
||||
auto armature_attr = joint_api.GetMjcArmatureAttr();
|
||||
if (armature_attr.HasAuthoredValue()) {
|
||||
double armature;
|
||||
armature_attr.Get(&armature);
|
||||
auto mjc_armature_attr =
|
||||
joint_api.GetPrim().GetAttribute(MjcPhysicsTokens->mjcArmature);
|
||||
auto mjc_damping_attr =
|
||||
joint_api.GetPrim().GetAttribute(MjcPhysicsTokens->mjcDamping);
|
||||
auto mjc_frictionloss_attr =
|
||||
joint_api.GetPrim().GetAttribute(MjcPhysicsTokens->mjcFrictionloss);
|
||||
|
||||
auto newton_armature_attr =
|
||||
joint_api.GetPrim().GetAttribute(NewtonTokens->newtonArmature);
|
||||
auto newton_damping_attr =
|
||||
joint_api.GetPrim().GetAttribute(NewtonTokens->newtonDamping);
|
||||
auto newton_friction_attr =
|
||||
joint_api.GetPrim().GetAttribute(NewtonTokens->newtonFriction);
|
||||
|
||||
bool mjc_armature_authored =
|
||||
mjc_armature_attr && mjc_armature_attr.HasAuthoredValue();
|
||||
bool mjc_damping_authored =
|
||||
mjc_damping_attr && mjc_damping_attr.HasAuthoredValue();
|
||||
bool mjc_frictionloss_authored =
|
||||
mjc_frictionloss_attr && mjc_frictionloss_attr.HasAuthoredValue();
|
||||
|
||||
bool newton_armature_authored =
|
||||
newton_armature_attr && newton_armature_attr.HasAuthoredValue();
|
||||
bool newton_damping_authored =
|
||||
newton_damping_attr && newton_damping_attr.HasAuthoredValue();
|
||||
bool newton_friction_authored =
|
||||
newton_friction_attr && newton_friction_attr.HasAuthoredValue();
|
||||
|
||||
if (mjc_armature_authored) {
|
||||
mjc_armature_attr.Get(&mj_joint->armature);
|
||||
mju_warning(
|
||||
"Prim '%s' uses deprecated mjc:armature. "
|
||||
"Please migrate to newton:armature.",
|
||||
joint_api.GetPrim().GetPath().GetText());
|
||||
} else if (newton_armature_authored) {
|
||||
float armature;
|
||||
newton_armature_attr.Get(&armature);
|
||||
mj_joint->armature = armature;
|
||||
}
|
||||
|
||||
auto damping_attr = joint_api.GetMjcDampingAttr();
|
||||
if (damping_attr.HasAuthoredValue()) {
|
||||
if (mjc_damping_authored) {
|
||||
double damping;
|
||||
damping_attr.Get(&damping);
|
||||
mjc_damping_attr.Get(&damping);
|
||||
mj_joint->damping[0] = damping;
|
||||
mju_warning(
|
||||
"Prim '%s' uses deprecated mjc:damping. "
|
||||
"Please migrate to newton:damping.",
|
||||
joint_api.GetPrim().GetPath().GetText());
|
||||
} else if (newton_damping_authored) {
|
||||
float damping;
|
||||
newton_damping_attr.Get(&damping);
|
||||
mj_joint->damping[0] = damping;
|
||||
}
|
||||
|
||||
auto frictionloss_attr = joint_api.GetMjcFrictionlossAttr();
|
||||
if (frictionloss_attr.HasAuthoredValue()) {
|
||||
if (mjc_frictionloss_authored) {
|
||||
double frictionloss;
|
||||
frictionloss_attr.Get(&frictionloss);
|
||||
mjc_frictionloss_attr.Get(&frictionloss);
|
||||
mj_joint->frictionloss = frictionloss;
|
||||
mju_warning(
|
||||
"Prim '%s' uses deprecated mjc:frictionloss. "
|
||||
"Please migrate to newton:friction.",
|
||||
joint_api.GetPrim().GetPath().GetText());
|
||||
} else if (newton_friction_authored) {
|
||||
float friction;
|
||||
newton_friction_attr.Get(&friction);
|
||||
mj_joint->frictionloss = friction;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1784,7 +1888,7 @@ void ParseMjcPhysicsMaterialAPI(
|
||||
// mjc takes precedence for backwards compatibility.
|
||||
auto mjc_torsional = material_api.GetTorsionalFrictionAttr();
|
||||
auto newton_torsional = material_prim.GetAttribute(
|
||||
kNewtonTokens->newtonTorsionalFriction);
|
||||
NewtonTokens->newtonTorsionalFriction);
|
||||
if (mjc_torsional.HasAuthoredValue()) {
|
||||
mjc_torsional.Get(&geom->friction[1]);
|
||||
if (!newton_torsional || !newton_torsional.HasAuthoredValue()) {
|
||||
@@ -1801,7 +1905,7 @@ void ParseMjcPhysicsMaterialAPI(
|
||||
// Rolling friction: same deprecation/fallback pattern.
|
||||
auto mjc_rolling = material_api.GetRollingFrictionAttr();
|
||||
auto newton_rolling = material_prim.GetAttribute(
|
||||
kNewtonTokens->newtonRollingFriction);
|
||||
NewtonTokens->newtonRollingFriction);
|
||||
if (mjc_rolling.HasAuthoredValue()) {
|
||||
mjc_rolling.Get(&geom->friction[2]);
|
||||
if (!newton_rolling || !newton_rolling.HasAuthoredValue()) {
|
||||
@@ -1814,6 +1918,17 @@ void ParseMjcPhysicsMaterialAPI(
|
||||
newton_rolling.Get(&val);
|
||||
geom->friction[2] = val;
|
||||
}
|
||||
|
||||
// Contact adhesion: newton:contactAdhesion -> geom->adhesion
|
||||
auto newton_adhesion = material_prim.GetAttribute(
|
||||
NewtonTokens->newtonContactAdhesion);
|
||||
if (newton_adhesion && newton_adhesion.HasAuthoredValue()) {
|
||||
float val;
|
||||
newton_adhesion.Get(&val);
|
||||
if (val >= 0.0f) {
|
||||
geom->adhesion = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParseDisplayColorAndOpacity(const pxr::UsdPrim& prim, mjsGeom* geom) {
|
||||
@@ -1858,12 +1973,15 @@ void ParseUsdGeomGprim(mjSpec* spec, const pxr::UsdPrim& gprim,
|
||||
SetLocalPoseFromPrim(gprim, body_prim, geom, caches.xform_cache);
|
||||
if (!MaybeParseGeomPrimitive(gprim, geom, caches.xform_cache)) {
|
||||
mjsMesh* mesh = ParseUsdMesh(spec, gprim, geom, caches.xform_cache);
|
||||
if (mesh != nullptr && gprim.HasAPI<pxr::MjcPhysicsMeshCollisionAPI>()) {
|
||||
if (mesh != nullptr &&
|
||||
(gprim.HasAPI<pxr::MjcPhysicsMeshCollisionAPI>())) {
|
||||
ParseMjcPhysicsMeshCollisionAPI(mesh,
|
||||
pxr::MjcPhysicsMeshCollisionAPI(gprim));
|
||||
}
|
||||
}
|
||||
|
||||
ParseNewtonMassAPIForGeom(geom, gprim);
|
||||
|
||||
pxr::UsdShadeMaterial bound_material =
|
||||
pxr::UsdShadeMaterialBindingAPI(gprim).ComputeBoundMaterial(
|
||||
&caches.bindings_cache, &caches.collection_query_cache);
|
||||
@@ -1915,6 +2033,7 @@ void ParseUsdPhysicsCollider(mjSpec* spec,
|
||||
|
||||
SetUsdPrimPathUserValue(geom->element, prim.GetPath());
|
||||
|
||||
ParseNewtonMassAPIForGeom(geom, prim);
|
||||
if (prim.HasAPI<pxr::MjcPhysicsCollisionAPI>()) {
|
||||
ParseMjcPhysicsCollisionAPI(geom, pxr::MjcPhysicsCollisionAPI(prim));
|
||||
}
|
||||
@@ -1926,7 +2045,7 @@ void ParseUsdPhysicsCollider(mjSpec* spec,
|
||||
pxr::UsdPrim bound_material_prim = bound_material.GetPrim();
|
||||
if (bound_material_prim.HasAPI<pxr::UsdPhysicsMaterialAPI>() ||
|
||||
bound_material_prim.HasAPI<pxr::MjcPhysicsMaterialAPI>() ||
|
||||
bound_material_prim.HasAPI(kNewtonTokens->NewtonMaterialAPI)) {
|
||||
bound_material_prim.HasAPI(NewtonTokens->NewtonMaterialAPI)) {
|
||||
ParseUsdPhysicsMaterialAPI(
|
||||
geom, pxr::UsdPhysicsMaterialAPI(bound_material_prim));
|
||||
ParseMjcPhysicsMaterialAPI(
|
||||
@@ -1966,7 +2085,8 @@ void ParseUsdPhysicsCollider(mjSpec* spec,
|
||||
mjsMesh* mesh = ParseUsdMesh(spec, prim, geom, caches.xform_cache);
|
||||
if (mesh != nullptr &&
|
||||
(prim.HasAPI<pxr::MjcPhysicsMeshCollisionAPI>() ||
|
||||
prim.HasAPI(kNewtonTokens->NewtonMeshCollisionAPI))) {
|
||||
prim.HasAPI(NewtonTokens->NewtonMeshCollisionAPI) ||
|
||||
prim.HasAPI(NewtonTokens->NewtonMassAPI))) {
|
||||
ParseMjcPhysicsMeshCollisionAPI(mesh,
|
||||
pxr::MjcPhysicsMeshCollisionAPI(prim));
|
||||
}
|
||||
@@ -2017,8 +2137,8 @@ void ParseMjcEqualityAPISolverParams(
|
||||
|
||||
void ParseConstraint(mjSpec* spec, const pxr::UsdPrim& prim, mjsBody* body,
|
||||
pxr::UsdGeomXformCache& xform_cache) {
|
||||
if (prim.HasAPI<pxr::MjcPhysicsEqualityJointAPI>() ||
|
||||
prim.HasAPI(kNewtonTokens->NewtonMimicAPI)) {
|
||||
if (prim.HasAPI(NewtonTokens->NewtonMimicAPI) ||
|
||||
prim.HasAPI<pxr::MjcPhysicsEqualityJointAPI>()) {
|
||||
pxr::MjcPhysicsEqualityJointAPI eq_joint_api(prim);
|
||||
mjsEquality* eq = mjs_addEquality(spec, nullptr);
|
||||
eq->type = mjEQ_JOINT;
|
||||
@@ -2031,7 +2151,7 @@ void ParseConstraint(mjSpec* spec, const pxr::UsdPrim& prim, mjsBody* body,
|
||||
|
||||
// Target joint: prefer newton:mimicJoint, fall back to deprecated mjc:target
|
||||
pxr::SdfPathVector targets;
|
||||
auto newton_mimic_rel = prim.GetRelationship(kNewtonTokens->newtonMimicJoint);
|
||||
auto newton_mimic_rel = prim.GetRelationship(NewtonTokens->newtonMimicJoint);
|
||||
if (newton_mimic_rel && newton_mimic_rel.GetTargets(&targets) && !targets.empty()) {
|
||||
mjs_setString(eq->name2, targets[0].GetAsString().c_str());
|
||||
} else {
|
||||
@@ -2045,8 +2165,8 @@ void ParseConstraint(mjSpec* spec, const pxr::UsdPrim& prim, mjsBody* body,
|
||||
}
|
||||
|
||||
// Coefficients: prefer Newton, fall back to deprecated MJC
|
||||
auto newton_coef0 = prim.GetAttribute(kNewtonTokens->newtonMimicCoef0);
|
||||
auto newton_coef1 = prim.GetAttribute(kNewtonTokens->newtonMimicCoef1);
|
||||
auto newton_coef0 = prim.GetAttribute(NewtonTokens->newtonMimicCoef0);
|
||||
auto newton_coef1 = prim.GetAttribute(NewtonTokens->newtonMimicCoef1);
|
||||
if (newton_coef0 && newton_coef0.HasAuthoredValue()) {
|
||||
float val;
|
||||
newton_coef0.Get(&val);
|
||||
@@ -2369,30 +2489,32 @@ void ParseUsdPhysicsJoint(mjSpec* spec, const pxr::UsdPrim& prim, mjsBody* body,
|
||||
SetDoubleArrFromGfVec3d(mj_joint->axis, rotated_axis);
|
||||
}
|
||||
|
||||
if (prim.HasAPI<pxr::MjcPhysicsJointAPI>()) {
|
||||
if (prim.HasAPI<pxr::MjcPhysicsJointAPI>() ||
|
||||
prim.HasAPI(NewtonTokens->NewtonJointAPI)) {
|
||||
ParseMjcPhysicsJointAPI(mj_joint, pxr::MjcPhysicsJointAPI(prim));
|
||||
}
|
||||
}
|
||||
|
||||
void ParseMjcPhysicsSite(mjSpec* spec, const pxr::MjcPhysicsSiteAPI& site_api,
|
||||
void ParseSite(mjSpec* spec, const pxr::UsdPrim& prim,
|
||||
const pxr::UsdPrim& parent_prim, mjsBody* parent,
|
||||
pxr::UsdGeomXformCache& xform_cache) {
|
||||
auto prim = site_api.GetPrim();
|
||||
mjsSite* site = mjs_addSite(parent, 0);
|
||||
mjs_setName(site->element,
|
||||
site_api.GetPrim().GetPath().GetAsString().c_str());
|
||||
SetLocalPoseFromPrim(site_api.GetPrim(), parent_prim, site, xform_cache);
|
||||
mjs_setName(site->element, prim.GetPath().GetAsString().c_str());
|
||||
SetLocalPoseFromPrim(prim, parent_prim, site, xform_cache);
|
||||
|
||||
SetUsdPrimPathUserValue(site->element, prim.GetPath());
|
||||
|
||||
auto group_attr = site_api.GetGroupAttr();
|
||||
if (group_attr.HasAuthoredValue()) {
|
||||
group_attr.Get(&site->group);
|
||||
if (prim.HasAPI<pxr::MjcPhysicsSiteAPI>()) {
|
||||
auto site_api = pxr::MjcPhysicsSiteAPI(prim);
|
||||
auto group_attr = site_api.GetGroupAttr();
|
||||
if (group_attr.HasAuthoredValue()) {
|
||||
group_attr.Get(&site->group);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert USD type to MuJoCo type.
|
||||
if (!MaybeParseGeomPrimitive(prim, site, xform_cache)) {
|
||||
mju_error("Prim with SiteAPI has unsupported typej %s",
|
||||
mju_error("Prim with SiteAPI has unsupported type %s",
|
||||
prim.GetTypeName().GetString().c_str());
|
||||
return;
|
||||
}
|
||||
@@ -2474,6 +2596,22 @@ void ParseUsdFilteredPairsAPI(mjSpec* spec, const pxr::UsdPrim& prim) {
|
||||
}
|
||||
}
|
||||
|
||||
void ParseNewtonArticulationRootAPI(mjSpec* spec, const pxr::UsdPrim& prim) {
|
||||
auto add_mobility_attr =
|
||||
prim.GetAttribute(NewtonTokens->newtonJointsAddMobility);
|
||||
if (add_mobility_attr && add_mobility_attr.HasAuthoredValue()) {
|
||||
bool add_mobility;
|
||||
add_mobility_attr.Get(&add_mobility);
|
||||
if (!add_mobility) {
|
||||
mju_warning(
|
||||
"Prim '%s' has newton:jointsAddMobility set to false, but MuJoCo "
|
||||
"only supports reduced-coordinate formulations where joints add "
|
||||
"mobility. Joints will be treated as adding mobility.",
|
||||
prim.GetPath().GetText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mjsBody* ParseUsdPhysicsRigidbody(
|
||||
mjSpec* spec, const pxr::UsdPhysicsRigidBodyAPI& rigidbody_api,
|
||||
const pxr::UsdPrim& parent_prim, mjsBody* parent,
|
||||
@@ -2487,6 +2625,10 @@ mjsBody* ParseUsdPhysicsRigidbody(
|
||||
ParseUsdPhysicsMassAPIForBody(body, pxr::UsdPhysicsMassAPI(prim));
|
||||
}
|
||||
|
||||
if (prim.HasAPI(NewtonTokens->NewtonArticulationRootAPI)) {
|
||||
ParseNewtonArticulationRootAPI(spec, prim);
|
||||
}
|
||||
|
||||
// The value is a pointer to a newly allocated SdfPath, which will be deleted
|
||||
// when the mjsElement is deleted.
|
||||
const pxr::SdfPath* usd_primpath = new pxr::SdfPath(prim.GetPath());
|
||||
@@ -2575,8 +2717,8 @@ void PopulateSpecFromTree(pxr::UsdStageRefPtr stage, mjSpec* spec,
|
||||
}
|
||||
|
||||
for (const auto& site_path : current_node->sites) {
|
||||
ParseMjcPhysicsSite(
|
||||
spec, pxr::MjcPhysicsSiteAPI(stage->GetPrimAtPath(site_path)),
|
||||
ParseSite(
|
||||
spec, stage->GetPrimAtPath(site_path),
|
||||
body_prim_for_xform, current_mj_body, caches.xform_cache);
|
||||
}
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ function(install_newton_usd_plugin install_base_dir)
|
||||
FetchContent_Declare(
|
||||
newton-usd-schemas
|
||||
GIT_REPOSITORY https://github.com/newton-physics/newton-usd-schemas.git
|
||||
GIT_TAG v0.1.0rc3
|
||||
GIT_TAG v0.4.0
|
||||
GIT_SHALLOW TRUE
|
||||
UPDATE_DISCONNECTED TRUE
|
||||
)
|
||||
|
||||
@@ -290,6 +290,7 @@ class "MjcSceneAPI" (
|
||||
}
|
||||
|
||||
class "MjcSiteAPI" (
|
||||
apiSchemas = ["NewtonSiteAPI"]
|
||||
doc = "API describing a MuJoCo site."
|
||||
)
|
||||
{
|
||||
@@ -340,7 +341,9 @@ class "MjcCollisionAPI" (
|
||||
)
|
||||
uniform bool mjc:shellinertia = 0 (
|
||||
displayName = "Shell Inertia"
|
||||
doc = "Enables handling of the inertia assuming mass is concentrated on the surface."
|
||||
doc = """DEPRECATED: Use NewtonMassAPI's newton:massModel = \"shell\" instead.
|
||||
|
||||
Enables handling of the inertia assuming mass is concentrated on the surface."""
|
||||
)
|
||||
uniform double[] mjc:solimp = [0.9, 0.95, 0.001, 0.5, 2] (
|
||||
displayName = "SolImp"
|
||||
@@ -364,7 +367,9 @@ class "MjcMeshCollisionAPI" (
|
||||
uniform token mjc:inertia = "legacy" (
|
||||
allowedTokens = ["legacy", "convex", "exact", "shell"]
|
||||
displayName = "Inertia"
|
||||
doc = "Controls how a mesh is used when mass and inertia are inferred from geometry."
|
||||
doc = """DEPRECATED: Use NewtonMassAPI's newton:massModel or UsdPhysics's physics:approximation instead.
|
||||
|
||||
Controls how a mesh is used when mass and inertia are inferred from geometry."""
|
||||
)
|
||||
uniform int mjc:maxhullvert = -1 (
|
||||
displayName = "Maximum Hull Vertices"
|
||||
@@ -493,6 +498,7 @@ class MjcKeyframe "MjcKeyframe" (
|
||||
}
|
||||
|
||||
class "MjcJointAPI" (
|
||||
apiSchemas = ["NewtonJointAPI"]
|
||||
doc = "API describing a MuJoCo joint."
|
||||
)
|
||||
{
|
||||
@@ -510,13 +516,19 @@ class "MjcJointAPI" (
|
||||
doc = "If this flag is enabled, gravity compensation applied to this joint is added to actuator forces (mjData.qfrc_actuator) rather than passive forces (mjData.qfrc_passive). Notionally, this means that gravity compensation is the result of a control system rather than natural buoyancy. In practice, enabling this flag is useful when joint-level actuator force clamping is used. In this case, the total actuation force applied on a joint, including gravity compensation, is guaranteed to not exceed the specified limits. See Force limits and actuatorfrcrange for more details on this type of force limit."
|
||||
)
|
||||
uniform double mjc:armature = 0 (
|
||||
doc = "Additional inertia associated with movement of the joint that is not due to body mass. This added inertia is usually due to a rotor (a.k.a armature) spinning faster than the joint itself due to a geared transmission. The value applies to all degrees of freedom created by this joint. Besides increasing the realism of joints with geared transmission, positive armature significantly improves simulation stability, even for small values, and is a recommended possible fix when encountering stability issues."
|
||||
doc = """DEPRECATED: Use newton:armature instead.
|
||||
|
||||
Additional inertia associated with movement of the joint that is not due to body mass. This added inertia is usually due to a rotor (a.k.a armature) spinning faster than the joint itself due to a geared transmission. The value applies to all degrees of freedom created by this joint. Besides increasing the realism of joints with geared transmission, positive armature significantly improves simulation stability, even for small values, and is a recommended possible fix when encountering stability issues."""
|
||||
)
|
||||
uniform double mjc:damping = 0 (
|
||||
doc = "Damping applied to all degrees of freedom created by this joint. Unlike friction loss which is computed by the constraint solver, damping is simply a force linear in velocity. It is included in the passive forces. Despite this simplicity, larger damping values can make numerical integrators unstable, which is why our Euler integrator handles damping implicitly. See Integration in the Computation chapter."
|
||||
doc = """DEPRECATED: Use newton:damping instead.
|
||||
|
||||
Damping applied to all degrees of freedom created by this joint. Unlike friction loss which is computed by the constraint solver, damping is simply a force linear in velocity. It is included in the passive forces. Despite this simplicity, larger damping values can make numerical integrators unstable, which is why our Euler integrator handles damping implicitly. See Integration in the Computation chapter."""
|
||||
)
|
||||
uniform double mjc:frictionloss = 0 (
|
||||
doc = "Friction loss due to dry friction. This value is the same for all degrees of freedom created by this joint. Semantically friction loss does not make sense for free joints, but the compiler allows it. To enable friction loss, set this attribute to a positive value."
|
||||
doc = """DEPRECATED: Use newton:friction instead.
|
||||
|
||||
Friction loss due to dry friction. This value is the same for all degrees of freedom created by this joint. Semantically friction loss does not make sense for free joints, but the compiler allows it. To enable friction loss, set this attribute to a positive value."""
|
||||
)
|
||||
uniform int mjc:group = 0 (
|
||||
displayName = "Group"
|
||||
|
||||
@@ -643,6 +643,7 @@ class "MjcSiteAPI"
|
||||
}
|
||||
doc = """API describing a MuJoCo site."""
|
||||
|
||||
prepend apiSchemas = ["NewtonSiteAPI"]
|
||||
inherits = </APISchemaBase>
|
||||
)
|
||||
{
|
||||
@@ -698,7 +699,9 @@ class "MjcCollisionAPI"
|
||||
string apiName = "ShellInertia"
|
||||
}
|
||||
displayName = "Shell Inertia"
|
||||
doc = """Enables handling of the inertia assuming mass is concentrated on the surface."""
|
||||
doc = """DEPRECATED: Use NewtonMassAPI's newton:massModel = "shell" instead.
|
||||
|
||||
Enables handling of the inertia assuming mass is concentrated on the surface."""
|
||||
)
|
||||
|
||||
uniform int mjc:priority = 0 (
|
||||
@@ -779,7 +782,9 @@ class "MjcMeshCollisionAPI"
|
||||
string apiName = "Inertia"
|
||||
}
|
||||
displayName = "Inertia"
|
||||
doc = """Controls how a mesh is used when mass and inertia are inferred from geometry."""
|
||||
doc = """DEPRECATED: Use NewtonMassAPI's newton:massModel or UsdPhysics's physics:approximation instead.
|
||||
|
||||
Controls how a mesh is used when mass and inertia are inferred from geometry."""
|
||||
)
|
||||
|
||||
uniform int mjc:maxhullvert = -1 (
|
||||
@@ -968,6 +973,7 @@ class "MjcJointAPI"
|
||||
}
|
||||
doc = """API describing a MuJoCo joint."""
|
||||
|
||||
prepend apiSchemas = ["NewtonJointAPI"]
|
||||
inherits = </APISchemaBase>
|
||||
)
|
||||
{
|
||||
@@ -1033,15 +1039,21 @@ class "MjcJointAPI"
|
||||
)
|
||||
|
||||
uniform double mjc:armature = 0 (
|
||||
doc = "Additional inertia associated with movement of the joint that is not due to body mass. This added inertia is usually due to a rotor (a.k.a armature) spinning faster than the joint itself due to a geared transmission. The value applies to all degrees of freedom created by this joint. Besides increasing the realism of joints with geared transmission, positive armature significantly improves simulation stability, even for small values, and is a recommended possible fix when encountering stability issues."
|
||||
doc = """DEPRECATED: Use newton:armature instead.
|
||||
|
||||
Additional inertia associated with movement of the joint that is not due to body mass. This added inertia is usually due to a rotor (a.k.a armature) spinning faster than the joint itself due to a geared transmission. The value applies to all degrees of freedom created by this joint. Besides increasing the realism of joints with geared transmission, positive armature significantly improves simulation stability, even for small values, and is a recommended possible fix when encountering stability issues."""
|
||||
)
|
||||
|
||||
uniform double mjc:damping = 0 (
|
||||
doc = "Damping applied to all degrees of freedom created by this joint. Unlike friction loss which is computed by the constraint solver, damping is simply a force linear in velocity. It is included in the passive forces. Despite this simplicity, larger damping values can make numerical integrators unstable, which is why our Euler integrator handles damping implicitly. See Integration in the Computation chapter."
|
||||
doc = """DEPRECATED: Use newton:damping instead.
|
||||
|
||||
Damping applied to all degrees of freedom created by this joint. Unlike friction loss which is computed by the constraint solver, damping is simply a force linear in velocity. It is included in the passive forces. Despite this simplicity, larger damping values can make numerical integrators unstable, which is why our Euler integrator handles damping implicitly. See Integration in the Computation chapter."""
|
||||
)
|
||||
|
||||
uniform double mjc:frictionloss = 0 (
|
||||
doc = "Friction loss due to dry friction. This value is the same for all degrees of freedom created by this joint. Semantically friction loss does not make sense for free joints, but the compiler allows it. To enable friction loss, set this attribute to a positive value."
|
||||
doc = """DEPRECATED: Use newton:friction instead.
|
||||
|
||||
Friction loss due to dry friction. This value is the same for all degrees of freedom created by this joint. Semantically friction loss does not make sense for free joints, but the compiler allows it. To enable friction loss, set this attribute to a positive value."""
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -122,14 +122,21 @@ TF_DEFINE_PRIVATE_TOKENS(kTokens,
|
||||
(UsdPreviewSurface)
|
||||
((NewtonMaterialAPI, "NewtonMaterialAPI"))
|
||||
((NewtonMeshCollisionAPI, "NewtonMeshCollisionAPI"))
|
||||
((NewtonJointAPI, "NewtonJointAPI"))
|
||||
((NewtonMassAPI, "NewtonMassAPI"))
|
||||
((newtonTorsionalFriction, "newton:torsionalFriction"))
|
||||
((newtonRollingFriction, "newton:rollingFriction"))
|
||||
((newtonArmature, "newton:armature"))
|
||||
((newtonDamping, "newton:damping"))
|
||||
((newtonFriction, "newton:friction"))
|
||||
((newtonMassModel, "newton:massModel"))
|
||||
((newtonMaxHullVertices, "newton:maxHullVertices"))
|
||||
((newtonMaxSolverIterations, "newton:maxSolverIterations"))
|
||||
((newtonTimeStepsPerSecond, "newton:timeStepsPerSecond"))
|
||||
((newtonGravityEnabled, "newton:gravityEnabled"))
|
||||
((newtonContactMargin, "newton:contactMargin"))
|
||||
((newtonContactGap, "newton:contactGap"))
|
||||
((newtonContactAdhesion, "newton:contactAdhesion"))
|
||||
);
|
||||
|
||||
// Using to satisfy TF_REGISTRY_FUNCTION macro below and avoid operating in PXR_NS.
|
||||
@@ -404,6 +411,13 @@ class ModelWriter {
|
||||
WriteUniformAttribute(mesh_spec, pxr::SdfValueTypeNames->Token,
|
||||
MjcPhysicsTokens->mjcInertia, inertia);
|
||||
|
||||
// Newton mass model attribute (partially replaces deprecated mjc:inertia)
|
||||
if (mesh->inertia == mjtMeshInertia::mjMESH_INERTIA_SHELL) {
|
||||
ApplyApiSchema(layer_, mesh_spec, kTokens->NewtonMassAPI);
|
||||
WriteUniformAttribute(mesh_spec, pxr::SdfValueTypeNames->Token,
|
||||
kTokens->newtonMassModel, MjcPhysicsTokens->shell);
|
||||
}
|
||||
|
||||
// Newton mesh attribute (replaces deprecated mjc:maxhullvert)
|
||||
if (mesh->maxhullvert != -1) {
|
||||
WriteUniformAttribute(mesh_spec, pxr::SdfValueTypeNames->Int,
|
||||
@@ -902,6 +916,11 @@ class ModelWriter {
|
||||
WriteUniformAttribute(material_spec, pxr::SdfValueTypeNames->Float,
|
||||
kTokens->newtonRollingFriction,
|
||||
(float)geom->friction[2]);
|
||||
if (geom->adhesion != 0.0f) {
|
||||
WriteUniformAttribute(material_spec, pxr::SdfValueTypeNames->Float,
|
||||
kTokens->newtonContactAdhesion,
|
||||
(float)geom->adhesion);
|
||||
}
|
||||
|
||||
return material_spec;
|
||||
}
|
||||
@@ -1703,10 +1722,12 @@ class ModelWriter {
|
||||
pxr::UsdPhysicsTokens->PhysicsCollisionAPI);
|
||||
ApplyApiSchema(layer_, geom_spec, MjcPhysicsTokens->MjcCollisionAPI);
|
||||
|
||||
WriteUniformAttribute(
|
||||
geom_spec, pxr::SdfValueTypeNames->Bool,
|
||||
MjcPhysicsTokens->mjcShellinertia,
|
||||
geom->typeinertia == mjtGeomInertia::mjINERTIA_SHELL);
|
||||
if (geom->typeinertia == mjtGeomInertia::mjINERTIA_SHELL) {
|
||||
ApplyApiSchema(layer_, geom_spec, kTokens->NewtonMassAPI);
|
||||
WriteUniformAttribute(geom_spec, pxr::SdfValueTypeNames->Token,
|
||||
kTokens->newtonMassModel,
|
||||
MjcPhysicsTokens->shell);
|
||||
}
|
||||
|
||||
WriteUniformAttribute(geom_spec, pxr::SdfValueTypeNames->Int,
|
||||
MjcPhysicsTokens->mjcPriority, geom->priority);
|
||||
@@ -2138,15 +2159,19 @@ class ModelWriter {
|
||||
WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double,
|
||||
MjcPhysicsTokens->mjcSpringref, joint->springref);
|
||||
|
||||
WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double,
|
||||
MjcPhysicsTokens->mjcArmature, joint->armature);
|
||||
// Newton joint attributes (replaces deprecated mjc:armature / mjc:damping
|
||||
// / mjc:frictionloss)
|
||||
WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Float,
|
||||
kTokens->newtonArmature,
|
||||
static_cast<float>(joint->armature));
|
||||
|
||||
WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double,
|
||||
MjcPhysicsTokens->mjcDamping, joint->damping[0]);
|
||||
WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Float,
|
||||
kTokens->newtonDamping,
|
||||
static_cast<float>(joint->damping[0]));
|
||||
|
||||
WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double,
|
||||
MjcPhysicsTokens->mjcFrictionloss,
|
||||
joint->frictionloss);
|
||||
WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Float,
|
||||
kTokens->newtonFriction,
|
||||
static_cast<float>(joint->frictionloss));
|
||||
}
|
||||
if (joint_id >= 0) {
|
||||
joint_paths_[joint_id] = joint_spec->GetPath();
|
||||
|
||||
@@ -1501,7 +1501,10 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsCollisionAPI) {
|
||||
EXPECT_ATTRIBUTE_HAS_NO_AUTHORED_VALUE(stage, "/test/body/box.mjc:gap");
|
||||
ExpectAttributeEqual(stage, "/test/body/box.newton:contactMargin", 0.8f);
|
||||
ExpectAttributeEqual(stage, "/test/body/box.newton:contactGap", 0.9f);
|
||||
ExpectAttributeEqual(stage, "/test/body/box.mjc:shellinertia", true);
|
||||
EXPECT_ATTRIBUTE_HAS_NO_AUTHORED_VALUE(stage,
|
||||
"/test/body/box.mjc:shellinertia");
|
||||
ExpectAttributeEqual(stage, "/test/body/box.newton:massModel",
|
||||
pxr::TfToken("shell"));
|
||||
}
|
||||
|
||||
TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsMeshCollisionAPI) {
|
||||
@@ -1849,10 +1852,19 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsJointAPI) {
|
||||
ExpectAttributeEqual(stage, "/test/parent/child/my_joint.mjc:margin", 1.8);
|
||||
ExpectAttributeEqual(stage, "/test/parent/child/my_joint.mjc:ref", 1.9);
|
||||
ExpectAttributeEqual(stage, "/test/parent/child/my_joint.mjc:springref", 2.0);
|
||||
ExpectAttributeEqual(stage, "/test/parent/child/my_joint.mjc:armature", 2.1);
|
||||
ExpectAttributeEqual(stage, "/test/parent/child/my_joint.mjc:damping", 2.2);
|
||||
ExpectAttributeEqual(stage, "/test/parent/child/my_joint.mjc:frictionloss",
|
||||
2.3);
|
||||
EXPECT_ATTRIBUTE_HAS_NO_AUTHORED_VALUE(
|
||||
stage, "/test/parent/child/my_joint.mjc:armature");
|
||||
EXPECT_ATTRIBUTE_HAS_NO_AUTHORED_VALUE(
|
||||
stage, "/test/parent/child/my_joint.mjc:damping");
|
||||
EXPECT_ATTRIBUTE_HAS_NO_AUTHORED_VALUE(
|
||||
stage, "/test/parent/child/my_joint.mjc:frictionloss");
|
||||
|
||||
ExpectAttributeEqual(stage, "/test/parent/child/my_joint.newton:armature",
|
||||
2.1f);
|
||||
ExpectAttributeEqual(stage, "/test/parent/child/my_joint.newton:damping",
|
||||
2.2f);
|
||||
ExpectAttributeEqual(stage, "/test/parent/child/my_joint.newton:friction",
|
||||
2.3f);
|
||||
}
|
||||
|
||||
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsFloatingAndFixedBaseBody) {
|
||||
|
||||
Reference in New Issue
Block a user