1919
2020#include < Tasks/QPConstr.h>
2121
22+ #include " mc_rbdyn/Collision.h"
23+ #include " mc_rtc/log/Logger.h"
24+ #include " mc_solver/QPSolver.h"
25+ #include < algorithm>
2226#include < tvm/task_dynamics/VelocityDamper.h>
2327
2428#include " utils/jointsToSelector.h"
@@ -113,12 +117,16 @@ struct TVMCollisionConstraint
113117 void addCollision (TVMQPSolver & solver, CollisionData & data)
114118 {
115119 const auto & col = data.collision ;
116- data.task = solver.problem ().add (
117- data.function >= 0 .,
118- tvm::task_dynamics::VelocityDamper (
119- solver.dt (), {col.iDist , col.sDist , col.damping , mc_solver::CollisionsConstraint::defaultDampingOffset},
120- tvm::constant::big_number),
121- {tvm::requirements::PriorityLevel (0 )});
120+ mc_rtc::log::info (" [CollisionsConstraint] Adding collision constraint with xsi={}, xsioff={}, m={}, lambda={}" ,
121+ col.damping , mc_solver::CollisionsConstraint::defaultDampingOffset, col.overDamping , col.lambda );
122+ data.task =
123+ solver.problem ().add (data.function >= 0 .,
124+ tvm::task_dynamics::VelocityDamper (solver.dt (),
125+ {col.iDist , col.sDist , col.damping ,
126+ mc_solver::CollisionsConstraint::defaultDampingOffset,
127+ col.overDamping , col.lambda },
128+ tvm::constant::big_number),
129+ {tvm::requirements::PriorityLevel (0 )});
122130 }
123131};
124132
@@ -368,6 +376,54 @@ void CollisionsConstraint::__addCollision(mc_solver::QPSolver & solver, const mc
368376 break ;
369377 }
370378 addMonitorButton (collId, col);
379+ if (logCollisions_) addLogs (collId, col);
380+ }
381+
382+ void CollisionsConstraint::__editCollision (mc_solver::QPSolver & solver, const mc_rbdyn::Collision & col)
383+ {
384+ // Check for the correct backend
385+ if (backend_ != QPSolver::Backend::TVM )
386+ {
387+ mc_rtc::log::error (" [CollisionsConstraint] Editing collisions is only supported for TVM backend currently." );
388+ return ;
389+ }
390+
391+ // Find the collision in the existing set of constraints
392+ auto collIdIt = collIdDict.find (__keyByNames (col.body1 , col.body2 ));
393+ if (collIdIt == collIdDict.end ())
394+ {
395+ mc_rtc::log::error (" [CollisionsConstraint] Attempting to edit a non-existent collision: {} - {}" , col.body1 ,
396+ col.body2 );
397+ return ;
398+ }
399+
400+ // Get the current collision data
401+ int collId = collIdIt->second .first ;
402+
403+ // Remove from collision vector
404+ // cols.erase(std::find(cols.begin(), cols.end(), p.second));
405+
406+ if (backend_ == QPSolver::Backend::TVM )
407+ {
408+ // Remove the existing collision
409+ tvm_constraint (constraint_)->deleteCollision (tvm_solver (solver), col);
410+ }
411+ else if (backend_ == QPSolver::Backend::Tasks)
412+ {
413+ // Remove the existing collision
414+ auto collConstr = tasks_constraint (constraint_);
415+ auto & qpsolver = tasks_solver (solver);
416+ bool ret = collConstr->rmCollision (collId);
417+ if (ret)
418+ {
419+ collConstr->updateNrVars ({}, qpsolver.data ());
420+ qpsolver.updateConstrSize ();
421+ }
422+ }
423+
424+ addCollision (solver, {col});
425+
426+ mc_rtc::log::info (" [CollisionsConstraint] Edited collision: {} - {}" , col.body1 , col.body2 );
371427}
372428
373429void CollisionsConstraint::addMonitorButton (int collId, const mc_rbdyn::Collision & col)
@@ -384,6 +440,45 @@ void CollisionsConstraint::addMonitorButton(int collId, const mc_rbdyn::Collisio
384440 }
385441}
386442
443+ void CollisionsConstraint::addLogs (int collId, const mc_rbdyn::Collision & col)
444+ {
445+ if (logger_ && inSolver_)
446+ {
447+ auto & logger = *logger_;
448+ std::string label = col.body1 + " ::" + col.body2 ;
449+ auto addLogger = [&](auto && distance_callback, auto && di_callback, auto && ds_callback)
450+ {
451+ logger.addLogEntry (" CollisionMonitor_" + label + " _distance" ,
452+ [distance_callback]() { return distance_callback (); });
453+ logger.addLogEntry (" CollisionMonitor_" + label + " _di" , [di_callback]() { return di_callback (); });
454+ logger.addLogEntry (" CollisionMonitor_" + label + " _ds" , [ds_callback]() { return ds_callback (); });
455+ };
456+ // Add the monitor
457+ switch (backend_)
458+ {
459+ case QPSolver::Backend::Tasks:
460+ {
461+ auto collConstr = tasks_constraint (constraint_);
462+ addLogger ([collConstr, collId]() { return collConstr->getCollisionData (collId).distance ; },
463+ [collConstr, collId]() { return collConstr->getCollisionData (collId).di ; },
464+ [collConstr, collId]() { return collConstr->getCollisionData (collId).ds ; });
465+ break ;
466+ }
467+ case QPSolver::Backend::TVM :
468+ {
469+ auto collConstr = tvm_constraint (constraint_);
470+ auto fn = collConstr->getData (collId)->function ;
471+ addLogger ([fn]() { return fn->distance (); },
472+ [collConstr, collId]() { return collConstr->getData (collId)->collision .iDist ; },
473+ [collConstr, collId]() { return collConstr->getData (collId)->collision .sDist ; });
474+ break ;
475+ }
476+ default :
477+ break ;
478+ }
479+ }
480+ }
481+
387482void CollisionsConstraint::toggleCollisionMonitor (int collId, const mc_rbdyn::Collision * col_p)
388483{
389484 auto findCollisionById = [this , collId, &col_p]()
@@ -474,9 +569,36 @@ void CollisionsConstraint::addCollisions(QPSolver & solver, const std::vector<mc
474569 }
475570}
476571
572+ void CollisionsConstraint::editCollisions (QPSolver & solver, const std::vector<mc_rbdyn::Collision> & cols)
573+ {
574+ // Check if the backend is TVM, as editing collisions is only supported for TVM
575+ if (backend_ != QPSolver::Backend::TVM )
576+ {
577+ mc_rtc::log::error (" [CollisionsConstraint] Editing collisions is only supported for TVM backend currently." );
578+ return ;
579+ }
580+ // Clear the existing collisions
581+ // tvm_constraint(constraint_)->clear();
582+ // Iterate over the list of collisions and call __editCollision for each
583+ for (const auto & col : cols) { __editCollision (solver, col); }
584+
585+ mc_rtc::log::info (" [CollisionsConstraint] Successfully edited {} collisions." , cols.size ());
586+ }
587+
588+ void CollisionsConstraint::setCollisionsDampers (QPSolver & solver, const std::vector<double > & dampers)
589+ {
590+ for (auto & col : cols)
591+ {
592+ col.overDamping = dampers[0 ];
593+ col.lambda = dampers[1 ];
594+ }
595+ editCollisions (solver, cols);
596+ }
597+
477598void CollisionsConstraint::addToSolverImpl (QPSolver & solver)
478599{
479600 gui_ = solver.gui ();
601+ logger_ = solver.logger ();
480602 const mc_rbdyn::Robot & r1 = solver.robots ().robot (r1Index);
481603 const mc_rbdyn::Robot & r2 = solver.robots ().robot (r2Index);
482604 category_ = {" Collisions" , r1.name () + " /" + r2.name ()};
@@ -500,7 +622,11 @@ void CollisionsConstraint::addToSolverImpl(QPSolver & solver)
500622 default :
501623 break ;
502624 }
503- for (const auto & cols : collIdDict) { addMonitorButton (cols.second .first , cols.second .second ); }
625+ for (const auto & cols : collIdDict)
626+ {
627+ addMonitorButton (cols.second .first , cols.second .second );
628+ if (logCollisions_) { addLogs (cols.second .first , cols.second .second ); };
629+ }
504630}
505631
506632void CollisionsConstraint::update (QPSolver &)
0 commit comments