diff --git a/examples/worlds/mimic_fast_slow_pendulums_world.sdf b/examples/worlds/mimic_fast_slow_pendulums_world.sdf
new file mode 100644
index 0000000000..b42c8bc73a
--- /dev/null
+++ b/examples/worlds/mimic_fast_slow_pendulums_world.sdf
@@ -0,0 +1,661 @@
+
+
+
+
+
+
+ 0.001
+ 1
+
+
+
+ true
+ 0 0 10 0 0 0
+ 0.8 0.8 0.8 1
+ 0.2 0.2 0.2 1
+
+ 1000
+ 0.9
+ 0.01
+ 0.001
+
+ -0.5 0.1 -0.9
+
+
+
+ true
+
+
+
+
+ 0 0 1
+ 100 100
+
+
+
+
+
+
+ 0 0 1
+ 100 100
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+
+
+
+ 0 0 0 0 0 0
+
+
+ 100
+
+
+ 0 0 0.01 0 0 0
+
+
+ 0.8
+ 0.02
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ -0.275 0 1.1 0 0 0
+
+
+ 0.2 0.2 2.2
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.01 0 0 0
+
+
+ 0.8
+ 0.02
+
+
+
+
+ -0.275 0 1.1 0 0 0
+
+
+ 0.2 0.2 2.2
+
+
+
+
+
+
+
+ 0 0 2.1 -1.5708 0 0
+ 0
+
+ 1.0
+ 0 0 0.5 0 0 0
+
+ 0.087
+ 0
+ 0
+ 0.087
+ 0
+ 0.006
+
+
+
+ -0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.5 0 0 0
+
+
+ 0.1
+ 1.0
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ -0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+
+ 0 0 0.5 0 0 0
+
+
+ 0.1
+ 1.0
+
+
+
+
+
+
+
+ -0.5 0 2.1 -1.5708 0 0
+ 0
+
+ 1.0
+ 0 0 0.25 0 0 0
+
+ 0.024
+ 0
+ 0
+ 0.024
+ 0
+ 0.006
+
+
+
+ 0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.25 0 0 0
+
+
+ 0.1
+ 0.5
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+
+ 0 0 0.2 0 0 0
+
+
+ 0.1
+ 0.5
+
+
+
+
+
+
+ base
+ slow_link
+
+ -1.0 0 0
+
+
+
+
+ base
+ fast_link
+
+ -1.0 0 0
+
+
+
+
+
+
+ 0 3 0 0 0 0
+
+
+ 100
+
+
+ 0 0 0.01 0 0 0
+
+
+ 0.8
+ 0.02
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ -0.275 0 1.1 0 0 0
+
+
+ 0.2 0.2 2.2
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.01 0 0 0
+
+
+ 0.8
+ 0.02
+
+
+
+
+ -0.275 0 1.1 0 0 0
+
+
+ 0.2 0.2 2.2
+
+
+
+
+
+
+
+ 0 0 2.1 -1.5708 0 0
+ 0
+
+ 1.0
+ 0 0 0.5 0 0 0
+
+ 0.087
+ 0
+ 0
+ 0.087
+ 0
+ 0.006
+
+
+
+ -0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.5 0 0 0
+
+
+ 0.1
+ 1.0
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ -0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+
+ 0 0 0.5 0 0 0
+
+
+ 0.1
+ 1.0
+
+
+
+
+
+
+
+ -0.5 0 2.1 -1.5708 0 0
+ 0
+
+ 1.0
+ 0 0 0.25 0 0 0
+
+ 0.024
+ 0
+ 0
+ 0.024
+ 0
+ 0.006
+
+
+
+ 0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.25 0 0 0
+
+
+ 0.1
+ 0.5
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+
+ 0 0 0.2 0 0 0
+
+
+ 0.1
+ 0.5
+
+
+
+
+
+
+ base
+ slow_link
+
+ -1.0 0 0
+
+ 1
+
+
+
+
+
+ base
+ fast_link
+
+ -1.0 0 0
+
+
+
+
+
+
+ 0 -3 0 0 0 0
+
+
+ 100
+
+
+ 0 0 0.01 0 0 0
+
+
+ 0.8
+ 0.02
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ -0.275 0 1.1 0 0 0
+
+
+ 0.2 0.2 2.2
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.01 0 0 0
+
+
+ 0.8
+ 0.02
+
+
+
+
+ -0.275 0 1.1 0 0 0
+
+
+ 0.2 0.2 2.2
+
+
+
+
+
+
+
+ 0 0 2.1 -1.5708 0 0
+ 0
+
+ 1.0
+ 0 0 0.5 0 0 0
+
+ 0.087
+ 0
+ 0
+ 0.087
+ 0
+ 0.006
+
+
+
+ -0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.5 0 0 0
+
+
+ 0.1
+ 1.0
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ -0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+
+ 0 0 0.5 0 0 0
+
+
+ 0.1
+ 1.0
+
+
+
+
+
+
+
+ -0.5 0 2.1 -1.5708 0 0
+ 0
+
+ 1.0
+ 0 0 0.25 0 0 0
+
+ 0.024
+ 0
+ 0
+ 0.024
+ 0
+ 0.006
+
+
+
+ 0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0 0 0.25 0 0 0
+
+
+ 0.1
+ 0.5
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+ 0.05 0 0 0 1.5708 0
+
+
+ 0.1
+ 0.3
+
+
+
+
+ 0 0 0.2 0 0 0
+
+
+ 0.1
+ 0.5
+
+
+
+
+
+
+ base
+ slow_link
+
+ -1.0 0 0
+
+
+
+
+ base
+ fast_link
+
+ -1.0 0 0
+
+ 1
+
+
+
+
+
+
+
+
diff --git a/src/systems/physics/Physics.cc b/src/systems/physics/Physics.cc
index 59cd31bc33..fb3837934d 100644
--- a/src/systems/physics/Physics.cc
+++ b/src/systems/physics/Physics.cc
@@ -478,6 +478,10 @@ class gz::sim::systems::PhysicsPrivate
JointFeatureList,
gz::physics::sdf::ConstructSdfJoint>{};
+ /// \brief Feature list for mimic constraints
+ public: struct MimicConstraintJointFeatureList : gz::physics::FeatureList<
+ physics::SetMimicConstraintFeature>{};
+
//////////////////////////////////////////////////
// Detachable joints
@@ -681,6 +685,7 @@ class gz::sim::systems::PhysicsPrivate
physics::Joint,
JointFeatureList,
DetachableJointFeatureList,
+ MimicConstraintJointFeatureList,
JointVelocityCommandFeatureList,
JointGetTransmittedWrenchFeatureList,
JointPositionLimitsCommandFeatureList,
@@ -1683,6 +1688,62 @@ void PhysicsPrivate::CreateJointEntities(const EntityComponentManager &_ecm,
this->entityJointMap.AddEntity(_entity, existingJoint);
this->topLevelModelMap.insert(
std::make_pair(_entity, topLevelModel(_entity, _ecm)));
+
+ // Check if mimic constraint should be applied to this joint's axes.
+ using AxisIndex = std::size_t;
+ std::map jointAxisByIndex;
+ auto jointAxis = _ecm.Component(_entity);
+ auto jointAxis2 = _ecm.Component(_entity);
+
+ if (jointAxis)
+ {
+ jointAxisByIndex[0] = jointAxis->Data();
+ }
+
+ if (jointAxis2)
+ {
+ jointAxisByIndex[1] = jointAxis2->Data();
+ }
+
+ for (const auto &[axisIndex, axis] : jointAxisByIndex)
+ {
+ if (auto mimic = axis.Mimic())
+ {
+ auto jointPtrMimic = this->entityJointMap
+ .EntityCast(existingJoint);
+ if (jointPtrMimic)
+ {
+ const auto leaderJoint =
+ basicModelPtrPhys->GetJoint(mimic->Joint());
+ std::size_t leaderAxis = 0;
+ if (mimic->Axis() == "axis2")
+ {
+ leaderAxis = 1;
+ }
+ jointPtrMimic->SetMimicConstraint(axisIndex,
+ leaderJoint,
+ leaderAxis,
+ mimic->Multiplier(),
+ mimic->Offset(),
+ mimic->Reference());
+ }
+ else
+ {
+ static bool informed{false};
+ if (!informed)
+ {
+ gzerr << "Attempting to create a mimic constraint for joint ["
+ << _name->Data()
+ << "] but the chosen physics engine does not support "
+ << "mimic constraints, so no constraint will be "
+ << "created."
+ << std::endl;
+ informed = true;
+ }
+ }
+ }
+ }
+
return true;
}