Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4afbcd0
Add mimic pendulum repro test and GUI debug example
jslee02 Nov 22, 2025
59ceb15
Improve mimic tracking tests and example tuning
jslee02 Nov 22, 2025
aec220a
Format code
jslee02 Nov 22, 2025
07d1c21
Adjust cfm and erp
jslee02 Nov 22, 2025
c6400fa
Fix mimic pendulum instability: Reference middle pendulum joints inst…
jslee02 Nov 22, 2025
ee8d855
Adjust mimic motor constraint
jslee02 Nov 22, 2025
ce5163c
Merge branch 'main' into gz/mimic_constraint
jslee02 Nov 22, 2025
769d733
Format code
jslee02 Nov 22, 2025
e29a2ac
Use mimic motor references and lock pendulum bases
jslee02 Nov 23, 2025
5d07ee6
Remove base locking from mimic pendulum demo
jslee02 Nov 23, 2025
0691f9b
Test mimic followers track middle pendulum
jslee02 Nov 23, 2025
b0975f8
Enable setting cfm and erp
jslee02 Nov 23, 2025
67cc9f7
Align mimic example/tests with SDF-only setup
jslee02 Nov 23, 2025
490cfd2
Cleanup mimic constraint defaults and stabilize mimic tests
jslee02 Nov 23, 2025
c403ca2
Tidy mimic constraint test includes
jslee02 Nov 23, 2025
236f7ba
Merge remote-tracking branch 'origin/main' into gz/mimic_constraint
jslee02 Nov 23, 2025
942fccb
Restore mimic motor ERP API and declare PlanarJoint converters
jslee02 Nov 23, 2025
9cb5ef8
Guard mimic constraint test from Bullet dependency
jslee02 Nov 23, 2025
6b9855f
Guard mimic example from optional Bullet dependency
jslee02 Nov 23, 2025
cb6f46b
Merge branch 'main' into gz/mimic_constraint
jslee02 Nov 23, 2025
57e39e0
Keep baseline pendulum uncoupled when configuring mimic motors
jslee02 Nov 23, 2025
7e302d6
Fix build error due to duplicate function decl
jslee02 Nov 24, 2025
15b47b3
Update .sdf
jslee02 Nov 24, 2025
016af54
Merge branch 'main' into gz/mimic_constraint
jslee02 Nov 24, 2025
bdb30b9
Merge branch 'main' into gz/mimic_constraint
jslee02 Nov 24, 2025
5f4a0bb
Merge branch 'main' into gz/mimic_constraint
jslee02 Nov 24, 2025
63fe4e6
Merge branch 'main' into gz/mimic_constraint
jslee02 Nov 24, 2025
ac8039c
Clamp cmake build parallelism
jslee02 Nov 24, 2025
c0e1479
Merge origin/main into gz/mimic_constraint
jslee02 Nov 24, 2025
debf7c8
Default parallel jobs to CI=1, else use host cores
jslee02 Nov 24, 2025
3f2a829
Use 75% of cores locally for cmake --parallel
jslee02 Nov 24, 2025
9c539a9
Revert "Use 75% of cores locally for cmake --parallel"
jslee02 Nov 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions dart/constraint/CouplerConstraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,21 @@
#include "dart/dynamics/Joint.hpp"
#include "dart/dynamics/Skeleton.hpp"

#define DART_CFM 1e-9
#include <cmath>

namespace {

constexpr inline double kConstraintForceMixing = 1e-6;
constexpr inline double kDefaultForceLimit = 800.0;
constexpr inline double kDefaultVelocityLimit = 50.0;
constexpr inline double kDefaultErp = 0.4;

} // namespace

