Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
8e24655
[solver] Allow to pass polytope instead of friction cone
arntanguy Mar 14, 2025
1d51927
[solver] Add feasible polytope to contact
arntanguy Mar 14, 2025
f580848
[logging] Add optional overloads to mc_rtc::log::*
arntanguy Mar 14, 2025
29c4d3a
[DynamicPolytope] Pass polytope correctly in addContact
arntanguy Mar 14, 2025
118f459
[bugfix][mc_rbdyn] Properly store feasibilityPolytope in the qp contact
arntanguy Mar 20, 2025
7798012
Detail logic with comments
Hugo-L3174 Mar 21, 2025
b7719e4
[WIP] Add linear function and polytope node
Hugo-L3174 Mar 25, 2025
1a95cf2
Mutex protect access of polytope
Hugo-L3174 Mar 25, 2025
666ef30
[WIP] Structures for new node and polytope constraint
Hugo-L3174 Mar 26, 2025
0f1b81c
fix: Lifetime of contact
arntanguy Mar 26, 2025
a9cd893
fix(contacts): Store contacts as pointers
arntanguy Mar 28, 2025
73716e7
Add 3D and 6D options, handle default cases
Hugo-L3174 Mar 29, 2025
5eed55c
Update DynamicFunction to handle surface contacts
Hugo-L3174 Mar 29, 2025
b47f4e1
Add contact wrench minimization and handle constraint size change
Hugo-L3174 Mar 31, 2025
7d39991
feat(tvm_solver): Allow to generate dot file of TVM graph
arntanguy Apr 1, 2025
705607b
fix(tvm): Properly register updates of PostureFunction
arntanguy Apr 1, 2025
26702e1
[Bugfix] Only build kinematic constraint in TVM impl if there are act…
Hugo-L3174 Apr 2, 2025
aad6070
Hold a polytope for each robot in the contact
Hugo-L3174 Apr 2, 2025
6b6c9bc
[temporary bugfix] Correct contact comparison (need to to this better…
Hugo-L3174 Apr 3, 2025
b9470bd
Handle dual robot contacts with the same variable
Hugo-L3174 Apr 3, 2025
80fa447
Correct both wrenches frames for double robot contacts
Hugo-L3174 Apr 7, 2025
7887328
Remove unnecessary external updates for feasible polytopes
Hugo-L3174 Apr 9, 2025
4981659
[fix bindings] Add shared_ptr contacts to build bindings
Hugo-L3174 Apr 9, 2025
12aa08d
fix(tests): fix rebase mistake
arntanguy Apr 9, 2025
e541ac6
[solver] Disable minimization of contact forces
arntanguy Apr 9, 2025
f4215a8
Add access to solver dynamics constraints
Hugo-L3174 Apr 10, 2025
4476378
Correct frames for dual robot contact
Hugo-L3174 Apr 15, 2025
c63a0ac
Add transforms map
Hugo-L3174 May 5, 2025
127ff4f
Store normals as MatrixXd instead of MatrixX3d expecting 6D extension
Hugo-L3174 May 5, 2025
a9c969e
[Bug] Remove TVM substitutions to avoid variables bug when adding and…
Hugo-L3174 May 5, 2025
ee8a96c
[Bug] Workaround for missing TVM solver events triggers
Hugo-L3174 May 6, 2025
c73ee00
Add momentum velocity and update momentum function
Hugo-L3174 May 7, 2025
da880f7
fix: Workaround for tasks that do addVariable after creation
arntanguy May 7, 2025
d3c7cb1
Fix Momentum function refVel and DynamicFunction erase order at conta…
Hugo-L3174 May 16, 2025
5796487
Generalize polytope constraint for 3D and 6D
Hugo-L3174 May 16, 2025
13b55f9
Add surface torsional friction constraint
Hugo-L3174 Jun 3, 2025
8cad661
Bugfix: Use jacobians in contact frame instead of body frame for wren…
Hugo-L3174 Jun 17, 2025
b90dac3
Feat: Remove unnecessary additions and removals using TVM updates
Hugo-L3174 Jun 17, 2025
206f8a3
Bugfix: Correct opposite frames transform order
Hugo-L3174 Jun 18, 2025
1312046
feat(mc_rbdyn): Allow variable body mass
arntanguy Sep 17, 2025
e857af7
feat(mc_rbdyn): Add force sensor frames
arntanguy Oct 6, 2025
4da724f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 15, 2026
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
3 changes: 3 additions & 0 deletions binding/python/mc_rbdyn/mc_rbdyn.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,14 @@ cdef class CylindricalSurface(Surface):
cdef CylindricalSurface CylindricalSurfaceFromPtr(c_mc_rbdyn.CylindricalSurface*)

cdef class Contact(object):
cdef shared_ptr[c_mc_rbdyn.Contact] ptr
cdef c_mc_rbdyn.Contact * impl
cdef cppbool own_impl__

cdef Contact ContactFromC(const c_mc_rbdyn.Contact &, cppbool copy=?)

cdef Contact ContactFromPtr(shared_ptr[c_mc_rbdyn.Contact], cppbool copy=?)

cdef class ContactVector(object):
cdef vector[c_mc_rbdyn.Contact] * v
cdef cppbool own_impl__
Expand Down
12 changes: 12 additions & 0 deletions binding/python/mc_rbdyn/mc_rbdyn.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,18 @@ cdef Contact ContactFromC(const c_mc_rbdyn.Contact& c, cppbool copy=True):
else:
ret.own_impl__ = False
ret.impl = &(c_mc_rbdyn.const_cast_contact(c))
ret.ptr = shared_ptr[c_mc_rbdyn.Contact]()
return ret

cdef Contact ContactFromPtr(shared_ptr[c_mc_rbdyn.Contact] ptr, cppbool copy=True):
cdef Contact ret = Contact(skip_alloc = True)
if copy:
ret.impl = new c_mc_rbdyn.Contact(deref(ptr.get()))
ret.own_impl__ = True
else:
ret.ptr = ptr
ret.impl = ptr.get()
ret.own_impl__ = False
return ret

cdef class ContactVector(object):
Expand Down
2 changes: 1 addition & 1 deletion binding/python/mc_solver/c_mc_solver.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ cdef extern from "<mc_solver/TasksQPSolver.h>" namespace "mc_solver":
cdef cppclass QPSolver:
void addConstraintSet(const ConstraintSet&)
void removeConstraintSet(const ConstraintSet&)
const vector[c_mc_rbdyn.Contact] & contacts()
const vector[shared_ptr[c_mc_rbdyn.Contact]] & contacts()
void setContacts(const vector[c_mc_rbdyn.Contact]&)
void addTask(c_qp.Task *)
void addTask(c_mc_tasks.MetaTask *)
Expand Down
2 changes: 1 addition & 1 deletion binding/python/mc_solver/mc_solver.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ cdef class QPSolver(object):
def contacts(self):
ret = []
for i in range(self.impl.contacts().size()):
ret.append(mc_rbdyn.ContactFromC(self.impl.contacts()[i]))
ret.append(mc_rbdyn.ContactFromPtr(self.impl.contacts()[i], copy=False))
return ret
def addTask(self, mc_tasks.MetaTask task):
self.impl.addTask(task.mt_base)
Expand Down
7 changes: 5 additions & 2 deletions include/mc_control/Contact.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ struct MC_CONTROL_DLLAPI Contact
const std::string & r1Surface,
const std::string & r2Surface,
double friction = mc_rbdyn::Contact::defaultFriction,
const Eigen::Vector6d & dof = Eigen::Vector6d::Ones())
: r1(r1), r2(r2), r1Surface(r1Surface), r2Surface(r2Surface), friction(friction), dof(dof)
const Eigen::Vector6d & dof = Eigen::Vector6d::Ones(),
std::optional<mc_rbdyn::FeasiblePolytope> feasiblePolytope = std::nullopt)
: r1(r1), r2(r2), r1Surface(r1Surface), r2Surface(r2Surface), friction(friction), dof(dof),
feasiblePolytope(feasiblePolytope)
{
}

