ObjectCollisionAvoidanceImpedanceController.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 2021
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
25#include <VirtualRobot/MathTools.h>
26#include <VirtualRobot/RobotNodeSet.h>
27
29#include <ArmarXCore/core/PackagePath.h> // for GUI
33
38
42
43#include <simox/control/geodesics/util.h>
44#include <simox/control/robot/NodeInterface.h>
45#include <simox/control/environment/collision.h>
46#include <simox/control/utils/primitive.h>
47
49
51{
52 NJointControllerRegistration<NJointTaskspaceObjectCollisionAvoidanceImpedanceController>
54 "NJointTaskspaceObjectCollisionAvoidanceImpedanceController");
55
59 const NJointControllerConfigPtr& config,
60 const VirtualRobot::RobotPtr& robot) :
62 {
63 ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
65 userCfgWithColl = CollisionCtrlCfg::FromAron(cfg->config);
66
67 coll = std::make_shared<core::ObjectCollisionAvoidanceBase>(rtGetRobot(), userCfgWithColl.coll);
68 collReady.store(true);
69 ARMARX_INFO << "-- " << getClassName() << " initialized --";
70 }
71
72 std::string
74 {
75 return "NJointTaskspaceObjectCollisionAvoidanceImpedanceController";
76 }
77
78 void
80 {
81 double time_measure = IceUtil::Time::now().toMicroSecondsDouble();
82 limbRTUpdateStatus(arm, deltaT);
83 double time_update_status = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
84
85 arm->controller.run(arm->rtConfig, arm->rtStatus);
86 double time_run_rt = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
87
88 if (collReady.load())
89 {
91 coll->rtLimbControllerRun(arm->kinematicChainName,
92 arm->rtStatus.jointPosition,
93 arm->rtStatus.qvelFiltered,
94 arm->rtConfig.torqueLimit,
95 arm->rtStatus.desiredJointTorque);
96 }
97 double time_coll_run = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
98
99 if (collReady.load())
100 {
101 limbRTSetTarget(arm,
102 coll->collLimb.at(arm->kinematicChainName).rts.desiredJointTorques);
103 }
104 else
105 {
106 limbRTSetTarget(arm, arm->rtStatus.desiredJointTorque);
107 }
108 double time_set_target = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
109
110 time_measure = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
111
112 if (time_measure > 200)
113 {
114 ARMARX_RT_LOGF_WARN("---- rt too slow: "
115 "time_update_status: %.2f\n"
116 "run_rt_limb: %.2f\n"
117 "run_coll_rt_limb: %.2f\n"
118 "set_target_limb: %.2f\n"
119 "time all: %.2f\n",
120 time_update_status, // 0-1 us
121 time_run_rt - time_update_status, //
122 time_coll_run - time_run_rt, //
123 time_set_target - time_coll_run, //
124 time_measure)
125 .deactivateSpam(1.0f); // 0-1 us
126 }
127 }
128
129 void
131 const IceUtil::Time& sensorValuesTimestamp,
132 const IceUtil::Time& timeSinceLastIteration)
133 {
134 double deltaT = timeSinceLastIteration.toSecondsDouble();
135
136 if (collReady.load())
137 {
139 coll->updateRtConfigFromUser();
140 coll->updateRtCollisionObjects();
141 coll->rtCollisionChecking();
142 }
143 for (auto& pair : limb)
144 {
145 this->limbRT(pair.second, deltaT);
146 }
147 if (hands)
148 {
149 hands->updateRTStatus(deltaT);
150 hands->setTargets();
151 }
152 }
153
154 Eigen::Isometry3d
155 NJointTaskspaceObjectCollisionAvoidanceImpedanceController::matrixToIsometry(Eigen::Matrix<double, 4, 4> transformation)
156 {
157 Eigen::Matrix3d rotation = transformation.block<3,3>(0,0);
158 Eigen::Vector3d translation = transformation.block<3,1>(0,3);
159 Eigen::Isometry3d transform;
160 transform.linear() = rotation;
161 transform.translation() = translation;
162 return transform;
163 }
164
165 void
167 const ::armarx::aron::data::dto::DictPtr& dto,
168 const Ice::Current& iceCurrent)
169 {
171 auto cfg = common::control_law::arondto::ObjectCollisionAvoidanceConfigDict::FromAron(dto);
172 coll->setUserCfg(cfg);
173 }
174
175 void
177 {
178 size_t numCollisionObjects = 0;
179 for (const auto& pair : collisionObjects) {
180 numCollisionObjects += pair.second.size();
181 }
182
183 std::vector<hpp::fcl::CollisionObject> allCollisionObjects;
184 allCollisionObjects.reserve(numCollisionObjects);
185 for (const auto& pair : collisionObjects) {
186 allCollisionObjects.insert(allCollisionObjects.end(), pair.second.begin(), pair.second.end());
187 }
188
189 coll->updateUserCollisionObjects(allCollisionObjects);
190 }
191
192 void
194 const std::string& primitiveSourceName,
195 const ::armarx::aron::data::dto::DictPtr& dto,
196 const Ice::Current& iceCurrent)
197 {
198 ARMARX_INFO_S << "updateCollisionObjects";
199 auto scene = common::control_law::arondto::CollisionScene::FromAron(dto);
200 auto boxes = scene.boxes;
201 auto spheres = scene.spheres;
202 auto cylinders = scene.cylinders;
203 auto capsules = scene.capsules;
204 auto ellipsoids = scene.ellipsoids;
205
206 if (collisionObjects.count(primitiveSourceName) == 0)
207 {
208 collisionObjects.emplace(primitiveSourceName, std::vector<hpp::fcl::CollisionObject>());
209 }
210 std::vector<hpp::fcl::CollisionObject>& collisionObjectsOfSource = collisionObjects[primitiveSourceName];
211 collisionObjectsOfSource.clear();
212 collisionObjectsOfSource.reserve(boxes.size() + spheres.size() + cylinders.size() + capsules.size() + ellipsoids.size());
213
214 for (auto box : boxes)
215 {
216 collisionObjectsOfSource.push_back(
217 simox::control::environment::createCollisionObject(
218 simox::control::utils::primitive::Box{.lengthX = box.lengthX, .lengthY = box.lengthY, .lengthZ = box.lengthZ},
219 matrixToIsometry(box.transformation)
220 )
221 );
222 }
223
224 for (auto sphere : spheres)
225 {
226 collisionObjectsOfSource.push_back(
227 simox::control::environment::createCollisionObject(
228 simox::control::utils::primitive::Sphere{.radius = sphere.radius},
229 matrixToIsometry(sphere.transformation)
230 )
231 );
232 }
233
234 for (auto cylinder : cylinders)
235 {
236 collisionObjectsOfSource.push_back(
237 simox::control::environment::createCollisionObject(
238 simox::control::utils::primitive::Cylinder{.radius = cylinder.radius, .lengthY = cylinder.lengthY},
239 matrixToIsometry(cylinder.transformation)
240 )
241 );
242 }
243
244 for (auto capsule : capsules)
245 {
246 collisionObjectsOfSource.push_back(
247 simox::control::environment::createCollisionObject(
248 simox::control::utils::primitive::Capsule{.radius = capsule.radius, .lengthY = capsule.lengthY},
249 matrixToIsometry(capsule.transformation)
250 )
251 );
252 }
253
254 for (auto ellipsoid : ellipsoids)
255 {
256 collisionObjectsOfSource.push_back(
257 simox::control::environment::createCollisionObject(
258 simox::control::utils::primitive::Ellipsoid{.lengthX = ellipsoid.lengthX, .lengthY = ellipsoid.lengthY, .lengthZ = ellipsoid.lengthZ},
259 matrixToIsometry(ellipsoid.transformation)
260 )
261 );
262 }
263
265 }
266
267
268
271 const Ice::Current& iceCurrent)
272 {
273 if (not collReady.load())
274 return nullptr;
275
277 return coll->userCfg.toAronDTO();
278 }
279
280 void
282 const ::armarx::aron::data::dto::DictPtr& dto,
283 const Ice::Current& iceCurrent)
284 {
286 userCfgWithColl = CollisionCtrlCfg::FromAron(dto);
288 coll->setUserCfg(userCfgWithColl.coll);
289 }
290
293 {
295 userCfgWithColl.limbs = userConfig.limbs;
296 userCfgWithColl.hands = userConfig.hands;
297 return userCfgWithColl.toAronDTO();
298 }
299
300 void
303 const DebugObserverInterfacePrx& debugObs)
304 {
305 // double limbTimeMeasure = IceUtil::Time::now().toMicroSecondsDouble();
306
307 StringVariantBaseMap datafields;
308 auto rtStatus = arm.bufferRTtoPublish.getUpToDateReadBuffer();
309
310 datafields["trackingError"] = new Variant(rtStatus.trackingError);
311 common::debugEigenVec(datafields, "desiredJointTorques", rtStatus.desiredJointTorques);
312 common::debugEigenVec(datafields, "selfCollisionTorque", rtStatus.selfCollisionJointTorque);
313 common::debugEigenVec(datafields, "jointLimitTorque", rtStatus.jointLimitJointTorque);
314
316 datafields, "projectedImpedanceTorque", rtStatus.projImpedanceJointTorque);
317 // common::debugEigenVec(datafields, "projectedJointLimitTorque", rtStatus.projJointLimTorque);
318 // common::debugEigenVec(datafields, "projectedForceImpedance", rtStatus.projForceImpedance);
319 // common::debugEigenVec(
320 // datafields, "projectedSelfCollisionTorque", rtStatus.projSelfCollTorque);
321
322 Eigen::VectorXf selfCollNullspace = rtStatus.selfCollNullSpace.diagonal();
323 Eigen::VectorXf jointLimNullspace = rtStatus.jointLimNullSpace.diagonal();
324 common::debugEigenVec(datafields, "selfCollNullspaceDiagonal", selfCollNullspace);
325 common::debugEigenVec(datafields, "jointLimNullspaceDiagonal", jointLimNullspace);
326
327 // if (rtData.enableJointLimitAvoidance)
328 // {
329 // for (size_t i = 0; i < rtStatus.jointLimitData.size(); ++i)
330 // {
331 // if (not rtStatus.jointLimitData[i].isLimitless)
332 // {
333 // datafields["n_des(q)_" + std::to_string(i) + "_" +
334 // rtStatus.jointLimitData[i].jointName] =
335 // new Variant(rtStatus.jointLimitData[i].desiredNSjointLim);
336 // datafields["q_damping" + std::to_string(i) + "_" +
337 // rtStatus.jointLimitData[i].jointName] =
338 // new Variant(rtStatus.jointLimitData[i].totalDamping);
339 // datafields["q_repTorque" + std::to_string(i) + "_" +
340 // rtStatus.jointLimitData[i].jointName] =
341 // new Variant(rtStatus.jointLimitData[i].repulsiveTorque);
342 // }
343 // }
344 // }
345
346 // datafields["activeCollPairsNum"] = new Variant(rtStatus.activeCollPairsNum);
347 // datafields["collisionPairsNum"] = new Variant(rtStatus.collisionPairsNum);
348 // datafields["jointLimitNullspaceTime"] = new Variant(rtStatus.jointLimitNullspaceTime);
349 // datafields["jointLimitTorqueTime"] = new Variant(rtStatus.jointLimitTorqueTime);
350 // datafields["collisionTorqueTime"] = new Variant(rtStatus.collisionTorqueTime);
351 // datafields["collNullspaceTime"] = new Variant(rtStatus.collNullspaceTime);
352 // datafields["collisionPairTime"] = new Variant(rtStatus.collisionPairTime);
353 // datafields["impForceRatio"] = new Variant(rtStatus.impForceRatio);
354 // datafields["impTorqueRatio"] = new Variant(rtStatus.impTorqueRatio);
355
356 // double timeMeasure = IceUtil::Time::now().toMicroSecondsDouble();
357 viz::Layer layer = arviz.layer(getName() + "_" + arm.nodeSetName);
358 for (int i = 0; i < rtStatus.activeCollPairsNum; ++i) {
359 // visualize impedance force
360
361
362 layer.add(viz::Arrow("force_" + std::to_string(i))
363 .fromTo(rtStatus.collDataVec[i].point1 * 1000.0,
364 rtStatus.collDataVec[i].point1 * 1000.0 +
365 rtStatus.collDataVec[i].direction * 50.0 *
366 rtStatus.collDataVec[i].repulsiveForce)
367 .color(simox::Color::blue()));
368
369
370 //size_t index = rtStatus.distanceIndexPairs[i].second;
371 datafields[std::to_string(i) + "_minDistance"] =
372 new Variant(rtStatus.collDataVec[i].minDistance);
373 datafields[std::to_string(i) + "_repForce"] =
374 new Variant(rtStatus.collDataVec[i].repulsiveForce);
375 datafields[std::to_string(i) + "_dampingForce"] =
376 new Variant(-1.0f * rtStatus.collDataVec[i].damping *
377 rtStatus.collDataVec[i].distanceVelocity);
378 datafields[std::to_string(i) + "_n_des(d)"] =
379 new Variant(rtStatus.collDataVec[i].desiredNSColl);
381 datafields, std::to_string(i) + "_point", rtStatus.collDataVec[i].point1);
383 datafields, std::to_string(i) + "_dir", rtStatus.collDataVec[i].direction);
384 }
385
386
387 // /// prepare test case config
388 // const float tolerance = 1e-9f;
389 // if (rtData.testConfig == 1)
390 // {
391 // if (rtStatus.evalData[0].nodeName == "ArmL8_Wri2")
392 // {
393 // // set distance
394 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_dist"] =
395 // new Variant(rtStatus.evalData[0].minDistance);
396 // // set f_rep, damping, desired NS space
397
398
399 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_repF"] =
400 // new Variant(rtStatus.evalData[0].repulsiveForce);
401 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_projMass"] =
402 // new Variant(rtStatus.evalData[0].projectedMass);
403 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_locStiffness"] =
404 // new Variant(rtStatus.evalData[0].localStiffness);
405 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_dampFactor"] =
406 // new Variant(rtStatus.evalData[0].damping);
407 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_distVel"] =
408 // new Variant(rtStatus.evalData[0].distanceVelocity);
409 // if (fabs(rtStatus.evalData[0].damping + 1.0f) < tolerance)
410 // {
411 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_dampForce"] =
412 // new Variant(0.0);
413 // }
414 // else
415 // {
416 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_dampForce"] =
417 // new Variant(-1.0 * rtStatus.evalData[0].damping *
418 // rtStatus.evalData[0].distanceVelocity);
419 // }
420
421 // datafields["ArmL8_Wri2_" + rtStatus.evalData[0].otherName + "_n_des(d)"] =
422 // new Variant(rtStatus.evalData[0].desiredNSColl);
423 // }
424 // if (rtStatus.evalData[1].nodeName == "ArmL8_Wri2")
425 // {
426 // // set distance
427 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_dist"] =
428 // new Variant(rtStatus.evalData[1].minDistance);
429 // // set f_rep, damping, desired NS space
430
431 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_repF"] =
432 // new Variant(rtStatus.evalData[1].repulsiveForce);
433 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_projMass"] =
434 // new Variant(rtStatus.evalData[1].projectedMass);
435 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_locStiffness"] =
436 // new Variant(rtStatus.evalData[1].localStiffness);
437 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_dampFactor"] =
438 // new Variant(rtStatus.evalData[1].damping);
439 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_distVel"] =
440 // new Variant(rtStatus.evalData[1].distanceVelocity);
441 // if (fabs(rtStatus.evalData[1].damping + 1.0f) < tolerance)
442 // {
443 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_dampForce"] =
444 // new Variant(0.0);
445 // }
446 // else
447 // {
448 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_dampForce"] =
449 // new Variant(-1.0 * rtStatus.evalData[1].damping *
450 // rtStatus.evalData[1].distanceVelocity);
451 // }
452
453 // datafields["ArmL8_Wri2_" + rtStatus.evalData[1].otherName + "_n_des(d)"] =
454 // new Variant(rtStatus.evalData[1].desiredNSColl);
455 // }
456 // if (rtStatus.evalData[2].nodeName == "ArmL7_Wri1")
457 // {
458 // // set distance
459 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_dist"] =
460 // new Variant(rtStatus.evalData[2].minDistance);
461 // // set f_rep, damping, desired NS space
462
463 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_repF"] =
464 // new Variant(rtStatus.evalData[2].repulsiveForce);
465
466 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_projMass"] =
467 // new Variant(rtStatus.evalData[2].projectedMass);
468 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_locStiffness"] =
469 // new Variant(rtStatus.evalData[2].localStiffness);
470 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_dampFactor"] =
471 // new Variant(rtStatus.evalData[2].damping);
472 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_distVel"] =
473 // new Variant(rtStatus.evalData[2].distanceVelocity);
474 // if (fabs(rtStatus.evalData[2].damping + 1.0f) < tolerance)
475 // {
476 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_dampForce"] =
477 // new Variant(0.0);
478 // }
479 // else
480 // {
481 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_dampForce"] =
482 // new Variant(-1.0 * rtStatus.evalData[2].damping *
483 // rtStatus.evalData[2].distanceVelocity);
484 // }
485
486
487 // datafields["ArmL7_Wri1_" + rtStatus.evalData[2].otherName + "_n_des(d)"] =
488 // new Variant(rtStatus.evalData[2].desiredNSColl);
489 // }
490 // if (rtStatus.evalData[3].nodeName == "ArmL8_Wri2")
491 // {
492 // // set distance
493 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_dist"] =
494 // new Variant(rtStatus.evalData[3].minDistance);
495 // // set f_rep, damping, desired NS space
496
497 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_repF"] =
498 // new Variant(rtStatus.evalData[3].repulsiveForce);
499
500 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_projMass"] =
501 // new Variant(rtStatus.evalData[3].projectedMass);
502 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_locStiffness"] =
503 // new Variant(rtStatus.evalData[3].localStiffness);
504 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_dampFactor"] =
505 // new Variant(rtStatus.evalData[3].damping);
506 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_distVel"] =
507 // new Variant(rtStatus.evalData[3].distanceVelocity);
508 // if (fabs(rtStatus.evalData[3].damping + 1.0f) < tolerance)
509 // {
510 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_dampForce"] =
511 // new Variant(0.0);
512 // }
513 // else
514 // {
515 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_dampForce"] =
516 // new Variant(-1.0 * rtStatus.evalData[3].damping *
517 // rtStatus.evalData[3].distanceVelocity);
518 // }
519
520
521 // datafields["ArmL8_Wri2_" + rtStatus.evalData[3].otherName + "_n_des(d)"] =
522 // new Variant(rtStatus.evalData[3].desiredNSColl);
523 // }
524
525 // if (rtStatus.evalData[4].nodeName == "ArmL8_Wri2")
526 // {
527 // // set distance
528 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_dist"] =
529 // new Variant(rtStatus.evalData[4].minDistance);
530 // // set f_rep, damping, desired NS space
531
532 // // values have been calculated
533 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_repF"] =
534 // new Variant(rtStatus.evalData[4].repulsiveForce);
535
536 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_projMass"] =
537 // new Variant(rtStatus.evalData[4].projectedMass);
538 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_locStiffness"] =
539 // new Variant(rtStatus.evalData[4].localStiffness);
540 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_dampFactor"] =
541 // new Variant(rtStatus.evalData[4].damping);
542 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_distVel"] =
543 // new Variant(rtStatus.evalData[4].distanceVelocity);
544 // if (fabs(rtStatus.evalData[4].damping + 1.0f) < tolerance)
545 // {
546 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_dampForce"] =
547 // new Variant(0.0);
548 // }
549 // else
550 // {
551 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_dampForce"] =
552 // new Variant(-1.0 * rtStatus.evalData[4].damping *
553 // rtStatus.evalData[4].distanceVelocity);
554 // }
555
556
557 // datafields["ArmL8_Wri2_" + rtStatus.evalData[4].otherName + "_n_des(d)"] =
558 // new Variant(rtStatus.evalData[4].desiredNSColl);
559 // }
560 // if (rtStatus.evalData[5].nodeName == "ArmL8_Wri2")
561 // {
562 // // set distance
563 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_dist"] =
564 // new Variant(rtStatus.evalData[5].minDistance);
565
566 // // values have been calculated
567 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_repF"] =
568 // new Variant(rtStatus.evalData[5].repulsiveForce);
569
570 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_projMass"] =
571 // new Variant(rtStatus.evalData[5].projectedMass);
572 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_locStiffness"] =
573 // new Variant(rtStatus.evalData[5].localStiffness);
574 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_dampFactor"] =
575 // new Variant(rtStatus.evalData[5].damping);
576 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_distVel"] =
577 // new Variant(rtStatus.evalData[5].distanceVelocity);
578 // if (fabs(rtStatus.evalData[5].damping + 1.0f) < tolerance)
579 // {
580 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_dampForce"] =
581 // new Variant(0.0);
582 // }
583 // else
584 // {
585 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_dampForce"] =
586 // new Variant(-1.0 * rtStatus.evalData[5].damping *
587 // rtStatus.evalData[5].distanceVelocity);
588 // }
589
590
591 // datafields["ArmL8_Wri2_" + rtStatus.evalData[5].otherName + "_n_des(d)"] =
592 // new Variant(rtStatus.evalData[5].desiredNSColl);
593 // }
594 // if (rtStatus.evalData[6].nodeName == "ArmL5_Elb1")
595 // {
596 // // set distance
597 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_dist"] =
598 // new Variant(rtStatus.evalData[6].minDistance);
599
600 // // values have been calculated
601 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_repF"] =
602 // new Variant(rtStatus.evalData[6].repulsiveForce);
603
604 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_projMass"] =
605 // new Variant(rtStatus.evalData[6].projectedMass);
606 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_locStiffness"] =
607 // new Variant(rtStatus.evalData[6].localStiffness);
608 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_dampFactor"] =
609 // new Variant(rtStatus.evalData[6].damping);
610 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_distVel"] =
611 // new Variant(rtStatus.evalData[6].distanceVelocity);
612 // if (fabs(rtStatus.evalData[6].damping + 1.0f) < tolerance)
613 // {
614 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_dampForce"] =
615 // new Variant(0.0);
616 // }
617 // else
618 // {
619 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_dampForce"] =
620 // new Variant(-1.0 * rtStatus.evalData[6].damping *
621 // rtStatus.evalData[6].distanceVelocity);
622 // }
623
624
625 // datafields["ArmL5_Elb1_" + rtStatus.evalData[6].otherName + "_n_des(d)"] =
626 // new Variant(rtStatus.evalData[6].desiredNSColl);
627 // }
628 // }
629
630 // visualize impedance force
631
632 layer.add(viz::Arrow("projImpForce")
633 .fromTo(rtStatus.globalPose.block<3, 1>(0, 3),
634 rtStatus.globalPose.block<3, 1>(0, 3) +
635 rtStatus.projForceImpedance.head(3) * 1000.0)
636 .color(simox::Color::red()));
637
638 arviz.commit(layer);
639
640
641 //double selfCollDebugTime = IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
642 //datafields["selfCollDebugTime"] = new Variant(selfCollDebugTime);
643
644 // debug value assignment torso, neck joints
645 // datafields["torsoJointValue_float"] = new Variant(rtStatus.torsoJointValuef);
646 // datafields["neck1JointValue_float"] = new Variant(rtStatus.neck1JointValuef);
647 // datafields["neck2JointValue_float"] = new Variant(rtStatus.neck2JointValuef);
648
649 // datafields["torsoJointValue_double"] = new Variant(rtStatus.torsoJointValued);
650 // datafields["neck1JointValue_double"] = new Variant(rtStatus.neck1JointValued);
651 // datafields["neck2JointValue_double"] = new Variant(rtStatus.neck2JointValued);
652
653 // common::debugEigenVec(
654 // datafields, "set_ActuatedJointValues", rtStatus.setActuatedJointValues.cast<float>());
655 // common::debugEigenVec(
656 // datafields, "get_ActuatedJointValues", rtStatus.getActuatedJointValues.cast<float>());
657
658 // double limbTime = IceUtil::Time::now().toMicroSecondsDouble() - limbTimeMeasure;
659 // datafields["limbOnPublishTime"] = new Variant(limbTime);
660
661 debugObs->setDebugChannel("CollAvoid_ImpCtrl_" + arm.nodeSetName, datafields);
662 }
663
664 void
666 const std::vector<hpp::fcl::CollisionObject>& objects,
667 const DebugObserverInterfacePrx& debugObs,
668 const std::string& layerSuffix)
669 {
670
671 viz::Layer objectLayer = arviz.layer(getName() + layerSuffix);
672 for (size_t i = 0; i < objects.size(); ++i)
673 {
674 auto object = objects.at(i);
675 auto position = object.getTranslation().cast<float>() * 1000;
676 auto rotation = object.getRotation().cast<float>();
677
678 switch (object.getNodeType())
679 {
680 case hpp::fcl::NODE_TYPE::GEOM_BOX:
681 {
682 const hpp::fcl::Box* box = std::static_pointer_cast<hpp::fcl::Box>(object.collisionGeometry()).get();
683 const viz::Box vizObject = viz::Box("box " + std::to_string(i))
684 .size(box->halfSide.cast<float>() * 1000 * 2)
685 .orientation(rotation)
686 .position(position)
687 .color(255, 0, 0, 128);
688 objectLayer.add(vizObject);
689 break;
690 }
691 case hpp::fcl::NODE_TYPE::GEOM_SPHERE:
692 {
693 const hpp::fcl::Sphere* sphere = std::static_pointer_cast<hpp::fcl::Sphere>(object.collisionGeometry()).get();
694 const viz::Sphere vizObject = viz::Sphere("sphere " + std::to_string(i))
695 .radius(static_cast<float>(sphere->radius) * 1000)
696 .orientation(rotation)
697 .position(position)
698 .color(0, 0, 255, 128);
699 objectLayer.add(vizObject);
700 break;
701 }
702 case hpp::fcl::NODE_TYPE::GEOM_CYLINDER:
703 {
704 // hpp fcl has height as z for cylinders, arviz y axis
705 const auto _rotation = rotation * Eigen::AngleAxisf(-M_PI / 2., Eigen::Vector3f::UnitX());
706 const hpp::fcl::Cylinder* cylinder = std::static_pointer_cast<hpp::fcl::Cylinder>(object.collisionGeometry()).get();
707 const viz::Cylinder vizObject = viz::Cylinder("cylinder " + std::to_string(i))
708 .height(static_cast<float>(cylinder->halfLength) * 1000 * 2)
709 .radius(static_cast<float>(cylinder->radius) * 1000)
710 .orientation(_rotation)
711 .position(position)
712 .color(0, 255, 0, 128);
713 objectLayer.add(vizObject);
714 break;
715 }
716 case hpp::fcl::NODE_TYPE::GEOM_CAPSULE: {
717 const hpp::fcl::Capsule* capsule = std::static_pointer_cast<hpp::fcl::Capsule>(object.collisionGeometry()).get();
718 Eigen::Vector3f offset;
719 offset << 0, 0, static_cast<float>(capsule->halfLength) * 1000;
720 offset = rotation * offset;
721 const viz::Sphere cap1 = viz::Sphere("capsule_cap1 " + std::to_string(i))
722 .radius(static_cast<float>(capsule->radius) * 1000)
723 .position(position + offset)
724 .orientation(rotation)
725 .color(255, 200, 0, 128);
726 const viz::Sphere cap2 = viz::Sphere("capsule_cap2 " + std::to_string(i))
727 .radius(static_cast<float>(capsule->radius) * 1000)
728 .position(position - offset)
729 .orientation(rotation)
730 .color(255, 200, 0, 128);
731 const auto _rotation = rotation * Eigen::AngleAxisf(-M_PI / 2., Eigen::Vector3f::UnitX());
732 const viz::Cylinder vizObject = viz::Cylinder("capsule_mid " + std::to_string(i))
733 .height(static_cast<float>(capsule->halfLength) * 1000 * 2)
734 .radius(static_cast<float>(capsule->radius) * 1000)
735 .color(255, 200, 0, 128)
736 .orientation(_rotation)
737 .position(position);
738 objectLayer.add(vizObject);
739 objectLayer.add(cap1);
740 objectLayer.add(cap2);
741 break;
742 }
743 case hpp::fcl::NODE_TYPE::GEOM_ELLIPSOID:
744 {
745 const hpp::fcl::Ellipsoid* ellipsoid = std::static_pointer_cast<hpp::fcl::Ellipsoid>(object.collisionGeometry()).get();
746 const viz::Ellipsoid vizObject = viz::Ellipsoid("ellipsoid " + std::to_string(i))
747 // axis lengths seem to be radii instead of axis lengths
748 .axisLengths(ellipsoid->radii.cast<float>() * 1000)
749 .orientation(rotation)
750 .position(position)
751 .color(255, 0, 200, 128);
752 objectLayer.add(vizObject);
753 break;
754 }
755 default: ;
756 }
757 }
758 arviz.commit(objectLayer);
759 }
760
761 void
763 const SensorAndControl& sc,
764 const DebugDrawerInterfacePrx& drawer,
765 const DebugObserverInterfacePrx& debugObs)
766 {
768 if (coll)
769 {
770 for (auto& pair : coll->collLimb)
771 {
772 collLimbPublish(pair.second, debugObs);
773 }
774 collObjectPublish(coll->userCollisionObjects, debugObs, "_collisionObjects");
775
776 const auto& robotObjects = coll->collisionRobot->getCollisionManager()->getObjects();
777 std::vector<hpp::fcl::CollisionObject> robotObjectsByValue;
778 for (const auto* ptr : robotObjects) {
779 robotObjectsByValue.push_back(*ptr);
780 }
781 collObjectPublish(robotObjectsByValue, debugObs, "_collisionRobot");
782 }
783 }
784
785 void
787 {
789 "rt Preactivate controller NJointTaskspaceObjectCollisionAvoidanceImpedanceController");
792 if (collReady.load())
793 {
795 coll->rtPreActivate();
796 }
797 }
798
799 void
801 {
803 if (collReady.load())
804 {
806 coll->rtPostDeactivate();
807 }
809 "post deactivate: NJointTaskspaceObjectCollisionAvoidanceImpedanceController");
810 }
811
814 const VirtualRobot::RobotPtr& robot,
815 const std::map<std::string, ConstControlDevicePtr>& controlDevices,
816 const std::map<std::string, ConstSensorDevicePtr>&)
817 {
818 using namespace armarx::WidgetDescription;
819 HBoxLayoutPtr layout = new HBoxLayout;
820
821
822 ::armarx::WidgetDescription::WidgetSeq widgets;
823
824 /// select default config
825 LabelPtr label = new Label;
826 label->text = "select a controller config";
827
828 StringComboBoxPtr cfgBox = new StringComboBox;
829 cfgBox->name = "config_box";
830 cfgBox->defaultIndex = 0;
831 cfgBox->multiSelect = false;
832
833 cfgBox->options = std::vector<std::string>{
834 "default", "default_a7_right", "default_a7_right_zero_torque"};
836
837 layout->children.emplace_back(label);
838 layout->children.emplace_back(cfgBox);
840
841 layout->children.insert(layout->children.end(), widgets.begin(), widgets.end());
842 ARMARX_INFO_S << "Layout done";
843 return layout;
844 }
845
848 const StringVariantBaseMap& values)
849 {
850 auto cfgName = values.at("config_box")->getString();
851 const armarx::PackagePath configPath(
852 "armarx_control",
853 "controller_config/NJointTaskspaceObjectCollisionAvoidanceImpedanceController/" + cfgName +
854 ".json");
855 ARMARX_INFO_S << "Loading config from " << configPath.toSystemPath();
856 ARMARX_CHECK(std::filesystem::exists(configPath.toSystemPath()));
857
858 auto cfgDTO = armarx::readFromJson<CollisionCtrlCfg>(configPath.toSystemPath());
859
861 return new ConfigurableNJointControllerConfig{cfgDTO.toAronDTO()};
862 }
863
864} // namespace armarx::control::njoint_controller::task_space
#define ARMARX_RT_LOGF_WARN(...)
#define ARMARX_RT_LOGF_INFO(...)
#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 onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
::armarx::aron::data::dto::DictPtr getConfig(const Ice::Current &iceCurrent=Ice::emptyCurrent) override
NJointTaskspaceImpedanceController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
NJointController interface.
void rtPreActivateController() override
This function is called before the controller is activated.
void limbRTUpdateStatus(ArmPtr &arm, const double deltaT)
-----------------------------— Real time cotnrol --------------------------------------—
void collObjectPublish(const std::vector< hpp::fcl::CollisionObject > &objects, const DebugObserverInterfacePrx &debugObs, const std::string &layerSuffix)
static WidgetDescription::WidgetPtr GenerateConfigDescription(const VirtualRobot::RobotPtr &, const std::map< std::string, ConstControlDevicePtr > &, const std::map< std::string, ConstSensorDevicePtr > &)
NJointTaskspaceObjectCollisionAvoidanceImpedanceController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
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
TODO make protected and use attorneys.
void updateCollisionObjects(const std::string &primitiveSourceName, const ::armarx::aron::data::dto::DictPtr &scene, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
void onPublish(const SensorAndControl &sc, const DebugDrawerInterfacePrx &drawer, const DebugObserverInterfacePrx &) override
void collLimbPublish(core::ObjectCollisionAvoidanceBase::NodeSetData &arm, const DebugObserverInterfacePrx &debugObs)
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent) override
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
The normal logging level.
Definition Logging.h:179
#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<::armarx::WidgetDescription::Widget > WidgetPtr
::IceInternal::Handle< Dict > DictPtr
void debugEigenVec(StringVariantBaseMap &datafields, const std::string &name, Eigen::VectorXf vec)
Definition utils.cpp:190
NJointControllerRegistration< NJointTaskspaceObjectCollisionAvoidanceImpedanceController > registrationControllerNJointTaskspaceObjectCollisionAvoidanceImpedanceController("NJointTaskspaceObjectCollisionAvoidanceImpedanceController")
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
AronDTO readFromJson(const std::filesystem::path &filename)
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT > >
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition algorithm.h:351
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