namespace dart {
namespace constraint {

double CouplerConstraint::mConstraintForceMixing = DART_CFM;
double CouplerConstraint::mConstraintForceMixing = kConstraintForceMixing;

//==============================================================================
CouplerConstraint::CouplerConstraint(
Expand Down Expand Up @@ -114,20 +123,32 @@ void CouplerConstraint::update()
const auto& mimicProp = mMimicProps[i];

double timeStep = mJoint->getSkeleton()->getTimeStep();
double velLower = mJoint->getVelocityLowerLimit(i);
double velUpper = mJoint->getVelocityUpperLimit(i);
if (!std::isfinite(velLower))
velLower = -kDefaultVelocityLimit;
if (!std::isfinite(velUpper))
velUpper = kDefaultVelocityLimit;
double qError
= mimicProp.mReferenceJoint->getPosition(mimicProp.mReferenceDofIndex)
* mimicProp.mMultiplier
+ mimicProp.mOffset - mJoint->getPosition(i);
double desiredVelocity = math::clip(
qError / timeStep,
mJoint->getVelocityLowerLimit(i),
mJoint->getVelocityUpperLimit(i));
const double erp = kDefaultErp;
double desiredVelocity
= math::clip((erp * qError) / timeStep, velLower, velUpper);

mNegativeVelocityError[i] = desiredVelocity - mJoint->getVelocity(i);

if (mNegativeVelocityError[i] != 0.0) {
mUpperBound[i] = mJoint->getForceUpperLimit(i) * timeStep;
mLowerBound[i] = mJoint->getForceLowerLimit(i) * timeStep;
double upper = mJoint->getForceUpperLimit(i);
double lower = mJoint->getForceLowerLimit(i);
if (!std::isfinite(upper))
upper = kDefaultForceLimit;
if (!std::isfinite(lower))
lower = -kDefaultForceLimit;

mUpperBound[i] = upper * timeStep;
mLowerBound[i] = lower * timeStep;

if (mActive[i]) {
++(mLifeTime[i]);
Expand Down
3 changes: 2 additions & 1 deletion dart/constraint/CouplerConstraint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

#include <dart/constraint/ConstraintBase.hpp>

#include <dart/dynamics/Fwd.hpp>
#include <dart/dynamics/MimicDofProperties.hpp>

#include <dart/Export.hpp>
Expand Down Expand Up @@ -144,7 +145,7 @@ class DART_API CouplerConstraint : public ConstraintBase
double mLowerBound[6];

/// Global constraint force mixing parameter in the range of [1e-9, 1]. The
/// default is 1e-5
/// default is 1e-6
/// @sa http://www.ode.org/ode-latest-userguide.html#sec_3_8_0
static double mConstraintForceMixing;
};
Expand Down
63 changes: 55 additions & 8 deletions dart/constraint/MimicMotorConstraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,22 @@

#include <iostream>

#define DART_CFM 1e-9
#include <cmath>

namespace {

constexpr inline double kConstraintForceMixing = 1e-6;
constexpr inline double kDefaultForceLimit = 800.0;
constexpr inline double kDefaultVelocityLimit = 50.0;
constexpr inline double kDefaultErp = 0.4;

} // namespace

namespace dart {
namespace constraint {

double MimicMotorConstraint::mConstraintForceMixing = DART_CFM;
double MimicMotorConstraint::mConstraintForceMixing = kConstraintForceMixing;
double MimicMotorConstraint::mErrorReductionParameter = kDefaultErp;

//==============================================================================
MimicMotorConstraint::MimicMotorConstraint(
Expand Down Expand Up @@ -117,6 +127,31 @@ double MimicMotorConstraint::getConstraintForceMixing()
return mConstraintForceMixing;
}

//==============================================================================
void MimicMotorConstraint::setErrorReductionParameter(double erp)
{
double clamped = erp;
if (clamped < 0.0) {
DART_WARN(
"Error reduction parameter [{}] is lower than 0.0. It is set to 0.0.",
erp);
clamped = 0.0;
} else if (clamped > 1.0) {
DART_WARN(
"Error reduction parameter [{}] is greater than 1.0. It is set to 1.0.",
erp);
clamped = 1.0;
}

mErrorReductionParameter = clamped;
}

//==============================================================================
double MimicMotorConstraint::getErrorReductionParameter()
{
return mErrorReductionParameter;
}

//==============================================================================
void MimicMotorConstraint::update()
{
Expand All @@ -128,21 +163,33 @@ void MimicMotorConstraint::update()
const auto& mimicProp = mMimicProps[i];

double timeStep = mJoint->getSkeleton()->getTimeStep();
double velLower = mJoint->getVelocityLowerLimit(i);
double velUpper = mJoint->getVelocityUpperLimit(i);
if (!std::isfinite(velLower))
velLower = -kDefaultVelocityLimit;
if (!std::isfinite(velUpper))
velUpper = kDefaultVelocityLimit;
double qError
= mimicProp.mReferenceJoint->getPosition(mimicProp.mReferenceDofIndex)
* mimicProp.mMultiplier
+ mimicProp.mOffset - mJoint->getPosition(i);
double desiredVelocity = math::clip(
qError / timeStep,
mJoint->getVelocityLowerLimit(i),
mJoint->getVelocityUpperLimit(i));
const double erp = mErrorReductionParameter;
double desiredVelocity
= math::clip((erp * qError) / timeStep, velLower, velUpper);

mNegativeVelocityError[i] = desiredVelocity - mJoint->getVelocity(i);

if (mNegativeVelocityError[i] != 0.0) {
// Note that we are computing impulse not force
mUpperBound[i] = mJoint->getForceUpperLimit(i) * timeStep;
mLowerBound[i] = mJoint->getForceLowerLimit(i) * timeStep;
double upper = mJoint->getForceUpperLimit(i);
double lower = mJoint->getForceLowerLimit(i);
if (!std::isfinite(upper))
upper = kDefaultForceLimit;
if (!std::isfinite(lower))
lower = -kDefaultForceLimit;

mUpperBound[i] = upper * timeStep;
mLowerBound[i] = lower * timeStep;

if (mActive[i]) {
++(mLifeTime[i]);
Expand Down
18 changes: 11 additions & 7 deletions dart/constraint/MimicMotorConstraint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,12 @@

#include <dart/constraint/ConstraintBase.hpp>

#include <dart/dynamics/Fwd.hpp>
#include <dart/dynamics/MimicDofProperties.hpp>

#include <vector>

namespace dart {

namespace dynamics {
class BodyNode;
class Joint;
} // namespace dynamics

namespace constraint {

/// MimicMotorConstraint behaves like a servo motor: it drives only the
Expand Down Expand Up @@ -84,6 +79,12 @@ class MimicMotorConstraint : public ConstraintBase
/// Get global constraint force mixing parameter
static double getConstraintForceMixing();

/// Set global error reduction parameter applied to mimic motors.
static void setErrorReductionParameter(double erp);

/// Get global error reduction parameter applied to mimic motors.
static double getErrorReductionParameter();

//----------------------------------------------------------------------------
// Friendship
//----------------------------------------------------------------------------
Expand Down Expand Up @@ -157,9 +158,12 @@ class MimicMotorConstraint : public ConstraintBase
double mLowerBound[6];

/// Global constraint force mixing parameter in the range of [1e-9, 1]. The
/// default is 1e-5
/// default is 1e-6
/// @sa http://www.ode.org/ode-latest-userguide.html#sec_3_8_0
static double mConstraintForceMixing;

/// Global error reduction parameter that scales mimic motor position error.
static double mErrorReductionParameter;
};

} // namespace constraint
Expand Down
Loading
Loading