Expand All @@ -42,6 +44,7 @@ struct MC_CONTROL_DLLAPI Contact
std::string r2Surface;
mutable double friction;
mutable Eigen::Vector6d dof;
mutable std::optional<mc_rbdyn::FeasiblePolytope> feasiblePolytope;

bool operator==(const Contact & rhs) const
{
Expand Down
12 changes: 8 additions & 4 deletions include/mc_control/MCController.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,19 @@ struct MC_CONTROL_DLLAPI MCController

/** Add a contact between two robots
*
* No effect if the contact is already present.
* No effect if the contact is already present and hasn't changed.
*
* Appropriate constraints will be updated/recreated as needed if contact properties changed (dof, friction,
* feasibility polytopes, etc)
*
* \param c Contact to add
* \param show When true print information
*/
void addContact(const Contact & c);
void addContact(const Contact & c, bool show = true);

/** Remove a contact between two robots
*
* No effect if the contact is already absent.
*
* No effect if the contact does not exist
*/
void removeContact(const Contact & c);

Expand Down
42 changes: 41 additions & 1 deletion include/mc_rbdyn/Contact.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
#include <mc_rbdyn/api.h>
#include <mc_rtc/Configuration.h>

#include <mc_tvm/fwd.h>

#include <Tasks/QPContacts.h>

#include <SpaceVecAlg/SpaceVecAlg>
#include <optional>

#include <memory>

Expand Down Expand Up @@ -43,12 +46,18 @@ MC_RBDYN_DLLAPI std::vector<sva::PTransformd> computePoints(const mc_rbdyn::Surf
const mc_rbdyn::Surface & envSurface,
const sva::PTransformd & X_es_rs);

struct FeasiblePolytope
{
Eigen::MatrixXd planeNormals;
Eigen::VectorXd planeConstants;
};

struct ContactImpl;

struct MC_RBDYN_DLLAPI Contact
{
public:
constexpr static int nrConeGen = 4;
constexpr static int nrConeGen = 4; // FIXME: use it in tvmqpsolver...
constexpr static double defaultFriction = 0.7;
constexpr static unsigned int nrBilatPoints = 4;

Expand Down Expand Up @@ -124,6 +133,23 @@ struct MC_RBDYN_DLLAPI Contact
/** Set the contact friction */
void friction(double friction);

void feasiblePolytopeR1(const FeasiblePolytope & polytope);
const std::optional<FeasiblePolytope> & feasiblePolytopeR1() const noexcept;

void feasiblePolytopeR2(const FeasiblePolytope & polytope);
const std::optional<FeasiblePolytope> & feasiblePolytopeR2() const noexcept;

/** Get the TVM polytope associated to robot 1 of this contact
*
* FIXME Returns a non-const reference from a const method because it is most often used to register dependencies
* between TVM nodes which require non-const objects
*/
mc_tvm::FeasiblePolytope & tvmPolytopeR1() const;

/** Get the TVM polytope associated to robot 2 of this contact
*/
mc_tvm::FeasiblePolytope & tvmPolytopeR2() const;

std::pair<std::string, std::string> surfaces() const;

sva::PTransformd X_0_r1s(const mc_rbdyn::Robot & robot) const;
Expand Down Expand Up @@ -164,6 +190,20 @@ struct MC_RBDYN_DLLAPI Contact
const sva::PTransformd & X_b1_b2,
const std::vector<sva::PTransformd> & points) const;

//! If present superseeds friction cone constraints
// feasible polytope for r1 of contact
std::optional<FeasiblePolytope> feasiblePolytopeR1_;

// feasible polytope for r2 of contact
std::optional<FeasiblePolytope> feasiblePolytopeR2_;

// Secures threaded access to the contact object
mutable std::mutex contactMutex_;

/* mutable to allow initialization in const method */
mutable mc_tvm::PolytopePtr tvm_polytopeR1_;
mutable mc_tvm::PolytopePtr tvm_polytopeR2_;

public:
static mc_rbdyn::Contact load(const mc_rbdyn::Robots & robots, const mc_rtc::Configuration & config);

Expand Down
7 changes: 6 additions & 1 deletion include/mc_rbdyn/Robot.h
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,12 @@ struct MC_RBDYN_DLLAPI Robot
const Eigen::Vector3d & zmpTarget() const;

/** Compute and returns the mass of the robot */
inline double mass() const noexcept { return mass_; }
inline double mass() const noexcept
{
double mass = 0.;
for(const auto & b : mb().bodies()) { mass += b.inertia().mass(); }
return mass;
}

/** @name Joint sensors
*
Expand Down
3 changes: 3 additions & 0 deletions include/mc_rbdyn/fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,7 @@ using ConstFramePtr = std::shared_ptr<const Frame>;

struct ForceSensor;

struct Contact;
using ContactPtr = std::shared_ptr<Contact>;

} // namespace mc_rbdyn
78 changes: 78 additions & 0 deletions include/mc_rtc/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,36 +52,114 @@ void critical(Args &&... args)
details::cerr().critical(std::forward<Args>(args)...);
}

/**
* Print an error message
*
* Displayed in red on terminals with color support
*
* @tparam Args Print all args using fmt format. The first argument can be an fmt formatting string
*/
template<typename... Args>
void error(Args &&... args)
{
details::cerr().error(std::forward<Args>(args)...);
}

/**
* Print optional error message
*/
template<typename... Args>
void error(bool print, Args &&... args)
{
if(print) { error(std::forward<Args>(args)...); }
}

/**
* Print a warning message
*
* Displayed in yellow on terminals with color support
*
* @tparam Args Print all args using fmt format. The first argument can be an fmt formatting string
*/
template<typename... Args>
void warning(Args &&... args)
{
details::cerr().warn(std::forward<Args>(args)...);
}

/**
* Print optional warning message
*/
template<typename... Args>
void warning(bool print, Args &&... args)
{
if(print) { warning(std::forward<Args>(args)...); }
}

/**
* Print an information message
*
* Displayed in blue on terminals with color support
*
* @tparam Args Print all args using fmt format. The first argument can be an fmt formatting string
*/
template<typename... Args>
void info(Args &&... args)
{
details::info().info(std::forward<Args>(args)...);
}

/**
* Print optional information message
*/
template<typename... Args>
void info(bool print, Args &&... args)
{
if(print) { info(std::forward<Args>(args)...); }
}

/**
* Print a success message
*
* Displayed in green on terminals with color support
*
* @tparam Args Print all args using fmt format. The first argument can be an fmt formatting string
*/
template<typename... Args>
void success(Args &&... args)
{
details::success().info(std::forward<Args>(args)...);
}

/**
* Print optional success message
*/
template<typename... Args>
void success(bool print, Args &&... args)
{
if(print) { success(std::forward<Args>(args)...); }
}

/**
* Displays a system notification
*
* @tparam Args Print all args using fmt format. The first argument can be an fmt formatting string
*/
template<typename... Args>
void notify(Args &&... args)
{
details::notify(fmt::format(std::forward<Args>(args)...));
}

/**
* Displays an optional system notification (libnotify, WinToast, etc.)
*/
template<typename... Args>
void notify(bool print, Args &&... args)
{
if(print) { notify(std::forward<Args>(args)...); }
}

} // namespace log

} // namespace mc_rtc
Expand Down
6 changes: 3 additions & 3 deletions include/mc_solver/QPSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ struct MC_SOLVER_DLLAPI QPSolver
virtual void setContacts(ControllerToken, const std::vector<mc_rbdyn::Contact> & contacts) = 0;

