3#include <SimoxUtility/math/convert/mat4f_to_quat.h>
4#include <VirtualRobot/MathTools.h>
5#include <VirtualRobot/Nodes/RobotNode.h>
6#include <VirtualRobot/RobotNodeSet.h>
8#include <simox/control/dynamics/RBDLModel.h>
9#include <simox/control/robot/NodeInterface.h>
27 const Eigen::VectorXf& qvelFiltered,
28 Eigen::VectorXf& jointVel,
29 const float distanceThreshold)
const
33 const auto* node = collisionRobotIndices.at(collDataVec.
node1);
34 auto localTransformation = Eigen::Isometry3d::Identity();
35 localTransformation.translation() =
36 node->getGlobalPose().inverse() * collDataVec.
point1.cast<
double>();
37 const bool result =
nodeSet->computeJacobian(
40 simox::control::robot::JacobianParams{
41 .mode = simox::control::utils::CartesianSelection::Position,
42 .localTransformation = localTransformation});
46 float distThrSquare = distanceThreshold * distanceThreshold;
47 float factor =
c.maxRepulsiveVel / distThrSquare;
48 float diff = collDataVec.
minDistance - distanceThreshold;
61 (collDataVec.
direction.transpose() * collDataVec.
jacobian.cast<
float>()).transpose();
81 collDataVec.
damping *=
c.recoveryDampingFactor;
85 const float projectedJacNorm =
88 if (projectedJacNorm > 1e-3)
90 scale = 1.0f / projectedJacNorm;
97 const simox::control::robot::NodeSetInterface*
nodeSet) :
109 ARMARX_INFO <<
"Destruction of CollisionAvoidanceVelController";
121 const Eigen::VectorXf& qvelFiltered,
151 if (
c.enableCollisionRecoveryOnStartup and (thresholdInit <
c.recoveryDistanceElapseMeter))
153 thresholdInit =
c.selfDistanceThreshold;
156 float minDist =
static_cast<float>(collisionPair.minDistance);
157 if (minDist < thresholdInit)
159 thresholdInit = std::max(minDist, 0.0f);
163 std::min(
c.selfDistanceThreshold, thresholdInit +
c.recoveryDistanceElapseMeter);
176 if (collisionRobotIndices.count(collisionPair.node1) == 0 and
177 collisionRobotIndices.count(collisionPair.node2) == 0)
186 selfCollDataVec.minDistance =
static_cast<float>(collisionPair.minDistance);
188 bool flipped =
false;
189 if (collisionRobotIndices.count(collisionPair.node1) > 0)
193 if (collisionRobotIndices.count(collisionPair.node2) > 0)
199 selfCollDataVec.node1 = collisionPair.node1;
200 selfCollDataVec.node2 = collisionPair.node2;
201 selfCollDataVec.point1 = collisionPair.point1->cast<
float>();
202 selfCollDataVec.point2 = collisionPair.point2->cast<
float>();
209 selfCollDataVec.node1 = collisionPair.node2;
210 selfCollDataVec.node2 = collisionPair.node1;
211 selfCollDataVec.point1 = collisionPair.point2->cast<
float>();
212 selfCollDataVec.point2 = collisionPair.point1->cast<
float>();
216 selfCollDataVec.direction = selfCollDataVec.point1 - selfCollDataVec.point2;
218 if (selfCollDataVec.minDistance < 0.0f)
220 selfCollDataVec.minDistance = 0.0f;
224 if (selfCollDataVec.point1.isApprox(selfCollDataVec.point2, 1e-8) and
225 collisionPair.normalVec != std::nullopt)
238 selfCollDataVec.direction = collisionPair.normalVec->cast<
float>();
241 selfCollDataVec.direction *= -1.0f;
246 selfCollDataVec.direction *= -1.0f;
250 selfCollDataVec.direction.normalize();
255 collisionRobotIndices,
267 const Eigen::VectorXf& qpos,
268 const Eigen::VectorXf& qvelFiltered)
const
283 for (
size_t i = 0; i < n; ++i)
286 if (joint.isLimitless)
294 if (qpos[i] < joint.qposThresholdLow)
296 diff = joint.qposThresholdLow - qpos[i];
299 else if (qpos[i] > joint.qposThresholdHigh)
301 diff = qpos[i] - joint.qposThresholdHigh;
314 joint.repulsiveJointVel =
315 std::min(joint.kRepulsive * (diff * diff),
c.maxRepulsiveJointVel);
319 const float localStiffness = 2.0f * joint.kRepulsive * diff;
320 const float jointInertia = rts.
inertia(i, i);
323 const float dampingGain =
324 2.0f * std::sqrt(jointInertia * localStiffness) *
c.dampingFactor;
326 joint.totalDamping = dampingGain * qvelFiltered[i];
338 const common::control_law::arondto::CollisionAvoidanceVelConfig&
c,
359 if (active.minDistance <
c.selfCollActivatorZ1)
364 else if (
c.selfCollActivatorZ1 <= active.minDistance &&
365 active.minDistance <=
c.selfCollActivatorZ2)
369 rtStatus.
selfCollK2 * std::pow(active.minDistance, 2) +
375 "desired null space value should not be higher than 1.0");
403 if (
c.onlyLimitCollDirection)
409 if ((active.projectedJacT(i) < 0.0f and
428 const Eigen::VectorXf& qpos)
const
443 rts.
k1Lo = joint.jointLimitNullSpaceWeightsLow(0);
444 rts.
k2Lo = joint.jointLimitNullSpaceWeightsLow(1);
445 rts.
k3Lo = joint.jointLimitNullSpaceWeightsLow(2);
446 rts.
k4Lo = joint.jointLimitNullSpaceWeightsLow(3);
447 rts.
k1Hi = joint.jointLimitNullSpaceWeightsHigh(0);
448 rts.
k2Hi = joint.jointLimitNullSpaceWeightsHigh(1);
449 rts.
k3Hi = joint.jointLimitNullSpaceWeightsHigh(2);
450 rts.
k4Hi = joint.jointLimitNullSpaceWeightsHigh(3);
454 if (not joint.isLimitless)
457 if (qpos[i] < joint.qposZ1Low)
462 else if (joint.qposZ1Low <= qpos[i] && qpos[i] <= joint.qposZ2Low)
466 rts.
k2Lo * std::pow(qpos[i], 2) + rts.
k3Lo * qpos[i] +
471 <<
"desired null space value should not be higher than 1.0, was "
473 <<
", approaching lower joint limit, weights: " << rts.
k1Lo <<
", "
477 else if (joint.qposZ2High <= qpos[i] && qpos[i] <= joint.qposZ1High)
481 rts.
k2Hi * std::pow(qpos[i], 2) + rts.
k3Hi * qpos[i] +
486 <<
"desired null space value should not be higher than 1.0, was "
488 <<
", approaching upper joint limit, weights: " << rts.
k1Hi <<
", "
492 else if (joint.qposZ1High < qpos[i])
523 const Eigen::VectorXf& qpos,
524 const Eigen::VectorXf& qvelFiltered,
530 dynamicsModel.getInertiaMatrix(qpos.cast<
double>(), rtStatus.
inertia);
537 if (
c.enableSelfCollisionAvoidance)
545 collisionRobotIndices,
549 if (
c.enableJointLimitAvoidance)
556 if (
c.enableSelfCollisionAvoidance)
561 if (
c.enableJointLimitAvoidance)
570 if (
c.filterSafetyValues)
652 else if (
c.enableSelfCollisionAvoidance and
c.enableJointLimitAvoidance)
656 if (
c.topPrioritySelfCollisionAvoidance)
683 else if (
c.topPriorityJointLimitAvoidance)
732 else if (
c.enableSelfCollisionAvoidance)
750 else if (
c.enableJointLimitAvoidance)
794 std::clamp(rtStatus.
desiredJointVel(i), -velocityLimit, velocityLimit);
801 const unsigned int nDoF,
802 const unsigned int maxCollisionPairs,
803 VirtualRobot::RobotNodeSetPtr& rns)
858 Eigen::Vector3d point1(0.0, 0.0, 0.0);
859 Eigen::Vector3d point2(0.0, 0.0, 0.0);
860 Eigen::Vector3d
norm(0.0, 0.0, 0.0);
883 CollisionAvoidanceVelController::RtStatusForSafetyStrategy::initJointLimtDataVec(
921 CollisionAvoidanceVelController::RtStatusForSafetyStrategy::initJointLimtDataVec(
923 const unsigned int nDoF,
924 VirtualRobot::RobotNodeSetPtr& rns)
929 localStiffnessJointLim = 0.0;
930 dampingJointLim = 0.0;
941 jointLimitData.resize(nDoF);
944 for (
size_t i = 0; i < nDoF; ++i)
946 jointLimitData[i].jointName = rns->getNode(i)->getName();
947 jointLimitData[i].isLimitless = rns->getNode(i)->isLimitless();
949 if (not jointLimitData[i].isLimitless)
951 jointLimitData[i].qLimLow = rns->getNode(i)->getJointLimitLow();
952 jointLimitData[i].qLimHigh = rns->getNode(i)->getJointLimitHigh();
957 for (
auto& joint : jointLimitData)
959 if (not joint.isLimitless)
962 float qRange = joint.qLimHigh - joint.qLimLow;
963 joint.thresholdRange =
c.jointRangeBufferZone * qRange;
964 joint.invThresholdSq = 1.0f / (joint.thresholdRange * joint.thresholdRange);
965 joint.kRepulsive =
c.maxRepulsiveJointVel * joint.invThresholdSq;
966 joint.qposThresholdLow = joint.qLimLow + joint.thresholdRange;
967 joint.qposThresholdHigh = joint.qLimHigh - joint.thresholdRange;
968 float qposZ1 =
c.jointRangeBufferZoneZ1 * qRange;
969 float qposZ2 =
c.jointRangeBufferZoneZ2 * qRange;
970 joint.qposZ1Low = joint.qLimLow + qposZ1;
971 joint.qposZ2Low = joint.qLimLow + qposZ2;
972 joint.qposZ1High = joint.qLimHigh - qposZ1;
973 joint.qposZ2High = joint.qLimHigh - qposZ2;
974 joint.jointLimitNullSpaceWeightsLow =
976 joint.jointLimitNullSpaceWeightsHigh =
1052 if (cfg.topPrioritySelfCollisionAvoidance)
1056 (cfg.topPrioritySelfCollisionAvoidance == !cfg.topPriorityJointLimitAvoidance));
1058 if (cfg.topPriorityJointLimitAvoidance)
1062 (cfg.topPrioritySelfCollisionAvoidance == !cfg.topPriorityJointLimitAvoidance));
1071 if (not
c.enableCollisionRecoveryOnStartup or not rtStatus.
inRecoveryMode)
1084 std::min(
c.selfDistanceThreshold,
#define ARMARX_RT_LOGF_WARNING(...)
void update(const Config &c, RtStatusForSafetyStrategy &rtStatus, double deltaT)
float collDistanceThreshold
float collDistanceThresholdInit
internal status of the controller, containing intermediate variables, mutable targets
Eigen::MatrixXf selfCollTempNullSpaceMatrix
float impTorqueRatio
intermediate projected torques via null space matrices ===== to remove the following
Eigen::MatrixXf jointLimNullSpace
double selfCollNullspaceTime
double collisionTorqueTime
Eigen::VectorXf finalTorque
double jointLimitNullspaceTime
double jointLimitTorqueTime
unsigned int objectCollDataIndex
void reset(const Config &c, unsigned int nDoF, unsigned int maxCollisionPairs, VirtualRobot::RobotNodeSetPtr &rns)
Eigen::VectorXf torqueAcc
Eigen::MatrixXf jointLimNullSpaceFiltered
Eigen::MatrixXf objectCollTempNullSpaceMatrix
Eigen::VectorXf jointLimitJointVel
Eigen::VectorXf jointLimitVelFiltered
float totalForceImpedance
Eigen::MatrixXf objectCollNullSpace
Eigen::VectorXf objectCollisionVelFiltered
Eigen::MatrixXf selfCollNullSpace
intermediate null space matrices ((self-)collision and joint limit avoidance)
Eigen::MatrixXf objectCollNullSpaceFiltered
float objectCollK1
object collision avoidance null space intermediate results
Eigen::VectorXf objectCollNormalizedJacT
Eigen::Vector4f selfCollisionNullSpaceWeights
collision avoidance initialization parameters
unsigned int collisionPairsNum
collision pair info
float projTotalForceImpedance
Eigen::MatrixXf selfCollNullSpaceFiltered
Eigen::VectorXf desiredJointVel
targets
double timeSinceStart
Adaptive threshold for collision recovery.
Eigen::VectorXf selfCollisionJointVel
std::vector< JointRangeBufferZoneData > jointLimitData
joint limit avoidance initialization parameters
unsigned int activeCollPairsNum
Eigen::Vector3f dirErrorImp
double collisionPairTime
time status
Eigen::VectorXf selfCollNormalizedJacT
void rtPreActivate(const Config &c)
float selfCollK1
self collision avoidance null space intermediate results
std::vector< CollisionData > collDataVec
distance results
Eigen::MatrixXd inertia
others
Eigen::MatrixXf inertiaInverse
Eigen::VectorXf trajFollowJointVel
intermediate torque results
Eigen::VectorXf selfCollisionVelFiltered
Eigen::VectorXf objectCollisionJointVel
Eigen::MatrixXf nullSpaceAcc
for generating torques according to priority
Eigen::MatrixXf impedanceNullSpace
Eigen::Vector6f projForceImpedance
void run(const Config &c, RtStatusForSafetyStrategy &robotStatus, RecoveryState &rStateSelfColl, const DistanceResults &collisionPairs, const CollisionRobotIndices &collisionRobotIndices, DynamicsModel &dynamicsModel, const Eigen::VectorXf &qpos, const Eigen::VectorXf &qvelFiltered, float velocityLimit, double deltaT)
------------------------------— main rt-loop ---------------------------------------—
void calculateSelfCollisionVel(const Config &c, RtStatusForSafetyStrategy &rtStatus, RecoveryState &rState, const DistanceResults &collisionPairs, const CollisionRobotIndices &collisionRobotIndices, const Eigen::VectorXf &qvelFiltered, double deltaT) const
avoidance torque methods
void calculateJointLimitNullspace(const Config &c, RtStatusForSafetyStrategy &rtStatus, const Eigen::VectorXf &qpos) const
simox::control::dynamics::RBDLModel DynamicsModel
const simox::control::robot::NodeSetInterface * nodeSet
::simox::control::environment::DistanceResult DistanceResult
std::size_t numNodes() const
void calculateSelfCollisionNullspace(const Config &c, RtStatusForSafetyStrategy &rtStatus) const
caclulate null spaces
void calculateJointLimitVel(const Config &c, RtStatusForSafetyStrategy &rtStatus, const Eigen::VectorXf &qpos, const Eigen::VectorXf &qvelFiltered) const
std::vector< DistanceResult > DistanceResults
std::unordered_map< unsigned int, const simox::control::robot::NodeInterface * > CollisionRobotIndices
~CollisionAvoidanceVelController()
CollisionAvoidanceVelController(const simox::control::robot::NodeSetInterface *nodeSet)
void calculateCollisionJointVel(CollisionData &collDataVec, const Config &c, RtStatusForSafetyStrategy &rts, const CollisionRobotIndices &collisionRobotIndices, const Eigen::VectorXf &qvelFiltered, Eigen::VectorXf &jointTorque, float distanceThreshold) const
common::control_law::arondto::CollisionAvoidanceVelConfig Config
#define ARMARX_CHECK_GREATER(lhs, rhs)
This macro evaluates whether lhs is greater (>) than rhs and if it turns out to be false it will thro...
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_LESS_EQUAL(lhs, rhs)
This macro evaluates whether lhs is less or equal (<=) rhs and if it turns out to be false it will th...
#define ARMARX_CHECK_NONNEGATIVE(number)
Check whether number is nonnegative (>= 0).
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
void validateConfigData(const arondto::CollisionAvoidanceConfig &cfg)
Eigen::Vector4f calculateTransitionWeights(float z1, float z2)
helper functions
This file is part of ArmarX.
double norm(const Point &a)
Eigen::VectorXf projectedJacT
Eigen::Vector3f direction
unsigned int node1
the distances and projected jacobians from the generateSelfCollisionTorque() method are needed for th...
#define ARMARX_TRACE_LITE