ColAvoidVel.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package ...
17 * @author Jianfeng Gao ( jianfeng dot gao at kit dot edu )
18 * @date 2025
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#include "ColAvoidVel.h"
24
25#include <SimoxUtility/color/Color.h>
26#include <VirtualRobot/MathTools.h>
27#include <VirtualRobot/RobotNodeSet.h>
28
29#include <simox/control/environment/collision.h>
30#include <simox/control/geodesics/util.h>
31#include <simox/control/robot/NodeInterface.h>
32#include <simox/control/utils/primitive.h>
33
35#include <ArmarXCore/core/PackagePath.h> // for GUI
39
43
45#include <armarx/control/common/control_law/aron/CollisionPrimitives.aron.generated.h>
47
49{
50 template <typename NJointControllerType, typename CollisionCtrlCfg>
53 const NJointControllerConfigPtr& config,
54 const VirtualRobot::RobotPtr& robot) :
55 NJointControllerType{robotUnit, config, robot}
56 {
57 auto cfg = ConfigPtrT::dynamicCast(config);
59 userCfgWithColl = CollisionCtrlCfg::FromAron(cfg->config);
60
61 coll = std::make_shared<CollAvoidVelBase>(this->rtGetRobot(), userCfgWithColl.coll);
62 collReady.store(true);
63 // const std::string rootNodeName = "root";
64 // rootNode = this->rtGetRobot()->getRobotNode(rootNodeName);
65 }
66
67 template <typename NJointControllerType, typename CollisionCtrlCfg>
68 void
70 ArmPtr& arm,
71 const double deltaT)
72 {
73 // limbRTUpdateStatus(arm, deltaT);
75 arm->controller.run(arm->rtConfig, arm->rtStatus);
76 // double time_run_rt = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
77
78 if (collReady.load())
79 {
81 // const std::string rootNodeName = "root";
82 // // coll->collLimb.at(arm->kinematicChainName)->rts.globalPose = rootNode->getGlobalPose();
83 // coll->collLimb.at(arm->kinematicChainName).rts.globalPose =
84 // this->rtGetRobot()->getGlobalPose();
85 coll->rtLimbControllerRun(arm->kinematicChainName,
86 arm->rtStatus.jointPosition,
87 arm->rtStatus.qvelFiltered,
88 arm->rtConfig.velocityLimit,
89 arm->rtStatus.desiredJointVelocity,
90 deltaT);
91 /// experimental implementation of admittance interface
92 arm->rtStatus.inertia = coll->collLimb.at(arm->kinematicChainName).rts.inertia;
93 }
94
95 if (collReady.load())
96 {
97 this->limbRTSetTarget(arm,
98 arm->rtStatus.nDoFTorque,
99 arm->rtStatus.nDoFVelocity,
100 arm->rtStatus.desiredJointTorque,
101 coll->collLimb.at(arm->kinematicChainName).rts.desiredJointVel);
102 }
103 else
104 {
105 this->limbRTSetTarget(arm,
106 arm->rtStatus.nDoFTorque,
107 arm->rtStatus.nDoFVelocity,
108 arm->rtStatus.desiredJointTorque,
109 arm->rtStatus.desiredJointVelocity);
110 }
111 }
112
113 template <typename NJointControllerType, typename CollisionCtrlCfg>
114 void
116 const IceUtil::Time& sensorValuesTimestamp,
117 const IceUtil::Time& timeSinceLastIteration)
118 {
119 double deltaT = timeSinceLastIteration.toSecondsDouble();
120 // globalPose = rtGetRobot()->getRobotNode("root")->getGlobalPose();
121
122 if (collReady.load())
123 {
125 coll->updateRtConfigFromUser();
126 coll->updateRtCollisionObjects();
127 coll->rtCollisionChecking();
128 }
129 for (auto& pair : this->limb)
130 {
131 this->limbRTUpdateStatus(pair.second, deltaT);
132 }
133
134 this->rtRunCoordinator(deltaT);
135
136 for (auto& pair : this->limb)
137 {
138 limbRT(pair.second, deltaT);
139 }
140 if (this->hands)
141 {
142 this->hands->updateRTStatus(deltaT);
143 }
144 }
145
146 template <typename NJointControllerType, typename CollisionCtrlCfg>
147 void
149 updateCollisionAvoidanceConfig(const ::armarx::aron::data::dto::DictPtr& dto,
150 const Ice::Current& iceCurrent)
151 {
153 auto cfg =
154 common::control_law::arondto::ObjectCollisionAvoidanceVelConfigDict::FromAron(dto);
155 coll->setUserCfg(cfg);
156 }
157
158 template <typename NJointControllerType, typename CollisionCtrlCfg>
159 void
161 {
162 size_t numCollisionObjects = 0;
163 for (const auto& pair : collisionObjects)
164 {
165 numCollisionObjects += pair.second.size();
166 }
167
168 std::vector<hpp::fcl::CollisionObject> allCollisionObjects;
169 allCollisionObjects.reserve(numCollisionObjects);
170 for (const auto& pair : collisionObjects)
171 {
172 allCollisionObjects.insert(
173 allCollisionObjects.end(), pair.second.begin(), pair.second.end());
174 }
175
176 coll->updateUserCollisionObjects(allCollisionObjects);
177 }
178
179 template <typename NJointControllerType, typename CollisionCtrlCfg>
180 void
182 const Ice::Current& iceCurrent)
183 {
184 coll->deleteUserCollisionObjects();
185 }
186
187 template <typename NJointControllerType, typename CollisionCtrlCfg>
188 void
190 const std::string& primitiveSourceName,
191 const ::armarx::aron::data::dto::DictPtr& dto,
192 const Ice::Current& iceCurrent)
193 {
194 ARMARX_INFO_S << "updateCollisionObjects";
195 auto scene = common::control_law::arondto::CollisionScene::FromAron(dto);
196 auto boxes = scene.boxes;
197 auto spheres = scene.spheres;
198 auto cylinders = scene.cylinders;
199 auto capsules = scene.capsules;
200 auto ellipsoids = scene.ellipsoids;
201
202 if (collisionObjects.count(primitiveSourceName) == 0)
203 {
204 collisionObjects.emplace(primitiveSourceName, std::vector<hpp::fcl::CollisionObject>());
205 }
206 std::vector<hpp::fcl::CollisionObject>& collisionObjectsOfSource =
207 collisionObjects[primitiveSourceName];
208 collisionObjectsOfSource.clear();
209 collisionObjectsOfSource.reserve(boxes.size() + spheres.size() + cylinders.size() +
210 capsules.size() + ellipsoids.size());
211
212 for (auto box : boxes)
213 {
214 collisionObjectsOfSource.push_back(simox::control::environment::createCollisionObject(
215 simox::control::utils::primitive::Box{
216 .lengthX = box.lengthX, .lengthY = box.lengthY, .lengthZ = box.lengthZ},
217 Eigen::Isometry3d{box.transformation}));
218 }
219
220 for (auto sphere : spheres)
221 {
222 collisionObjectsOfSource.push_back(simox::control::environment::createCollisionObject(
223 simox::control::utils::primitive::Sphere{.radius = sphere.radius},
224 Eigen::Isometry3d{sphere.transformation}));
225 }
226
227 for (auto cylinder : cylinders)
228 {
229 collisionObjectsOfSource.push_back(simox::control::environment::createCollisionObject(
230 simox::control::utils::primitive::Cylinder{.radius = cylinder.radius,
231 .lengthY = cylinder.lengthY},
232 Eigen::Isometry3d{cylinder.transformation}));
233 }
234
235 for (auto capsule : capsules)
236 {
237 collisionObjectsOfSource.push_back(simox::control::environment::createCollisionObject(
238 simox::control::utils::primitive::Capsule{.radius = capsule.radius,
239 .lengthY = capsule.lengthY},
240 Eigen::Isometry3d{capsule.transformation}));
241 }
242
243 for (auto ellipsoid : ellipsoids)
244 {
245 collisionObjectsOfSource.push_back(simox::control::environment::createCollisionObject(
246 simox::control::utils::primitive::Ellipsoid{.lengthX = ellipsoid.lengthX,
247 .lengthY = ellipsoid.lengthY,
248 .lengthZ = ellipsoid.lengthZ},
249 Eigen::Isometry3d{ellipsoid.transformation}));
250 }
251
253 }
254
255 template <typename NJointControllerType, typename CollisionCtrlCfg>
258 getCollisionAvoidanceConfig(const Ice::Current& iceCurrent)
259 {
260 if (not collReady.load())
261 return nullptr;
262
264 return coll->userCfg.toAronDTO();
265 }
266
267 template <typename NJointControllerType, typename CollisionCtrlCfg>
268 void
270 const ::armarx::aron::data::dto::DictPtr& dto,
271 const Ice::Current& iceCurrent)
272 {
273 NJointControllerType::updateConfig(dto);
274 userCfgWithColl = CollisionCtrlCfg::FromAron(dto);
276 coll->setUserCfg(userCfgWithColl.coll);
277 }
278
279 template <typename NJointControllerType, typename CollisionCtrlCfg>
282 const Ice::Current& iceCurrent)
283 {
284 // for (auto& pair : this->limb)
285 // {
286 // this->userConfig.limbs.at(pair.first) =
287 // pair.second->bufferConfigRtToUser.getUpToDateReadBuffer();
288 // }
289 NJointControllerType::getConfig();
290 userCfgWithColl.limbs = this->userConfig.limbs;
291 userCfgWithColl.hands = this->userConfig.hands; // TODO check this
292 return userCfgWithColl.toAronDTO();
293 }
294
295 template <typename NJointControllerType, typename CollisionCtrlCfg>
296 void
299 const DebugObserverInterfacePrx& debugObs)
300 {
301 // double limbTimeMeasure = IceUtil::Time::now().toMicroSecondsDouble();
302
303 StringVariantBaseMap datafields;
304 auto rtStatus = arm.bufferRTtoPublish.getUpToDateReadBuffer();
305 auto recoveryState = arm.bufferRecoveryStateSelfColl.getUpToDateReadBuffer();
306
307 datafields["collDistanceThreshold"] = new Variant(recoveryState.collDistanceThreshold);
308 datafields["collDistanceThresholdInit"] =
309 new Variant(recoveryState.collDistanceThresholdInit);
310
311 datafields["trackingError"] = new Variant(rtStatus.trackingError);
312 common::debugEigenVec(datafields, "desiredJointVel", rtStatus.desiredJointVel);
313 common::debugEigenVec(datafields, "selfCollisionTorque", rtStatus.selfCollisionJointVel);
314 common::debugEigenVec(datafields, "jointLimitTorque", rtStatus.jointLimitJointVel);
315
316 // common::debugEigenVec(
317 // datafields, "projectedImpedanceTorque", rtStatus.projImpedanceJointTorque);
318 // common::debugEigenVec(datafields, "projectedJointLimitTorque", rtStatus.projJointLimTorque);
319 // common::debugEigenVec(datafields, "projectedForceImpedance", rtStatus.projForceImpedance);
320 // common::debugEigenVec(
321 // datafields, "projectedSelfCollisionTorque", rtStatus.projSelfCollTorque);
322
323 const Eigen::VectorXf selfCollNullspace = rtStatus.selfCollNullSpace.diagonal();
324 const Eigen::VectorXf jointLimNullspace = rtStatus.jointLimNullSpace.diagonal();
325 common::debugEigenVec(datafields, "selfCollNullspaceDiagonal", selfCollNullspace);
326 common::debugEigenVec(datafields, "jointLimNullspaceDiagonal", jointLimNullspace);
327
328 // if (rtData.enableJointLimitAvoidance)
329 // {
330 // for (size_t i = 0; i < rtStatus.jointLimitData.size(); ++i)
331 // {
332 // if (not rtStatus.jointLimitData[i].isLimitless)
333 // {
334 // datafields["n_des(q)_" + std::to_string(i) + "_" +
335 // rtStatus.jointLimitData[i].jointName] =
336 // new Variant(rtStatus.jointLimitData[i].desiredNSjointLim);
337 // datafields["q_damping" + std::to_string(i) + "_" +
338 // rtStatus.jointLimitData[i].jointName] =
339 // new Variant(rtStatus.jointLimitData[i].totalDamping);
340 // datafields["q_repTorque" + std::to_string(i) + "_" +
341 // rtStatus.jointLimitData[i].jointName] =
342 // new Variant(rtStatus.jointLimitData[i].repulsiveTorque);
343 // }
344 // }
345 // }
346
347 datafields["collisionPairsNum"] = new Variant(rtStatus.collisionPairsNum);
348 datafields["activeCollPairsNum"] = new Variant(rtStatus.activeCollPairsNum);
349
350 datafields["collisionPairTime"] = new Variant(rtStatus.collisionPairTime);
351 datafields["collisionTorqueTime"] = new Variant(rtStatus.collisionTorqueTime);
352 datafields["jointLimitTorqueTime"] = new Variant(rtStatus.jointLimitTorqueTime);
353 datafields["selfCollNullspaceTime"] = new Variant(rtStatus.selfCollNullspaceTime);
354 datafields["jointLimitNullspaceTime"] = new Variant(rtStatus.jointLimitNullspaceTime);
355
356 datafields["impForceRatio"] = new Variant(rtStatus.impForceRatio);
357 datafields["impTorqueRatio"] = new Variant(rtStatus.impTorqueRatio);
358
359 // auto& globalPose = rtStatus.globalPose;
360 // auto transformVector = [](const Eigen::Matrix4f& pose,
361 // const Eigen::Vector3f& vec) -> Eigen::Vector3f
362 // {
363 // // Eigen::Vector3f homogeneous_vector;
364 // // homogeneous_vector << vec, 1.0;
365 //
366 // return common::getOri(pose) * vec + common::getPos(pose);
367 // // return globalPose.head<3>() / globalPose(3);
368 // };
369
370 // double timeMeasure = IceUtil::Time::now().toMicroSecondsDouble();
371 // viz::Layer layer = arviz.layer(getClassName() + "_" + arm->nodeSetName);
372
373 for (unsigned int i = 0; i < rtStatus.activeCollPairsNum; ++i)
374 {
375 // visualize impedance force
376 // layer.add(viz::Arrow("projImpForce_" + std::to_string(i))
377 // .fromTo(rtStatus.collDataVec[i].point * 1000.0,
378 // rtStatus.collDataVec[i].point * 1000.0 +
379 // rtStatus.collDataVec[i].projectedImpedanceForce *
380 // rtStatus.collDataVec[i].direction * 5.0)
381 // .color(simox::Color::purple()));
382
383 // layer.add(viz::Arrow("impForce_" + std::to_string(i))
384 // .fromTo(rtStatus.collDataVec[i].point * 1000.0,
385 // rtStatus.collDataVec[i].point * 1000.0 +
386 // rtStatus.forceImpedance.head<3>().dot(
387 // rtStatus.collDataVec[i].direction) *
388 // rtStatus.collDataVec[i].direction * 5.0)
389 // .color(simox::Color::yellow())); // project forceImp in dir of collision
390
391 // layer.add(
392 // viz::Arrow("force_" + std::to_string(i))
393 // .fromTo(transformVector(rtStatus.globalPose,
394 // rtStatus.collDataVec[i].point * 1000.0f),
395 // transformVector(rtStatus.globalPose,
396 // rtStatus.collDataVec[i].point * 1000.0f +
397 // rtStatus.collDataVec[i].direction * 50.0f *
398 // rtStatus.collDataVec[i].repulsiveForce))
399 // .color(simox::Color::blue()));
400
401 //size_t index = rtStatus.distanceIndexPairs[i].second;
402 datafields[std::to_string(i) + "_minDistance"] =
403 new Variant(rtStatus.collDataVec[i].minDistance);
404 datafields[std::to_string(i) + "_repVel"] =
405 new Variant(rtStatus.collDataVec[i].repulsiveVel);
406 datafields[std::to_string(i) + "_dampingForce"] = new Variant(
407 -1.0f * rtStatus.collDataVec[i].damping * rtStatus.collDataVec[i].distanceVelocity);
408 datafields[std::to_string(i) + "_n_des(d)"] =
409 new Variant(rtStatus.collDataVec[i].desiredNSColl);
411 datafields, std::to_string(i) + "_point", rtStatus.collDataVec[i].point1);
413 datafields, std::to_string(i) + "_dir", rtStatus.collDataVec[i].direction);
414 }
415 // layer.add(viz::Pose("___root___").pose(rtStatus.globalPose).scale(2));
416
417
418 // /// prepare test case config
419 // const float tolerance = 1e-9f;
420 // if (rtData.testConfig == 1)
421 // {
422 // if (rtStatus.evalData[0].nodeName == "ArmL8_Wri2")
423 // {
424 // // set distance
425 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_dist"] =
426 // new Variant(rtStatus.evalData[0].minDistance);
427 // // set f_rep, damping, desired NS space
428
429
430 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_repF"] =
431 // new Variant(rtStatus.evalData[0].repulsiveForce);
432 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_projMass"] =
433 // new Variant(rtStatus.evalData[0].projectedMass);
434 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_locStiffness"] =
435 // new Variant(rtStatus.evalData[0].localStiffness);
436 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_dampFactor"] =
437 // new Variant(rtStatus.evalData[0].damping);
438 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_distVel"] =
439 // new Variant(rtStatus.evalData[0].distanceVelocity);
440 // if (fabs(rtStatus.evalData[0].damping + 1.0f) < tolerance)
441 // {
442 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_dampForce"] =
443 // new Variant(0.0);
444 // }
445 // else
446 // {
447 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_dampForce"] =
448 // new Variant(-1.0 * rtStatus.evalData[0].damping *
449 // rtStatus.evalData[0].distanceVelocity);
450 // }
451
452 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_n_des(d)"] =
453 // new Variant(rtStatus.evalData[0].desiredNSColl);
454 // }
455 // if (rtStatus.evalData[1].nodeName == "ArmL8_Wri2")
456 // {
457 // // set distance
458 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_dist"] =
459 // new Variant(rtStatus.evalData[1].minDistance);
460 // // set f_rep, damping, desired NS space
461
462 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_repF"] =
463 // new Variant(rtStatus.evalData[1].repulsiveForce);
464 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_projMass"] =
465 // new Variant(rtStatus.evalData[1].projectedMass);
466 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_locStiffness"] =
467 // new Variant(rtStatus.evalData[1].localStiffness);
468 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_dampFactor"] =
469 // new Variant(rtStatus.evalData[1].damping);
470 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_distVel"] =
471 // new Variant(rtStatus.evalData[1].distanceVelocity);
472 // if (fabs(rtStatus.evalData[1].damping + 1.0f) < tolerance)
473 // {
474 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_dampForce"] =
475 // new Variant(0.0);
476 // }
477 // else
478 // {
479 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_dampForce"] =
480 // new Variant(-1.0 * rtStatus.evalData[1].damping *
481 // rtStatus.evalData[1].distanceVelocity);
482 // }
483
484 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_n_des(d)"] =
485 // new Variant(rtStatus.evalData[1].desiredNSColl);
486 // }
487 // if (rtStatus.evalData[2].nodeName == "ArmL7_Wri1")
488 // {
489 // // set distance
490 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_dist"] =
491 // new Variant(rtStatus.evalData[2].minDistance);
492 // // set f_rep, damping, desired NS space
493
494 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_repF"] =
495 // new Variant(rtStatus.evalData[2].repulsiveForce);
496
497 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_projMass"] =
498 // new Variant(rtStatus.evalData[2].projectedMass);
499 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_locStiffness"] =
500 // new Variant(rtStatus.evalData[2].localStiffness);
501 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_dampFactor"] =
502 // new Variant(rtStatus.evalData[2].damping);
503 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_distVel"] =
504 // new Variant(rtStatus.evalData[2].distanceVelocity);
505 // if (fabs(rtStatus.evalData[2].damping + 1.0f) < tolerance)
506 // {
507 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_dampForce"] =
508 // new Variant(0.0);
509 // }
510 // else
511 // {
512 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_dampForce"] =
513 // new Variant(-1.0 * rtStatus.evalData[2].damping *
514 // rtStatus.evalData[2].distanceVelocity);
515 // }
516
517
518 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_n_des(d)"] =
519 // new Variant(rtStatus.evalData[2].desiredNSColl);
520 // }
521 // if (rtStatus.evalData[3].nodeName == "ArmL8_Wri2")
522 // {
523 // // set distance
524 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_dist"] =
525 // new Variant(rtStatus.evalData[3].minDistance);
526 // // set f_rep, damping, desired NS space
527
528 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_repF"] =
529 // new Variant(rtStatus.evalData[3].repulsiveForce);
530
531 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_projMass"] =
532 // new Variant(rtStatus.evalData[3].projectedMass);
533 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_locStiffness"] =
534 // new Variant(rtStatus.evalData[3].localStiffness);
535 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_dampFactor"] =
536 // new Variant(rtStatus.evalData[3].damping);
537 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_distVel"] =
538 // new Variant(rtStatus.evalData[3].distanceVelocity);
539 // if (fabs(rtStatus.evalData[3].damping + 1.0f) < tolerance)
540 // {
541 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_dampForce"] =
542 // new Variant(0.0);
543 // }
544 // else
545 // {
546 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_dampForce"] =
547 // new Variant(-1.0 * rtStatus.evalData[3].damping *
548 // rtStatus.evalData[3].distanceVelocity);
549 // }
550
551
552 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_n_des(d)"] =
553 // new Variant(rtStatus.evalData[3].desiredNSColl);
554 // }
555
556 // if (rtStatus.evalData[4].nodeName == "ArmL8_Wri2")
557 // {
558 // // set distance
559 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_dist"] =
560 // new Variant(rtStatus.evalData[4].minDistance);
561 // // set f_rep, damping, desired NS space
562
563 // // values have been calculated
564 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_repF"] =
565 // new Variant(rtStatus.evalData[4].repulsiveForce);
566
567 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_projMass"] =
568 // new Variant(rtStatus.evalData[4].projectedMass);
569 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_locStiffness"] =
570 // new Variant(rtStatus.evalData[4].localStiffness);
571 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_dampFactor"] =
572 // new Variant(rtStatus.evalData[4].damping);
573 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_distVel"] =
574 // new Variant(rtStatus.evalData[4].distanceVelocity);
575 // if (fabs(rtStatus.evalData[4].damping + 1.0f) < tolerance)
576 // {
577 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_dampForce"] =
578 // new Variant(0.0);
579 // }
580 // else
581 // {
582 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_dampForce"] =
583 // new Variant(-1.0 * rtStatus.evalData[4].damping *
584 // rtStatus.evalData[4].distanceVelocity);
585 // }
586
587
588 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_n_des(d)"] =
589 // new Variant(rtStatus.evalData[4].desiredNSColl);
590 // }
591 // if (rtStatus.evalData[5].nodeName == "ArmL8_Wri2")
592 // {
593 // // set distance
594 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_dist"] =
595 // new Variant(rtStatus.evalData[5].minDistance);
596
597 // // values have been calculated
598 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_repF"] =
599 // new Variant(rtStatus.evalData[5].repulsiveForce);
600
601 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_projMass"] =
602 // new Variant(rtStatus.evalData[5].projectedMass);
603 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_locStiffness"] =
604 // new Variant(rtStatus.evalData[5].localStiffness);
605 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_dampFactor"] =
606 // new Variant(rtStatus.evalData[5].damping);
607 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_distVel"] =
608 // new Variant(rtStatus.evalData[5].distanceVelocity);
609 // if (fabs(rtStatus.evalData[5].damping + 1.0f) < tolerance)
610 // {
611 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_dampForce"] =
612 // new Variant(0.0);
613 // }
614 // else
615 // {
616 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_dampForce"] =
617 // new Variant(-1.0 * rtStatus.evalData[5].damping *
618 // rtStatus.evalData[5].distanceVelocity);
619 // }
620
621
622 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_n_des(d)"] =
623 // new Variant(rtStatus.evalData[5].desiredNSColl);
624 // }
625 // if (rtStatus.evalData[6].nodeName == "ArmL5_Elb1")
626 // {
627 // // set distance
628 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_dist"] =
629 // new Variant(rtStatus.evalData[6].minDistance);
630
631 // // values have been calculated
632 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_repF"] =
633 // new Variant(rtStatus.evalData[6].repulsiveForce);
634
635 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_projMass"] =
636 // new Variant(rtStatus.evalData[6].projectedMass);
637 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_locStiffness"] =
638 // new Variant(rtStatus.evalData[6].localStiffness);
639 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_dampFactor"] =
640 // new Variant(rtStatus.evalData[6].damping);
641 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_distVel"] =
642 // new Variant(rtStatus.evalData[6].distanceVelocity);
643 // if (fabs(rtStatus.evalData[6].damping + 1.0f) < tolerance)
644 // {
645 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_dampForce"] =
646 // new Variant(0.0);
647 // }
648 // else
649 // {
650 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_dampForce"] =
651 // new Variant(-1.0 * rtStatus.evalData[6].damping *
652 // rtStatus.evalData[6].distanceVelocity);
653 // }
654
655
656 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_n_des(d)"] =
657 // new Variant(rtStatus.evalData[6].desiredNSColl);
658 // }
659 // }
660
661 // visualize impedance force
662
663 // layer.add(viz::Arrow("impForce")
664 // .fromTo(rtStatus.currentPose.block<3, 1>(0, 3),
665 // rtStatus.currentPose.block<3, 1>(0, 3) +
666 // rtStatus.forceImpedance.head<3>() * 1000.0)
667 // .color(simox::Color::yellow()));
668 // layer.add(viz::Arrow("projImpForce")
669 // .fromTo(rtStatus.currentPose.block<3, 1>(0, 3),
670 // rtStatus.currentPose.block<3, 1>(0, 3) +
671 // rtStatus.projForceImpedance.head<3>() * 1000.0)
672 // .color(simox::Color::purple()));
673
674 // layer.add(viz::Robot(filename).pose(Eigen::Matrix4f::Identity()))
675 // arviz.commit(layer);
676
677
678 //double selfCollDebugTime = IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
679 //datafields["selfCollDebugTime"] = new Variant(selfCollDebugTime);
680
681 // debug value assignment torso, neck joints
682 // datafields["torsoJointValue_float"] = new Variant(rtStatus.torsoJointValuef);
683 // datafields["neck1JointValue_float"] = new Variant(rtStatus.neck1JointValuef);
684 // datafields["neck2JointValue_float"] = new Variant(rtStatus.neck2JointValuef);
685
686 // datafields["torsoJointValue_double"] = new Variant(rtStatus.torsoJointValued);
687 // datafields["neck1JointValue_double"] = new Variant(rtStatus.neck1JointValued);
688 // datafields["neck2JointValue_double"] = new Variant(rtStatus.neck2JointValued);
689
690 // common::debugEigenVec(
691 // datafields, "set_ActuatedJointValues", rtStatus.setActuatedJointValues.cast<float>());
692 // common::debugEigenVec(
693 // datafields, "get_ActuatedJointValues", rtStatus.getActuatedJointValues.cast<float>());
694
695 // double limbTime = IceUtil::Time::now().toMicroSecondsDouble() - limbTimeMeasure;
696 // datafields["limbOnPublishTime"] = new Variant(limbTime);
697
698 debugObs->setDebugChannel("CollAvoid_ImpCtrl_" + arm.nodeSetName, datafields);
699 }
700
701 template <typename NJointControllerType, typename CollisionCtrlCfg>
702 void
704 const std::vector<hpp::fcl::CollisionObject>& objects,
705 const DebugObserverInterfacePrx& debugObs,
706 const std::string& layerSuffix)
707 {
708
709 viz::Layer objectLayer = arviz.layer(getName() + layerSuffix);
710 for (size_t i = 0; i < objects.size(); ++i)
711 {
712 auto object = objects.at(i);
713 const auto position = object.getTranslation().cast<float>() * 1000;
714 const Eigen::Matrix3f rotation = object.getRotation().cast<float>();
715
716 switch (object.getNodeType())
717 {
718 case hpp::fcl::NODE_TYPE::GEOM_BOX:
719 {
720 const hpp::fcl::Box* box =
721 std::static_pointer_cast<hpp::fcl::Box>(object.collisionGeometry()).get();
722 const viz::Box vizObject = viz::Box("box " + std::to_string(i))
723 .size(box->halfSide.cast<float>() * 1000 * 2)
724 .orientation(rotation)
725 .position(position)
726 .color(255, 0, 0, 128);
727 objectLayer.add(vizObject);
728 break;
729 }
730 case hpp::fcl::NODE_TYPE::GEOM_SPHERE:
731 {
732 const hpp::fcl::Sphere* sphere =
733 std::static_pointer_cast<hpp::fcl::Sphere>(object.collisionGeometry())
734 .get();
735 const viz::Sphere vizObject =
736 viz::Sphere("sphere " + std::to_string(i))
737 .radius(static_cast<float>(sphere->radius) * 1000)
738 .orientation(rotation)
739 .position(position)
740 .color(0, 0, 255, 128);
741 objectLayer.add(vizObject);
742 break;
743 }
744 case hpp::fcl::NODE_TYPE::GEOM_CYLINDER:
745 {
746 const hpp::fcl::Cylinder* cylinder =
747 std::static_pointer_cast<hpp::fcl::Cylinder>(object.collisionGeometry())
748 .get();
749 const viz::Cylinder vizObject =
750 viz::Cylinder("cylinder " + std::to_string(i))
751 .height(static_cast<float>(cylinder->halfLength) * 1000 * 2)
752 .radius(static_cast<float>(cylinder->radius) * 1000)
753 .orientation(rotation *
754 Eigen::AngleAxisf(M_PI / 2., Eigen::Vector3f::UnitX()))
755 .position(position)
756 .color(0, 255, 0, 128);
757 objectLayer.add(vizObject);
758 break;
759 }
760 case hpp::fcl::NODE_TYPE::GEOM_CAPSULE:
761 {
762 const hpp::fcl::Capsule* capsule =
763 std::static_pointer_cast<hpp::fcl::Capsule>(object.collisionGeometry())
764 .get();
765 const auto _rotation =
766 rotation * Eigen::AngleAxisf(M_PI / 2., Eigen::Vector3f::UnitX());
767 Eigen::Vector3f offset;
768 offset << 0, static_cast<float>(capsule->halfLength) * 1000, 0;
769 offset = _rotation * offset;
770
771 const viz::Sphere cap1 = viz::Sphere("capsule_cap1 " + std::to_string(i))
772 .radius(static_cast<float>(capsule->radius) * 1000)
773 .position(position + offset)
774 .orientation(_rotation)
775 .color(255, 200, 0, 128);
776 const viz::Sphere cap2 = viz::Sphere("capsule_cap2 " + std::to_string(i))
777 .radius(static_cast<float>(capsule->radius) * 1000)
778 .position(position - offset)
779 .orientation(_rotation)
780 .color(255, 200, 0, 128);
781 const viz::Cylinder vizObject =
782 viz::Cylinder("capsule_mid " + std::to_string(i))
783 .height(static_cast<float>(capsule->halfLength) * 1000 * 2)
784 .radius(static_cast<float>(capsule->radius) * 1000)
785 .color(255, 200, 0, 128)
786 .orientation(_rotation)
787 .position(position);
788 objectLayer.add(vizObject);
789 objectLayer.add(cap1);
790 objectLayer.add(cap2);
791 break;
792 }
793 case hpp::fcl::NODE_TYPE::GEOM_ELLIPSOID:
794 {
795 const hpp::fcl::Ellipsoid* ellipsoid =
796 std::static_pointer_cast<hpp::fcl::Ellipsoid>(object.collisionGeometry())
797 .get();
798 const viz::Ellipsoid vizObject =
799 viz::Ellipsoid("ellipsoid " + std::to_string(i))
800 // axis lengths seem to be radii instead of axis lengths
801 .axisLengths(ellipsoid->radii.cast<float>() * 1000)
802 .orientation(rotation)
803 .position(position)
804 .color(255, 0, 200, 128);
805 objectLayer.add(vizObject);
806 break;
807 }
808 default:;
809 }
810 }
811 arviz.commit(objectLayer);
812 }
813
814 template <typename NJointControllerType, typename CollisionCtrlCfg>
815 void
817 const SensorAndControl& sc,
818 const DebugDrawerInterfacePrx& drawer,
819 const DebugObserverInterfacePrx& debugObs)
820 {
821 NJointControllerType::onPublish(sc, drawer, debugObs);
822 if (coll)
823 {
824 for (auto& pair : coll->collLimb)
825 {
826 collLimbPublish(pair.second, debugObs);
827 }
828 collObjectPublish(coll->userCollisionObjects, debugObs, "_collisionObjects");
829
830 // TODO uses rt collision robot
831 const auto& robotObjects = coll->collisionRobot->getCollisionManager()->getObjects();
832 std::vector<hpp::fcl::CollisionObject> robotObjectsByValue;
833 for (const auto* ptr : robotObjects)
834 {
835 robotObjectsByValue.push_back(*ptr);
836 }
837 collObjectPublish(robotObjectsByValue, debugObs, "_collisionRobot");
838 }
839 }
840
841 template <typename NJointControllerType, typename CollisionCtrlCfg>
842 void
844 {
845 // ARMARX_RT_LOGF_INFO("rt Preactivate controller "
846 // "NJointTaskspaceCollisionAvoidanceMixedImpedanceVelocityController");
847 NJointControllerType::rtPreActivateController();
849 if (collReady.load())
850 {
852 coll->rtPreActivate();
853 }
854 }
855
856 template <typename NJointControllerType, typename CollisionCtrlCfg>
857 void
858 NJointTSVelBasedColController<NJointControllerType,
860 {
861 NJointControllerType::rtPostDeactivateController();
862 if (collReady.load())
863 {
865 coll->rtPostDeactivate();
866 }
867 // ARMARX_RT_LOGF_INFO("-- post deactivate: "
868 // "NJointTaskspaceCollisionAvoidanceMixedImpedanceVelocityController");
869 }
870
871 template <typename NJointControllerType, typename CollisionCtrlCfg>
875 {
876 auto cfgName = values.at("config_box")->getString();
877 const armarx::PackagePath configPath(
878 "armarx_control",
879 "controller_config/" + std::string(NJointControllerType::ControlType::TypeName) +
880 "Col/" + cfgName + ".json");
881 ARMARX_INFO_S << "Loading config from " << configPath.toSystemPath();
882 ARMARX_CHECK(std::filesystem::exists(configPath.toSystemPath()));
883
884 auto cfgDTO = armarx::readFromJson<CollisionCtrlCfg>(configPath.toSystemPath());
885
887 return new ConfigurableNJointControllerConfig{cfgDTO.toAronDTO()};
888 }
889
890 /// ================================== TSMixImpVelCol ==================================
892 law::arondto::TSVelColConfigDict>;
893
896
898 const NJointControllerConfigPtr& config,
899 const VirtualRobot::RobotPtr& robot) :
900 // NJointTSVelController(robotUnit, config, robot),
902 robotUnit,
903 config,
904 robot)
905 {
906 }
907
908 std::string
909 NJointTSVelColController::getClassName(const Ice::Current&) const
910 {
911 return "TSVelCol";
912 }
913
914} // namespace armarx::control::njoint_controller::task_space
#define M_PI
Definition MathTools.h:17
std::string getName() const
Retrieve name of object.
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
const T & getUpToDateReadBuffer() const
The Variant class is described here: Variants.
Definition Variant.h:224
void collObjectPublish(const std::vector< hpp::fcl::CollisionObject > &objects, const DebugObserverInterfacePrx &debugObs, const std::string &layerSuffix)
void collLimbPublish(CollAvoidVelBase::NodeSetData &arm, const DebugObserverInterfacePrx &debugObs)
std::map< std::string, std::vector< hpp::fcl::CollisionObject > > collisionObjects
void updateCollisionAvoidanceConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
NJointController interface for collision avoidance.
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
void updateCollisionObjects(const std::string &primitiveSourceName, const ::armarx::aron::data::dto::DictPtr &scene, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
static ConfigPtrT GenerateConfigFromVariants(const StringVariantBaseMap &values)
void onPublish(const SensorAndControl &sc, const DebugDrawerInterfacePrx &drawer, const DebugObserverInterfacePrx &) override
::armarx::aron::data::dto::DictPtr getConfig(const Ice::Current &iceCurrent) override
NJointTSVelBasedColController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
void rtPreActivateController() override
NJointControllerBase interface.
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent) override
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
NJointTSVelColController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
void limbRTSetTarget(ArmPtr &arm, const size_t nDoFTorque, const size_t nDoFVelocity, const Eigen::VectorXf &targetTorque, const Eigen::VectorXf &targetVelocity)
Definition Base.cpp:365
DerivedT & color(Color color)
Definition ElementOps.h:218
DerivedT & position(float x, float y, float z)
Definition ElementOps.h:136
DerivedT & orientation(Eigen::Quaternionf const &ori)
Definition ElementOps.h:152
#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_INFO_S
Definition Logging.h:200
armarx::aron::data::dto::Dict getCollisionAvoidanceConfig()
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
::IceInternal::Handle< Dict > DictPtr
void debugEigenVec(StringVariantBaseMap &datafields, const std::string &name, Eigen::VectorXf vec)
Definition utils.cpp:190
NJointControllerRegistration< NJointTSVelColController > registrationControllerNJointTSVelColController("TSVelCol")
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
AronDTO readFromJson(const std::filesystem::path &filename)
IceUtil::Handle< class RobotUnit > RobotUnitPtr
Definition FTSensor.h:34
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl
Box & size(Eigen::Vector3f const &s)
Definition Elements.h:52
Cylinder & height(float h)
Definition Elements.h:84
Cylinder & radius(float r)
Definition Elements.h:76
Ellipsoid & axisLengths(const Eigen::Vector3f &axisLengths)
Definition Elements.h:156
void add(ElementT const &element)
Definition Layer.h:31
Sphere & radius(float r)
Definition Elements.h:138
#define ARMARX_TRACE
Definition trace.h:75