/** Returns the current set of contacts */
inline const std::vector<mc_rbdyn::Contact> & contacts() const noexcept { return contacts_; }
inline const std::vector<std::shared_ptr<mc_rbdyn::Contact>> & contacts() const noexcept { return contacts_; }

/** Returns the current set of constraints */
inline const std::vector<mc_solver::ConstraintSet *> & constraints() const noexcept { return constraints_; }
Expand Down Expand Up @@ -285,7 +285,7 @@ struct MC_SOLVER_DLLAPI QPSolver
std::shared_ptr<mc_rtc::Logger> logger() const;

/** Set the GUI helper for this solver instance */
void gui(std::shared_ptr<mc_rtc::gui::StateBuilder> gui);
virtual void gui(std::shared_ptr<mc_rtc::gui::StateBuilder> gui);
/** Access to the gui instance */
std::shared_ptr<mc_rtc::gui::StateBuilder> gui() const;

Expand All @@ -303,7 +303,7 @@ struct MC_SOLVER_DLLAPI QPSolver
double timeStep;

/** Holds mc_rbdyn::Contact in the solver */
std::vector<mc_rbdyn::Contact> contacts_;
std::vector<std::shared_ptr<mc_rbdyn::Contact>> contacts_;

/** Holds MetaTask currently in the solver */
std::vector<mc_tasks::MetaTask *> metaTasks_;
Expand Down
Loading
Loading