Skip to content

Commit 6678565

Browse files
authored
Add per-DoF mimic actuator mode (#2222)
1 parent f95940d commit 6678565

File tree

17 files changed

+715
-225
lines changed

17 files changed

+715
-225
lines changed

.github/workflows/ci_gz_physics.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,7 @@ jobs:
7878
mkdir -p "${RUNNER_TEMP}/ccache"
7979
8080
- name: Test gz-physics
81+
env:
82+
DART_PARALLEL_JOBS: 8
8183
run: |
8284
pixi r -e gazebo test-gz

.github/workflows/ci_macos.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ jobs:
5252
- name: Setup pixi
5353
uses: prefix-dev/setup-pixi@v0.9.3
5454
with:
55-
cache: true
55+
# Avoid cache key generation failures on macOS self-hosted runners
56+
cache: false
5657

5758
- name: Add pixi to PATH (prepend to override system pixi)
5859
run: echo "${HOME}/.pixi/bin" >> $GITHUB_PATH
@@ -102,7 +103,8 @@ jobs:
102103
- name: Setup pixi
103104
uses: prefix-dev/setup-pixi@v0.9.3
104105
with:
105-
cache: true
106+
# Avoid cache key generation failures on macOS self-hosted runners
107+
cache: false
106108

107109
- name: Add pixi to PATH (prepend to override system pixi)
108110
run: echo "${HOME}/.pixi/bin" >> $GITHUB_PATH

.github/workflows/ci_ubuntu.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
- name: Checkout
5252
uses: actions/checkout@v5
5353

54-
- name: Remove preinstalled pixi (if any)
54+
- name: Remove stale pixi binary
5555
run: rm -f "$HOME/.pixi/bin/pixi"
5656

5757
- name: Setup pixi

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
- Removed all APIs deprecated in DART 6.0 (legacy BodyNode collision flags, Skeleton self-collision aliases, Joint `getLocal*`/`updateLocal*` accessors, `World::checkCollision(bool)`, `ConstraintSolver::setCollisionDetector(raw*)`, Marker `getBodyNode()`, `SdfParser::readSdfFile`, and deprecated XML helpers).
3939
- Removed all APIs deprecated in DART 6.7 (legacy math random helpers, `Skeleton::clone()` overloads, and `ConstraintSolver::set/getLCPSolver()`).
4040
- Removed all APIs deprecated in DART 6.2 (legacy Entity/BodyNode/JacobianNode/Joints/Skeleton notifiers, `Shape::notify*Update`, `EllipsoidShape::getSize`/`setSize`, `MultiSphereShape` alias, and `Eigen::make_aligned_shared` alias).
41+
- Allow configuring mimic actuator mode per DoF so multi-axis joints can mimic a single axis without forcing the rest of the joint into mimic mode; added `Joint::setActuatorType(std::size_t, ...)`, `Joint::getActuatorType(std::size_t)`, `Joint::getActuatorTypes()`, and `Joint::hasActuatorType(...)` plus the corresponding dartpy bindings and regression tests. ([#1684](https://github.com/dartsim/dart/issues/1684))
4142
- Deprecated `ResourceRetriever::getFilePath()` and the overriding implementations across retrievers. The method now emits compiler deprecation warnings and will be removed in DART 8.0; use the new resource-materialization helpers (e.g., the SDF/OSG utilities) instead.
4243
- Removed the final compatibility headers that only re-included their replacements (`dart/collision/Option.hpp`, `dart/collision/Result.hpp`, and `dart/dynamics/MultiSphereShape.hpp`) and scrubbed the remaining deprecated documentation strings.
4344
- Removed `CollisionFilter::needCollision()` (deprecated in DART 6.3).

dart/constraint/ConstraintSolver.cpp

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -516,19 +516,47 @@ void ConstraintSolver::updateConstraints()
516516
}
517517

518518
if (joint->areLimitsEnforced()
519-
|| joint->getActuatorType() == dynamics::Joint::SERVO) {
519+
|| joint->hasActuatorType(dynamics::Joint::SERVO)) {
520520
mJointConstraints.push_back(std::make_shared<JointConstraint>(joint));
521521
}
522522

523-
if (joint->getActuatorType() == dynamics::Joint::MIMIC
524-
&& joint->getMimicJoint()) {
525-
if (joint->isUsingCouplerConstraint()) {
526-
mCouplerConstraints.push_back(std::make_shared<CouplerConstraint>(
527-
joint, joint->getMimicDofProperties()));
528-
} else {
529-
mMimicMotorConstraints.push_back(
530-
std::make_shared<MimicMotorConstraint>(
531-
joint, joint->getMimicDofProperties()));
523+
if (joint->hasActuatorType(dynamics::Joint::MIMIC)) {
524+
auto mimicProps = joint->getMimicDofProperties();
525+
mimicProps.resize(joint->getNumDofs());
526+
const auto dofCount = joint->getNumDofs();
527+
bool hasValidMimicDof = false;
528+
bool useCouplerConstraint = false;
529+
bool allMimicWithReference = true;
530+
for (std::size_t dofIndex = 0; dofIndex < dofCount; ++dofIndex) {
531+
if (joint->getActuatorType(dofIndex) == dynamics::Joint::MIMIC) {
532+
if (mimicProps[dofIndex].mReferenceJoint != nullptr) {
533+
hasValidMimicDof = true;
534+
if (mimicProps[dofIndex].mConstraintType
535+
== dynamics::MimicConstraintType::Coupler) {
536+
useCouplerConstraint = true;
537+
}
538+
} else {
539+
allMimicWithReference = false;
540+
DART_WARN(
541+
"Joint '{}' DoF {} is set to MIMIC without a reference; "
542+
"mimic constraint will be skipped.",
543+
joint->getName(),
544+
dofIndex);
545+
}
546+
} else {
547+
allMimicWithReference = false;
548+
}
549+
}
550+
551+
if (hasValidMimicDof) {
552+
if (useCouplerConstraint && allMimicWithReference) {
553+
mCouplerConstraints.push_back(std::make_shared<CouplerConstraint>(
554+
joint, joint->getMimicDofProperties()));
555+
} else {
556+
mMimicMotorConstraints.push_back(
557+
std::make_shared<MimicMotorConstraint>(
558+
joint, joint->getMimicDofProperties()));
559+
}
532560
}
533561
}
534562
}

dart/constraint/CouplerConstraint.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#include "dart/dynamics/Joint.hpp"
3939
#include "dart/dynamics/Skeleton.hpp"
4040

41+
#include <algorithm>
42+
4143
#include <cmath>
4244

4345
namespace {
@@ -122,6 +124,12 @@ void CouplerConstraint::update()
122124
for (std::size_t i = 0; i < dof; ++i) {
123125
const auto& mimicProp = mMimicProps[i];
124126

127+
if (mJoint->getActuatorType(i) != dynamics::Joint::MIMIC
128+
|| mimicProp.mReferenceJoint == nullptr) {
129+
mActive[i] = false;
130+
continue;
131+
}
132+
125133
double timeStep = mJoint->getSkeleton()->getTimeStep();
126134
double velLower = mJoint->getVelocityLowerLimit(i);
127135
double velUpper = mJoint->getVelocityUpperLimit(i);
@@ -339,8 +347,14 @@ void CouplerConstraint::uniteSkeletons()
339347

340348
auto dependentRoot = ConstraintBase::compressPath(dependentSkeleton);
341349

342-
for (const auto& mimicProp : mMimicProps) {
343-
if (mimicProp.mReferenceJoint == nullptr)
350+
for (std::size_t i = 0; i < mJoint->getNumDofs(); ++i) {
351+
if (i >= mMimicProps.size())
352+
break;
353+
354+
const auto& mimicProp = mMimicProps[i];
355+
356+
if (mJoint->getActuatorType(i) != dynamics::Joint::MIMIC
357+
|| mimicProp.mReferenceJoint == nullptr)
344358
continue;
345359

346360
auto referenceBody = mimicProp.mReferenceJoint->getChildBodyNode();
@@ -380,8 +394,13 @@ void CouplerConstraint::uniteSkeletons()
380394
//==============================================================================
381395
bool CouplerConstraint::isActive() const
382396
{
383-
if (mJoint->getActuatorType() == dynamics::Joint::MIMIC)
384-
return true;
397+
const auto dof = std::min(mJoint->getNumDofs(), mMimicProps.size());
398+
for (std::size_t i = 0; i < dof; ++i) {
399+
if (mJoint->getActuatorType(i) == dynamics::Joint::MIMIC
400+
&& mMimicProps[i].mReferenceJoint != nullptr) {
401+
return true;
402+
}
403+
}
385404

386405
return false;
387406
}

dart/constraint/JointConstraint.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,8 @@ void JointConstraint::update()
298298
continue;
299299
}
300300

301-
const bool isServo = mJoint->getActuatorType() == dynamics::Joint::SERVO;
301+
const bool isServo = mJoint->getActuatorType(static_cast<std::size_t>(i))
302+
== dynamics::Joint::SERVO;
302303
const double servoCommand
303304
= isServo ? mJoint->getCommand(static_cast<std::size_t>(i)) : 0.0;
304305
const bool atLowerLimit
@@ -367,7 +368,8 @@ void JointConstraint::update()
367368
}
368369

369370
// Servo motor constraint check
370-
if (mJoint->getActuatorType() == dynamics::Joint::SERVO) {
371+
if (mJoint->getActuatorType(static_cast<std::size_t>(i))
372+
== dynamics::Joint::SERVO) {
371373
// The desired velocity shouldn't be out of the velocity limits
372374
double desired_velocity = math::clip(
373375
mJoint->getCommand(static_cast<std::size_t>(i)),

dart/constraint/MimicMotorConstraint.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ void MimicMotorConstraint::update()
162162
for (std::size_t i = 0; i < dof; ++i) {
163163
const auto& mimicProp = mMimicProps[i];
164164

165+
if (mJoint->getActuatorType(i) != dynamics::Joint::MIMIC
166+
|| mimicProp.mReferenceJoint == nullptr) {
167+
mActive[i] = false;
168+
continue;
169+
}
170+
165171
double timeStep = mJoint->getSkeleton()->getTimeStep();
166172
double velLower = mJoint->getVelocityLowerLimit(i);
167173
double velUpper = mJoint->getVelocityUpperLimit(i);
@@ -327,11 +333,14 @@ dynamics::SkeletonPtr MimicMotorConstraint::getRootSkeleton() const
327333
//==============================================================================
328334
bool MimicMotorConstraint::isActive() const
329335
{
330-
// Since we are not allowed to set the joint actuator type per each
331-
// DegreeOfFreedom, we just check if the whole joint is SERVO actuator.
332-
if (mJoint->getActuatorType() == dynamics::Joint::MIMIC)
333-
return true;
334-
336+
const std::size_t dof = mJoint->getNumDofs();
337+
for (std::size_t i = 0; i < dof; ++i) {
338+
if (mJoint->getActuatorType(i) == dynamics::Joint::MIMIC
339+
&& i < mMimicProps.size()
340+
&& mMimicProps[i].mReferenceJoint != nullptr) {
341+
return true;
342+
}
343+
}
335344
return false;
336345
}
337346

0 commit comments

Comments
 (0)