BulletPhysicsWorld.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2013-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package ArmarXSimulation::Simulator
19 * @author Nikolaus ( vahrenkamp at kit dot edu )
20 * @date 2014
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25#include "BulletPhysicsWorld.h"
26
27#include <algorithm>
28#include <memory>
29
30#include <VirtualRobot/CollisionDetection/CollisionChecker.h>
31#include <VirtualRobot/Nodes/ForceTorqueSensor.h>
32#include <VirtualRobot/Robot.h>
33#include <VirtualRobot/RobotFactory.h>
34
38
39#include <SimDynamics/DynamicsEngine/BulletEngine/BulletRobot.h>
40
41using namespace VirtualRobot;
42using namespace SimDynamics;
43using namespace armarx;
44
51
57
58void
63 bool floorPlane,
64 std::string floorTexture)
65{
66 ARMARX_INFO_S << "Init BulletPhysicsWorld. Creating bullet engine...";
67
68 simVisuData.robots.clear();
69 simVisuData.objects.clear();
70 simVisuData.floorTextureFile.clear();
71 simVisuData.floor = false;
72
73 simReportData.robots.clear();
74
75 contacts.clear();
76 this->maxRealTimeSimSpeed = maxRealTimeSimSpeed;
77 this->stepSizeMs = stepSizeMS;
78 this->bulletFixedTimeStepMS = bulletFixedTimeStepMS;
79 this->bulletFixedTimeStepMaxNrLoops = bulletFixedTimeStepMaxNrLoops;
80
81 dynamicsWorld = SimDynamics::DynamicsWorld::Init();
82
83 bulletEngine = std::dynamic_pointer_cast<BulletEngine>(dynamicsWorld->getEngine());
84
85 if (!bulletEngine)
86 {
88 << "Could not cast engine to BULLET engine, non-bullet engines not yet supported!";
89 throw UserException("Bullet engine missing");
90 }
91
92 bulletEngine->setMutex(engineMutex);
93
94 setupFloor(floorPlane, floorTexture);
95
96 m_clock.reset();
97}
98
99void
100BulletPhysicsWorld::actuateRobotJoints(const std::string& robotName,
101 const std::map<std::string, float>& angles,
102 const std::map<std::string, float>& velocities)
103{
104 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
105
106 ARMARX_DEBUG_S << "actuateRobotJoints: first:" << angles.begin()->first
107 << ", ang: " << angles.begin()->second << ", vel:" << velocities.begin()->second;
108 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
109 if (!dynamicsRobot)
110 {
111 ARMARX_WARNING_S << "No robot available";
112 return;
113 }
114
115 RobotPtr kinRob = dynamicsRobot->getRobot();
116
117 if (!kinRob || kinRob->getName() != robotName)
118 {
119 ARMARX_WARNING_S << "No robot available with name " << robotName;
120
121 if (kinRob)
122 {
123 ARMARX_WARNING_S << "available robot:" << kinRob->getName();
124 }
125
126 return;
127 }
128
129 bool isStatic = dynamicRobots[robotName].isStatic;
130
131 for (const auto& angle : angles)
132 {
133 // target values
134 std::string targetJointName = angle.first;
135 float targetJointPos = angle.second;
136 auto velIt = velocities.find(angle.first);
137
138 if (isStatic)
139 {
140 RobotNodePtr rn = kinRob->getRobotNode(targetJointName);
141 BulletRobot* br = dynamic_cast<BulletRobot*>(dynamicsRobot.get());
142 if (br && br->hasLink(rn))
143 {
144 kinRob->setJointValue(rn, targetJointPos);
145 BulletRobot::LinkInfo link = br->getLink(rn);
146 RobotNodePtr nodeCloneA;
147 RobotNodePtr nodeCloneB;
148
149 if (link.nodeA && link.dynNode1)
150 {
151 nodeCloneA = kinRob->getRobotNode(link.nodeA->getName());
152 link.dynNode1->setPose(nodeCloneA->getGlobalPose());
153 }
154 if (link.nodeB && link.dynNode2)
155 {
156 nodeCloneB = kinRob->getRobotNode(link.nodeB->getName());
157 link.dynNode1->setPose(nodeCloneB->getGlobalPose());
158 }
159 }
160 }
161 else
162 {
163 if (kinRob->hasRobotNode(targetJointName) &&
164 dynamicsRobot->getDynamicsRobotNode(targetJointName) && velIt != velocities.end())
165 {
166 VR_ASSERT(not kinRob->isPassive());
167 dynamicsRobot->actuateNode(dynamicsRobot->getRobot()->getRobotNode(targetJointName),
168 static_cast<double>(targetJointPos),
169 static_cast<double>(velIt->second));
170 }
171 else
172 {
173 ARMARX_WARNING_S << deactivateSpam(5, targetJointName) << "No node with name "
174 << targetJointName;
175 }
176 }
177 }
178}
179
180void
181BulletPhysicsWorld::actuateRobotJointsPos(const std::string& robotName,
182 const std::map<std::string, float>& angles)
183{
184 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
185 if (angles.size() == 0)
186 {
187 return;
188 }
189 ARMARX_DEBUG_S << "actuateRobotJointsPos: first:" << angles.begin()->first
190 << ", ang: " << angles.begin()->second;
191
192 // ARMARX_WARNING_S << "actuateRobotJointsPos: " << VAROUT(angles);
193
194 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
195 if (!dynamicsRobot)
196 {
197 ARMARX_WARNING_S << "No robot available with name " << robotName;
198 return;
199 }
200 bool isStatic = dynamicRobots[robotName].isStatic;
201
202 RobotPtr kinRob = dynamicsRobot->getRobot();
203
204 if (!kinRob || kinRob->getName() != robotName)
205 {
206 ARMARX_WARNING_S << "No robot available with name " << robotName;
207 return;
208 }
209
210 for (const auto& angle : angles)
211 {
212 // target values
213 std::string targetJointName = angle.first;
214 float targetJoint = angle.second;
215
216 if (kinRob->hasRobotNode(
217 targetJointName) /*&& dynamicsRobot->getDynamicsRobotNode(targetJointName)*/)
218 {
219 if (isStatic or kinRob->isPassive())
220 {
221 RobotNodePtr rn = kinRob->getRobotNode(targetJointName);
222 BulletRobot* br = dynamic_cast<BulletRobot*>(dynamicsRobot.get());
223 if (br && br->hasLink(rn))
224 {
225 kinRob->setJointValue(rn, targetJoint);
226 BulletRobot::LinkInfo link = br->getLink(rn);
227 RobotNodePtr nodeCloneA;
228 RobotNodePtr nodeCloneB;
229
230 if (link.nodeA && link.dynNode1)
231 {
232 nodeCloneA = kinRob->getRobotNode(link.nodeA->getName());
233 link.dynNode1->setPose(nodeCloneA->getGlobalPose());
234 }
235 if (link.nodeB && link.dynNode2)
236 {
237 nodeCloneB = kinRob->getRobotNode(link.nodeB->getName());
238 link.dynNode1->setPose(nodeCloneB->getGlobalPose());
239 }
240 }
241 }
242 else
243 {
244 VR_ASSERT(not kinRob->isPassive());
245 dynamicsRobot->actuateNode(targetJointName, static_cast<double>(targetJoint));
246 }
247 }
248 else
249 {
250 ARMARX_WARNING_S << deactivateSpam(5, targetJointName) << "No node with name "
251 << targetJointName;
252 }
253 }
254}
255
256void
257BulletPhysicsWorld::actuateRobotJointsVel(const std::string& robotName,
258 const std::map<std::string, float>& velocities)
259{
260 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
261 ARMARX_DEBUG_S << "actuateRobotJointsVel: first: vel:" << velocities.begin()->second;
262
263 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
264 if (!dynamicsRobot)
265 {
266 ARMARX_WARNING_S << "No robot available";
267 return;
268 }
269
270 RobotPtr kinRob = dynamicsRobot->getRobot();
271
272 if (!kinRob || kinRob->getName() != robotName)
273 {
274 ARMARX_WARNING_S << "No robot available with name " << robotName;
275 return;
276 }
277
278 // store velocities for static robots
279 DynamicsRobotInfo& ri = dynamicRobots[robotName];
280 if (ri.isStatic)
281 {
282 // preserve all values of velocities, and add values of robotInfo
283 std::map<std::string, float> res = velocities;
284 res.insert(ri.targetVelocities.begin(), ri.targetVelocities.end());
285 ri.targetVelocities = res;
286 }
287 else
288 {
289
290 for (const auto& velocitie : velocities)
291 {
292 // target values
293 std::string targetJointName = velocitie.first;
294 float targetJointVel = velocitie.second;
295
296 if (kinRob->hasRobotNode(targetJointName))
297 {
298 VR_ASSERT(not kinRob->isPassive());
299
300 dynamicsRobot->actuateNodeVel(targetJointName, static_cast<double>(targetJointVel));
301 }
302 else
303 {
304 ARMARX_WARNING_S << "No node with name " << targetJointName;
305 }
306 }
307 }
308}
309
310void
312 const std::map<std::string, float>& torques)
313{
314 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
315 ARMARX_DEBUG_S << "actuateRobotJointsTorque: first:" << torques.begin()->first << ","
316 << torques.begin()->second;
317
318 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
319 if (!dynamicsRobot)
320 {
321 ARMARX_WARNING_S << "No robot available";
322 return;
323 }
324
325 RobotPtr kinRob = dynamicsRobot->getRobot();
326
327 if (!kinRob || kinRob->getName() != robotName)
328 {
329 ARMARX_WARNING_S << "No robot available with name " << robotName;
330 return;
331 }
332
333 for (const auto& torque : torques)
334 {
335 // target values
336 std::string targetJointName = torque.first;
337 float targetJointTorque = torque.second;
338
339 if (kinRob->hasRobotNode(targetJointName))
340 {
341 VR_ASSERT(not kinRob->isPassive());
342
343 dynamicsRobot->actuateNodeTorque(targetJointName,
344 static_cast<double>(targetJointTorque));
345 }
346 else
347 {
348 ARMARX_WARNING_S << "No node with name " << targetJointName;
349 }
350 }
351}
352
353void
354BulletPhysicsWorld::setRobotPose(const std::string& robotName, const Eigen::Matrix4f& globalPose)
355{
356 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
357 ARMARX_DEBUG_S << "setRobotPose:" << globalPose(0, 3) << "," << globalPose(1, 3) << ", "
358 << globalPose(2, 3);
359
360 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
361 if (!dynamicsRobot)
362 {
363 ARMARX_WARNING_S << "No robot available";
364 return;
365 }
366
367 RobotPtr kinRob = dynamicsRobot->getRobot();
368
369 if (!kinRob || kinRob->getName() != robotName)
370 {
371 ARMARX_WARNING_S << "No robot available with name " << robotName;
372 return;
373 }
374
375 Eigen::Matrix4f gp =
376 globalPose; // just a hack to convert const to non-const (fixed in newest simox version)
377 dynamicsRobot->setGlobalPose(gp);
378}
379
380void
381BulletPhysicsWorld::applyForceRobotNode(const std::string& robotName,
382 const std::string& robotNodeName,
383 const Eigen::Vector3f& force)
384{
385 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
386 ARMARX_DEBUG_S << "ApplyForce";
387
388 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
389 if (!dynamicsRobot)
390 {
391 ARMARX_WARNING_S << "No robot available";
392 return;
393 }
394
395 RobotPtr kinRob = dynamicsRobot->getRobot();
396
397 if (!kinRob || kinRob->getName() != robotName)
398 {
399 ARMARX_WARNING_S << "No robot available with name " << robotName;
400 return;
401 }
402
403 RobotNodePtr rn = kinRob->getRobotNode(robotNodeName);
404
405 if (!rn)
406 {
407 ARMARX_WARNING_S << "No robotnode available with name " << robotNodeName;
408 return;
409 }
410
411 dynamicsRobot->getDynamicsRobotNode(rn)->applyForce(force);
412}
413
414void
415BulletPhysicsWorld::applyTorqueRobotNode(const std::string& robotName,
416 const std::string& robotNodeName,
417 const Eigen::Vector3f& torque)
418{
419 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
420 ARMARX_DEBUG_S << "ApplyTorque";
421
422 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
423
424 if (!dynamicsRobot)
425 {
426 ARMARX_WARNING_S << "No robot available with name " << robotName;
427 return;
428 }
429
430 RobotPtr kinRob = dynamicsRobot->getRobot();
431
432 if (!kinRob || kinRob->getName() != robotName)
433 {
434 ARMARX_WARNING_S << "No robot available with name " << robotName;
435 return;
436 }
437
438 RobotNodePtr rn = kinRob->getRobotNode(robotNodeName);
439
440 if (!rn)
441 {
442 ARMARX_WARNING_S << "No robotnode available with name " << robotNodeName;
443 return;
444 }
445
446 dynamicsRobot->getDynamicsRobotNode(rn)->applyTorque(torque);
447}
448
449void
450BulletPhysicsWorld::applyForceObject(const std::string& objectName, const Eigen::Vector3f& force)
451{
452 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
453 SimDynamics::DynamicsObjectPtr o = getObject(objectName);
454
455 if (!o)
456 {
457 ARMARX_WARNING_S << "No object found with name " << objectName;
458 return;
459 }
460
461 o->applyForce(force);
462}
463
464void
465BulletPhysicsWorld::applyTorqueObject(const std::string& objectName, const Eigen::Vector3f& torque)
466{
467 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
468 SimDynamics::DynamicsObjectPtr o = getObject(objectName);
469
470 if (!o)
471 {
472 ARMARX_WARNING_S << "No object found with name " << objectName;
473 return;
474 }
475
476 o->applyTorque(torque);
477}
478
479SimDynamics::DynamicsObjectPtr
480BulletPhysicsWorld::getObject(const std::string& objectName)
481{
482 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
483 SimDynamics::DynamicsObjectPtr o;
484 std::vector<SimDynamics::DynamicsObjectPtr>::const_iterator it;
485
486 for (it = dynamicsObjects.begin(); it != dynamicsObjects.end(); it++)
487 {
488 if ((*it)->getName() == objectName)
489 {
490 o = *it;
491 break;
492 }
493 }
494
495 return o;
496}
497
498bool
499BulletPhysicsWorld::hasObject(const std::string& instanceName)
500{
501 return getObject(instanceName).get();
502}
503
504void
505BulletPhysicsWorld::setObjectPose(const std::string& objectName, const Eigen::Matrix4f& globalPose)
506{
507 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
508 SimDynamics::DynamicsObjectPtr o = getObject(objectName);
509
510 if (!o)
511 {
512 ARMARX_WARNING_S << "No object found with name " << objectName;
513 return;
514 }
515
516 o->setPose(globalPose);
517}
518
519void
520BulletPhysicsWorld::activateObject(const std::string& objectName)
521{
522 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
523 SimDynamics::DynamicsObjectPtr o = getObject(objectName);
524
525 if (!o)
526 {
527 ARMARX_WARNING_S << "No object found with name " << objectName;
528 return;
529 }
530
531 // need newest simox version for this (2.3.48)
532 //o->activate();
533
534 // this works for earlier versions but activates all objects
535 bulletEngine->activateAllObjects(); // avoid sleeping objects
536}
537
538float
539BulletPhysicsWorld::getRobotMass(const std::string& robotName)
540{
541 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
542
543 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
544 if (!dynamicsRobot)
545 {
546 ARMARX_WARNING_S << "No robot available";
547 return 0;
548 }
549
550 RobotPtr kinRob = dynamicsRobot->getRobot();
551
552 if (!kinRob || kinRob->getName() != robotName)
553 {
554 ARMARX_WARNING_S << "No robot available with name " << robotName;
555 return 0;
556 }
557
558 return kinRob->getMass();
559}
560
561std::map<std::string, float>
562BulletPhysicsWorld::getRobotJointAngles(const std::string& robotName)
563{
564 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
565 std::map<std::string, float> res;
566
567 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
568 if (!dynamicsRobot)
569 {
570 ARMARX_WARNING_S << "No robot available";
571 return res;
572 }
573
574 RobotPtr kinRob = dynamicsRobot->getRobot();
575
576 if (!kinRob || kinRob->getName() != robotName)
577 {
578 ARMARX_WARNING_S << "No robot available with name " << robotName;
579 return res;
580 }
581
582 std::vector<RobotNodePtr> rn = kinRob->getRobotNodes();
583
584 for (auto& i : rn)
585 {
586 if (i->isJoint())
587 {
588 res[i->getName()] = i->getJointValue();
589 }
590 }
591
592 ARMARX_DEBUG_S << "getRobotJointAngles:" << res.begin()->second;
593
594 return res;
595}
596
597float
598BulletPhysicsWorld::getRobotJointAngle(const std::string& robotName, const std::string& nodeName)
599{
600 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
601
602 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
603 if (!dynamicsRobot)
604 {
605 ARMARX_WARNING_S << "No robot available";
606 return 0;
607 }
608
609 RobotPtr kinRob = dynamicsRobot->getRobot();
610
611 if (!kinRob || kinRob->getName() != robotName)
612 {
613 ARMARX_WARNING_S << "No robot available with name " << robotName;
614 return 0;
615 }
616
617 if (!kinRob->hasRobotNode(nodeName))
618 {
619 ARMARX_WARNING_S << "No robotNode available with name " << nodeName;
620 return 0;
621 }
622
623 float res = kinRob->getRobotNode(nodeName)->getJointValue();
624 ARMARX_DEBUG_S << "getRobotJointAngle:" << res;
625 return res;
626}
627
628std::map<std::string, float>
630{
631 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
632 std::map<std::string, float> res;
633
634 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
635 if (!dynamicsRobot)
636 {
637 ARMARX_WARNING_S << "No robot available";
638 return res;
639 }
640
641 RobotPtr kinRob = dynamicsRobot->getRobot();
642
643 if (!kinRob || kinRob->getName() != robotName)
644 {
645 ARMARX_WARNING_S << "No robot available with name " << robotName;
646 return res;
647 }
648
649 std::vector<RobotNodePtr> rn = kinRob->getRobotNodes();
650
651 for (auto& i : rn)
652 {
653 if (i->isJoint())
654 {
655 float vel = dynamicsRobot->getJointSpeed(i);
656 res[i->getName()] = vel;
657 }
658 }
659
660 ARMARX_DEBUG_S << "getRobotJointVelocities:" << res.begin()->second;
661 return res;
662}
663
664float
665BulletPhysicsWorld::getRobotJointVelocity(const std::string& robotName, const std::string& nodeName)
666{
667 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
668
669 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
670 if (!dynamicsRobot)
671 {
672 ARMARX_WARNING_S << "No robot available";
673 return 0;
674 }
675
676 RobotPtr kinRob = dynamicsRobot->getRobot();
677
678 if (!kinRob || kinRob->getName() != robotName)
679 {
680 ARMARX_WARNING_S << "No robot available with name " << robotName;
681 return 0;
682 }
683
684 if (!kinRob->hasRobotNode(nodeName))
685 {
686 ARMARX_WARNING_S << "No robotNode available with name " << nodeName;
687 return 0;
688 }
689
690 double res = dynamicsRobot->getJointSpeed(kinRob->getRobotNode(nodeName));
691 ARMARX_DEBUG_S << "getRobotJointVelocity:" << res;
692 return static_cast<float>(res);
693}
694
695std::map<std::string, float>
696BulletPhysicsWorld::getRobotJointTorques(const std::string& robotName)
697{
698 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
699 std::map<std::string, float> res;
700
701 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
702 if (!dynamicsRobot)
703 {
704 ARMARX_WARNING_S << "No robot available";
705 return res;
706 }
707
708 VirtualRobot::RobotPtr kinRob = dynamicsRobot->getRobot();
709
710 if (!kinRob || kinRob->getName() != robotName)
711 {
712 ARMARX_WARNING_S << "No robot available with name " << robotName;
713 return res;
714 }
715
716 SimDynamics::BulletRobot* br = dynamic_cast<BulletRobot*>(dynamicsRobot.get());
717 if (!br)
718 {
719 ARMARX_WARNING_S << "No bullet robot available with name " << robotName;
720 return res;
721 }
722 std::vector<RobotNodePtr> rn = kinRob->getRobotNodes();
723
724 for (auto& i : rn)
725 {
726 if (i->isJoint() && br)
727 {
728 if (dynamicsRobot->isNodeActuated(i))
729 {
730 res[i->getName()] = br->getJointTorque(i);
731 }
732 }
733 }
734 return res;
735}
736
737ForceTorqueDataSeq
739{
740 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
741 DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
742 RobotPtr virtualRobot = getRobot(robotName);
743 if (!dynamicsRobot || !virtualRobot)
744 {
745 static bool printed = false;
746 if (!printed)
747 {
748 ARMARX_WARNING_S << "No robot available with name " << robotName;
749 printed = true;
750 }
751 }
752 const auto ftsensors = virtualRobot->getSensors<ForceTorqueSensor>();
753 ForceTorqueDataSeq result;
754 result.reserve(ftsensors.size());
755 for (const VirtualRobot::ForceTorqueSensorPtr& sensor : ftsensors)
756 {
757 ForceTorqueData data;
758 Eigen::Vector3f force = sensor->getForce();
759 Eigen::Vector3f torque = sensor->getTorque();
760 data.nodeName = sensor->getRobotNode()->getName();
761 data.sensorName = sensor->getName();
762
763 if (!robotName.empty() && !data.nodeName.empty())
764 {
765 RobotNodePtr rn = dynamicsRobot->getRobot()->getRobotNode(data.nodeName);
766 Eigen::Vector3f forceGlobal = force;
767 Eigen::Vector3f torqueGlobal = torque;
768 if (rn)
769 {
770 Eigen::Matrix3f rotMat = rn->getGlobalPose().block(0, 0, 3, 3);
771 force = rotMat.inverse() * forceGlobal;
772 torque = rotMat.inverse() * torqueGlobal;
773 }
774 }
775 data.force = new Vector3{force};
776 data.torque = new Vector3{torque};
777
778 result.emplace_back(std::move(data));
779 }
780 return result;
781}
782
783float
784BulletPhysicsWorld::getRobotJointLimitLo(const std::string& robotName, const std::string& nodeName)
785{
786 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
787
788 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
789 if (!dynamicsRobot)
790 {
791 ARMARX_WARNING_S << "No robot available";
792 return 0;
793 }
794
795 RobotPtr kinRob = dynamicsRobot->getRobot();
796
797 if (!kinRob || kinRob->getName() != robotName)
798 {
799 ARMARX_WARNING_S << "No robot available with name " << robotName;
800 return 0;
801 }
802
803 if (!kinRob->hasRobotNode(nodeName))
804 {
805 ARMARX_WARNING_S << "No robotNode available with name " << nodeName;
806 return 0;
807 }
808
809 return kinRob->getRobotNode(nodeName)->getJointLimitLo();
810}
811
812float
813BulletPhysicsWorld::getRobotJointLimitHi(const std::string& robotName, const std::string& nodeName)
814{
815 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
816
817 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
818 if (!dynamicsRobot)
819 {
820 ARMARX_WARNING_S << "No robot available";
821 return 0;
822 }
823
824 RobotPtr kinRob = dynamicsRobot->getRobot();
825
826 if (!kinRob || kinRob->getName() != robotName)
827 {
828 ARMARX_WARNING_S << "No robot available with name " << robotName;
829 return 0;
830 }
831
832 if (!kinRob->hasRobotNode(nodeName))
833 {
834 ARMARX_WARNING_S << "No robotNode available with name " << nodeName;
835 return 0;
836 }
837
838 return kinRob->getRobotNode(nodeName)->getJointLimitHi();
839}
840
841Eigen::Matrix4f
842BulletPhysicsWorld::getRobotPose(const std::string& robotName)
843{
844 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
845 ARMARX_DEBUG_S << "get robot pose";
846
847 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
848 if (!dynamicsRobot)
849 {
850 ARMARX_WARNING_S << "No robot available";
851 return Eigen::Matrix4f::Identity();
852 }
853
854 RobotPtr kinRob = dynamicsRobot->getRobot();
855
856 if (!kinRob || kinRob->getName() != robotName)
857 {
858 ARMARX_WARNING_S << "No robot available with name " << robotName;
859
860 if (kinRob)
861 {
862 ARMARX_WARNING_S << "available robot:" << kinRob->getName();
863 }
864
865 return Eigen::Matrix4f::Identity();
866 }
867
868 return kinRob->getGlobalPose();
869}
870
871float
872BulletPhysicsWorld::getRobotMaxTorque(const std::string& robotName, const std::string& nodeName)
873{
874 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
875 ARMARX_DEBUG_S << "getRobotMaxTorque";
876
877 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
878 if (!dynamicsRobot)
879 {
880 ARMARX_WARNING_S << "Robot '" << robotName << "' does not exist";
881 return 0.0f;
882 }
883
884 RobotPtr kinRob = dynamicsRobot->getRobot();
885
886 if (!kinRob || kinRob->getName() != robotName)
887 {
888 ARMARX_WARNING_S << "No robot available with name " << robotName;
889
890 if (kinRob)
891 {
892 ARMARX_WARNING_S << "available robot:" << kinRob->getName();
893 }
894
895 return 0.0f;
896 }
897
898 if (!kinRob->hasRobotNode(nodeName))
899 {
900 ARMARX_WARNING_S << "Robot node '" << nodeName << "' does not exist";
901 return 0.0f;
902 }
903
904 return kinRob->getRobotNode(nodeName)->getMaxTorque();
905}
906
907void
908BulletPhysicsWorld::setRobotMaxTorque(const std::string& robotName,
909 const std::string& nodeName,
910 float maxTorque)
911{
912 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
913 ARMARX_DEBUG_S << "setRobotMaxTorque";
914
915 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
916 if (!dynamicsRobot)
917 {
918 ARMARX_WARNING_S << "Robot '" << robotName << "' does not exist";
919 return;
920 }
921
922 RobotPtr kinRob = dynamicsRobot->getRobot();
923
924 if (!kinRob || kinRob->getName() != robotName)
925 {
926 ARMARX_WARNING_S << "No robot available with name " << robotName;
927
928 if (kinRob)
929 {
930 ARMARX_WARNING_S << "available robot:" << kinRob->getName();
931 }
932
933 return;
934 }
935
936 if (!kinRob->hasRobotNode(nodeName))
937 {
938 ARMARX_WARNING_S << "Robot node '" << nodeName << "' does not exist";
939 return;
940 }
941
942 kinRob->getRobotNode(nodeName)->setMaxTorque(maxTorque);
943}
944
945Eigen::Matrix4f
946BulletPhysicsWorld::getRobotNodePose(const std::string& robotName, const std::string& robotNodeName)
947{
948 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
949 ARMARX_DEBUG_S << "get robot node pose";
950
951 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
952 if (!dynamicsRobot)
953 {
954 ARMARX_WARNING_S << "No robot available with name '" << robotName << "'";
955 return Eigen::Matrix4f::Identity();
956 }
957
958 RobotPtr kinRob = dynamicsRobot->getRobot();
959
960 if (!kinRob || kinRob->getName() != robotName)
961 {
962 ARMARX_WARNING_S << "No robot available with name " << robotName;
963 return Eigen::Matrix4f::Identity();
964 }
965
966 if (!kinRob->hasRobotNode(robotNodeName))
967 {
968 ARMARX_WARNING_S << "No robotNode available with name " << robotNodeName;
969 return Eigen::Matrix4f::Identity();
970 }
971
972 return kinRob->getRobotNode(robotNodeName)->getGlobalPose();
973}
974
975Eigen::Vector3f
977 const std::string& nodeName)
978{
979 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
980 ARMARX_DEBUG_S << "get robot linear velocity";
981
982 DynamicsObjectPtr dynamicsRobotNode = this->getFirstDynamicsObject(robotName, nodeName);
983
984 if (!dynamicsRobotNode)
985 {
986 return Eigen::Vector3f::Identity();
987 }
988 return dynamicsRobotNode->getLinearVelocity();
989}
990
991SimDynamics::DynamicsObjectPtr
993 const std::string& nodeName)
994{
995 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
996 if (!dynamicsRobot)
997 {
998 Ice::StringSeq robots;
999 for (auto& elem : getRobots())
1000 {
1001 robots.push_back(elem.first);
1002 }
1003
1004 ARMARX_WARNING_S << deactivateSpam(1) << "No robot available with name '" << robotName
1005 << "' - available robots: " << robots;
1006
1007 return {};
1008 }
1009
1010 RobotPtr kinRob = dynamicsRobot->getRobot();
1011
1012 if (!kinRob || kinRob->getName() != robotName)
1013 {
1014 ARMARX_WARNING_S << "No robot available with name " << robotName;
1015 return {};
1016 }
1017
1018 if (!kinRob->hasRobotNode(nodeName))
1019 {
1020 ARMARX_WARNING_S << "No robotNode available with name " << nodeName;
1021 return {};
1022 }
1023
1024
1025 RobotNodePtr robotNode = kinRob->getRobotNode(nodeName);
1026 DynamicsObjectPtr dynamicsRobotNode = dynamicsRobot->getDynamicsRobotNode(robotNode);
1027 // search first parent with dynamic object
1028
1029 while (!dynamicsRobotNode)
1030 {
1031 robotNode = std::dynamic_pointer_cast<RobotNode>(robotNode->getParent());
1032 if (!robotNode)
1033 {
1034 ARMARX_WARNING_S << "unable to get parent robot node";
1035 return {};
1036 }
1037 dynamicsRobotNode = dynamicsRobot->getDynamicsRobotNode(robotNode);
1038 }
1039
1040 return dynamicsRobotNode;
1041}
1042
1043Eigen::Vector3f
1045 const std::string& nodeName)
1046{
1047 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1048 ARMARX_DEBUG_S << "get robot angular vel";
1049
1050 DynamicsObjectPtr dynamicsRobotNode = this->getFirstDynamicsObject(robotName, nodeName);
1051
1052 if (!dynamicsRobotNode)
1053 {
1054 return Eigen::Vector3f::Identity();
1055 }
1056
1057 return dynamicsRobotNode->getAngularVelocity();
1058}
1059
1060void
1062 const std::string& robotNodeName,
1063 const Eigen::Vector3f& vel)
1064{
1065 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1066 ARMARX_DEBUG_S << "set robot lin vel";
1067
1068 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
1069 if (!dynamicsRobot)
1070 {
1071 ARMARX_WARNING_S << "No robot available";
1072 return;
1073 }
1074
1075 RobotPtr kinRob = dynamicsRobot->getRobot();
1076
1077 if (!kinRob || kinRob->getName() != robotName)
1078 {
1079 ARMARX_WARNING_S << "No robot available with name " << robotName;
1080 return;
1081 }
1082
1083 if (!kinRob->hasRobotNode(robotNodeName))
1084 {
1085 ARMARX_WARNING_S << "No robotNode available with name " << robotNodeName;
1086 return;
1087 }
1088
1089 dynamicsRobot->getDynamicsRobotNode(kinRob->getRobotNode(robotNodeName))
1090 ->setLinearVelocity(vel);
1091 ARMARX_DEBUG_S << "set robot lin vel end";
1092}
1093
1094void
1096 const std::string& robotNodeName,
1097 const Eigen::Vector3f& vel)
1098{
1099 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1100 ARMARX_DEBUG_S << "set robot ang vel";
1101
1102 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
1103 if (!dynamicsRobot)
1104 {
1105 ARMARX_WARNING_S << "No robot available";
1106 return;
1107 }
1108
1109 RobotPtr kinRob = dynamicsRobot->getRobot();
1110
1111 if (!kinRob || kinRob->getName() != robotName)
1112 {
1113 ARMARX_WARNING_S << "No robot available with name " << robotName;
1114 return;
1115 }
1116
1117 if (!kinRob->hasRobotNode(robotNodeName))
1118 {
1119 ARMARX_WARNING_S << "No robotNode available with name " << robotNodeName;
1120 return;
1121 }
1122
1123 dynamicsRobot->getDynamicsRobotNode(kinRob->getRobotNode(robotNodeName))
1124 ->setAngularVelocity(vel);
1125 ARMARX_DEBUG_S << "set robot ang vel end";
1126}
1127
1128void
1130 const std::string& robotNodeName,
1131 const Eigen::Vector3f& vel)
1132{
1133 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1134 ARMARX_DEBUG_S << "set robot lin vel";
1135
1136 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
1137 if (!dynamicsRobot)
1138 {
1139 ARMARX_WARNING_S << "No robot available";
1140 return;
1141 }
1142
1143 RobotPtr kinRob = dynamicsRobot->getRobot();
1144
1145 if (!kinRob || kinRob->getName() != robotName)
1146 {
1147 ARMARX_WARNING_S << "No robot available with name '" << robotName << "'";
1148 return;
1149 }
1150
1151 if (!kinRob->hasRobotNode(robotNodeName))
1152 {
1153 ARMARX_WARNING_S << "No robotNode available with name '" << robotNodeName << "'";
1154 return;
1155 }
1156
1157 if (!dynamicsRobot->hasDynamicsRobotNode(kinRob->getRobotNode(robotNodeName)))
1158 {
1159 ARMARX_WARNING_S << "No dynamic robotNode available with name '" << robotNodeName << "'";
1160 return;
1161 }
1162
1163 Eigen::Matrix4f newPose;
1164 newPose.setIdentity();
1165 newPose.block<3, 1>(0, 3) = vel;
1166 auto globalPose = dynamicsRobot->getRobot()->getGlobalPose();
1167 globalPose(0, 3) = 0;
1168 globalPose(1, 3) = 0;
1169 globalPose(2, 3) = 0;
1170 auto globalNewPose = globalPose * newPose;
1171 dynamicsRobot->getDynamicsRobotNode(kinRob->getRobotNode(robotNodeName))
1172 ->setLinearVelocity(globalNewPose.block<3, 1>(0, 3));
1173 ARMARX_DEBUG_S << "set robot lin vel end";
1174}
1175
1176void
1178 const std::string& robotNodeName,
1179 const Eigen::Vector3f& vel)
1180{
1181 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1182 ARMARX_DEBUG_S << "set robot ang vel";
1183
1184 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
1185 if (!dynamicsRobot)
1186 {
1187 ARMARX_WARNING_S << "No robot available";
1188 return;
1189 }
1190
1191 RobotPtr kinRob = dynamicsRobot->getRobot();
1192
1193 if (!kinRob || kinRob->getName() != robotName)
1194 {
1195 ARMARX_WARNING_S << "No robot available with name '" << robotName << "'";
1196 return;
1197 }
1198
1199 if (!kinRob->hasRobotNode(robotNodeName))
1200 {
1201 ARMARX_WARNING_S << "No robotNode available with name '" << robotNodeName << "'";
1202 return;
1203 }
1204
1205 if (!dynamicsRobot->hasDynamicsRobotNode(kinRob->getRobotNode(robotNodeName)))
1206 {
1207 ARMARX_WARNING_S << "No dynamic robotNode available with name '" << robotNodeName << "'";
1208 return;
1209 }
1210
1211 Eigen::Matrix4f newPose;
1212 newPose.setIdentity();
1213 newPose.block<3, 1>(0, 3) = vel;
1214 auto globalPose = dynamicsRobot->getRobot()->getGlobalPose();
1215 globalPose(0, 3) = 0;
1216 globalPose(1, 3) = 0;
1217 globalPose(2, 3) = 0;
1218 auto globalNewPose = globalPose * newPose;
1219
1220 RobotNodePtr robotNode = kinRob->getRobotNode(robotNodeName);
1221 DynamicsObjectPtr dynamicsRobotNode = dynamicsRobot->getDynamicsRobotNode(robotNode);
1222 dynamicsRobotNode->setAngularVelocity(globalNewPose.block<3, 1>(0, 3));
1223}
1224
1225bool
1226BulletPhysicsWorld::hasRobot(const std::string& robotName)
1227{
1228 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1229
1230 std::map<std::string, DynamicsRobotInfo>::iterator it = dynamicRobots.begin();
1231 while (it != dynamicRobots.end())
1232 {
1233 if (it->first == robotName)
1234 {
1235 return true;
1236 }
1237 it++;
1238 }
1239
1240 return false;
1241}
1242
1243bool
1244BulletPhysicsWorld::hasRobotNode(const std::string& robotName, const std::string& robotNodeName)
1245{
1246 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1247
1248 SimDynamics::DynamicsRobotPtr dynRob = getDynamicRobot(robotName);
1249 if (!dynRob)
1250 {
1251 return false;
1252 }
1253
1254 return (dynRob->getRobot()->hasRobotNode(robotNodeName));
1255}
1256
1258BulletPhysicsWorld::getRobot(const std::string& robotName)
1259{
1260 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1261 SimDynamics::DynamicsRobotPtr r = getDynamicRobot(robotName);
1262 if (!r)
1263 {
1264 return VirtualRobot::RobotPtr();
1265 }
1266
1267 return r->getRobot();
1268}
1269
1270std::map<std::string, RobotPtr>
1272{
1273 std::map<std::string, RobotPtr> result;
1274 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1275 for (auto& elem : dynamicRobots)
1276 {
1277 const DynamicsRobotInfo& info = elem.second;
1278 result[elem.first] = (info.robot);
1279 }
1280 return result;
1281}
1282
1283SimDynamics::DynamicsRobotPtr
1284BulletPhysicsWorld::getDynamicRobot(const std::string& robotName)
1285{
1286 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1287
1288 if (!hasRobot(robotName))
1289 {
1290 return SimDynamics::DynamicsRobotPtr();
1291 }
1292
1293 return dynamicRobots[robotName].dynamicsRobot;
1294}
1295
1296SimDynamics::DynamicsObjectPtr
1297BulletPhysicsWorld::getDynamicsObject(const std::string& objectName)
1298{
1299 SimDynamics::DynamicsObjectPtr o;
1300 std::vector<SimDynamics::DynamicsObjectPtr>::const_iterator it;
1301
1302 for (it = dynamicsObjects.begin(); it != dynamicsObjects.end(); it++)
1303 {
1304 if ((*it)->getName() == objectName)
1305 {
1306 o = *it;
1307 break;
1308 }
1309 }
1310
1311 return o;
1312}
1313
1314Eigen::Matrix4f
1315BulletPhysicsWorld::getObjectPose(const std::string& objectName)
1316{
1317 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1318 ARMARX_DEBUG_S << "get object pose";
1319 SimDynamics::DynamicsObjectPtr o = getDynamicsObject(objectName);
1320
1321 if (!o)
1322 {
1323 ARMARX_WARNING_S << "No object found with name " << objectName;
1324 return Eigen::Matrix4f::Identity();
1325 }
1326
1327 return o->getSceneObject()->getGlobalPose();
1328}
1329
1330bool
1331BulletPhysicsWorld::objectReleasedEngine(const std::string& robotName,
1332 const std::string& robotNodeName,
1333 const std::string& objectName)
1334{
1335 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1336 ARMARX_INFO_S << "Object released, robot " << robotName << ", node:" << robotNodeName
1337 << ", object:" << objectName;
1338 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
1339 if (!dynamicsRobot)
1340 {
1341 ARMARX_WARNING_S << "No robot available with name " << robotName;
1342 return false;
1343 }
1344 RobotPtr kinRob = dynamicsRobot->getRobot();
1345
1346 if (!kinRob || kinRob->getName() != robotName)
1347 {
1348 ARMARX_WARNING_S << "No robot available with name " << robotName;
1349 return false;
1350 }
1351
1352 if (!kinRob->hasRobotNode(robotNodeName))
1353 {
1354 ARMARX_WARNING_S << "No robotNode available with name " << robotNodeName;
1355 return false;
1356 }
1357
1358 SimDynamics::DynamicsObjectPtr o = getObject(objectName);
1359
1360 if (!o)
1361 {
1362 ARMARX_WARNING_S << "No object found with name " << objectName;
1363 return false;
1364 }
1365
1366 bool res = dynamicsWorld->getEngine()->detachObjectFromRobot(robotName, o);
1367
1368 return res;
1369}
1370
1371bool
1372BulletPhysicsWorld::objectGraspedEngine(const std::string& robotName,
1373 const std::string& robotNodeName,
1374 const std::string& objectName,
1375 Eigen::Matrix4f& storeLocalTransform)
1376{
1377 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1378 ARMARX_INFO_S << "Object grasped, robot " << robotName << ", node:" << robotNodeName
1379 << ", object:" << objectName;
1380
1381 // check if object is already grasped
1382 for (const auto& ao : attachedObjects)
1383 {
1384 if (ao.robotName == robotName && ao.robotNodeName == robotNodeName &&
1385 ao.objectName == objectName)
1386 {
1387 ARMARX_INFO_S << "Object already attached, skipping...";
1388 return false;
1389 }
1390 }
1391 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
1392 RobotPtr kinRob = dynamicsRobot->getRobot();
1393
1394 if (!kinRob || kinRob->getName() != robotName)
1395 {
1396 ARMARX_WARNING_S << "No robot available with name " << robotName;
1397 return false;
1398 }
1399
1400 if (!kinRob->hasRobotNode(robotNodeName))
1401 {
1402 ARMARX_WARNING_S << "No robotNode available with name " << robotNodeName;
1403 return false;
1404 }
1405
1406 RobotNodePtr rn = kinRob->getRobotNode(robotNodeName);
1407
1408
1409 SimDynamics::DynamicsObjectPtr o = getObject(objectName);
1410
1411 if (!o)
1412 {
1413 ARMARX_WARNING_S << "No object found with name " << objectName;
1414 return false;
1415 }
1416
1417 bool res = dynamicsWorld->getEngine()->attachObjectToRobot(robotName, robotNodeName, o);
1418 storeLocalTransform = rn->toLocalCoordinateSystem(o->getSceneObject()->getGlobalPose());
1419 return res;
1420}
1421
1422SceneObjectPtr
1424{
1425 if (!dynamicsWorld || !dynamicsWorld->getEngine()->getFloor())
1426 {
1427 return SceneObjectPtr();
1428 }
1429 return dynamicsWorld->getEngine()->getFloor()->getSceneObject();
1430}
1431
1432bool
1433BulletPhysicsWorld::removeRobotEngine(const std::string& robotName)
1434{
1435 // lock engine and data
1436 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1437
1438 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
1439 if (!dynamicsWorld || !dynamicsRobot)
1440 {
1441 return false;
1442 }
1443
1444 ARMARX_DEBUG_S << "Removing robot " << robotName;
1445
1446
1447 //access engine
1448 {
1449 if (robotName != dynamicsRobot->getRobot()->getName())
1450 {
1451 ARMARX_WARNING_S << "Robot names differ...";
1452 }
1453
1454 dynamicsWorld->removeRobot(dynamicsRobot);
1455 dynamicRobots.erase(robotName);
1456 }
1457
1458 return true;
1459}
1460
1461bool
1463 double pid_p,
1464 double pid_i,
1465 double pid_d,
1466 const std::string& filename,
1467 bool staticRobot,
1468 bool selfCollisions)
1469{
1470 ARMARX_VERBOSE_S << "Adding robot " << robot->getName() << ", file: " << filename;
1471
1472 // lock engine and data
1473 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1474
1475 //access engine
1476 ARMARX_DEBUG_S << "add robot";
1477
1478 if (!dynamicsWorld)
1479 {
1480 ARMARX_ERROR_S << "No physics world!";
1481 return false;
1482 }
1483
1484 if (hasRobot(robot->getName()))
1485 {
1486 ARMARX_ERROR_S << "More than one robot with identical name is currently not supported!";
1487 return false;
1488 }
1489
1490 DynamicsRobotInfo robInfo;
1491 if (staticRobot)
1492 {
1493 ARMARX_INFO_S << "Building static robot...";
1494 std::vector<RobotNodePtr> nodes = robot->getRobotNodes();
1495 for (auto n : nodes)
1496 {
1497 n->setSimulationType(SceneObject::Physics::eKinematic);
1498 }
1499 }
1500
1501 SimDynamics::DynamicsRobotPtr dynamicsRobot;
1502 try
1503 {
1504 dynamicsRobot = dynamicsWorld->CreateDynamicsRobot(robot);
1505 ARMARX_DEBUG_S << "add dynamicsRobot" << dynamicsRobot->getName();
1506
1507 auto& controllers = dynamicsRobot->getControllers();
1508 std::vector<RobotNodePtr> nodes = robot->getRobotNodes();
1509
1510 if (not robot->isPassive())
1511 {
1512 ARMARX_INFO_S << "Configuring controllers for robot " << dynamicsRobot->getName();
1513
1514 for (auto node : nodes)
1515 {
1516 if (node->isRotationalJoint())
1517 {
1518 if (controllers.find(node) == controllers.end())
1519 {
1520 controllers[node] = VelocityMotorController(
1521 static_cast<double>(node->getMaxVelocity()),
1522 static_cast<double>(node->getMaxAcceleration()));
1523 }
1524 controllers[node].reset(pid_p, pid_i, pid_d);
1525 }
1526 }
1527 }
1528
1529 ARMARX_INFO_S << "The robot " << dynamicsRobot->getName() << " has " << controllers.size()
1530 << " controllers";
1531
1532 if (not selfCollisions)
1533 {
1534 dynamicsRobot->enableSelfCollisions(
1535 false); // do not pass the value selfCollisions in here, because it would reset the specifically set ingored-collisions.
1536 }
1537
1538 dynamicsWorld->addRobot(dynamicsRobot);
1539 ARMARX_DEBUG_S << "add dynamicsRobot2 " << dynamicsRobot->getName();
1540 }
1541 catch (VirtualRobotException& e)
1542 {
1543 ARMARX_ERROR_S << " ERROR while building dynamic robot";
1544 ARMARX_ERROR_S << e.what();
1545 return false;
1546 }
1547
1548
1549 // since we do not visualize this robot we can skip visualization updates
1550 dynamicsRobot->getRobot()->setThreadsafe(false); // we already got a mutex protection
1551 dynamicsRobot->getRobot()->setUpdateVisualization(false);
1552
1553
1554 robInfo.isStatic = staticRobot;
1555 robInfo.robot = robot;
1556 robInfo.dynamicsRobot = dynamicsRobot;
1557
1558 dynamicRobots[robot->getName()] = robInfo;
1559
1560 return true;
1561}
1562
1564BulletPhysicsWorld::toFramedPose(const Eigen::Matrix4f& globalPose,
1565 const std::string& robotName,
1566 const std::string& frameName)
1567{
1568 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1569
1570 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
1571
1572 if (!dynamicsRobot || dynamicsRobot->getRobot()->getName() != robotName)
1573 {
1574 ARMARX_WARNING_S << "No robot or wrong name: " << robotName;
1575 return FramedPosePtr();
1576 }
1577
1578 RobotNodePtr rn = dynamicsRobot->getRobot()->getRobotNode(frameName);
1579
1580 if (!rn)
1581 {
1582 ARMARX_WARNING_S << "No robot node found(" << frameName << ")";
1583 return FramedPosePtr();
1584 }
1585
1586 Eigen::Matrix4f localPose = rn->toLocalCoordinateSystem(globalPose);
1587
1588 armarx::FramedPosePtr framedPose =
1589 new armarx::FramedPose(localPose, frameName, dynamicsRobot->getRobot()->getName());
1590 return framedPose;
1591}
1592
1593bool
1595 std::map<std::string, armarx::PoseBasePtr>& objMap)
1596{
1597 // lock engine and data
1598 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1599 ScopedRecursiveLockPtr lockSync = getScopedSyncLock(__FUNCTION__);
1600
1601 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
1602 // update visu data
1603 if (!dynamicsRobot || robotName != dynamicsRobot->getName())
1604 {
1605 //ARMARX_ERROR_S << "no robot data";
1606 return false;
1607 }
1608
1609 VirtualRobot::RobotPtr kinRobEngine = dynamicsRobot->getRobot();
1610 VirtualRobot::SceneObjectPtr currentObjEngine = kinRobEngine->getRootNode();
1611
1612 if (!synchronizeSceneObjectPoses(currentObjEngine, objMap))
1613 {
1614 ARMARX_ERROR_S << "Failed to synchronize objects...";
1615 return false;
1616 }
1617 return true;
1618}
1619
1620bool
1621BulletPhysicsWorld::getRobotStatus(const std::string& robotName,
1622 NameValueMap& jointAngles,
1623 NameValueMap& jointVelocities,
1624 NameValueMap& jointTorques,
1625 Eigen::Vector3f& linearVelocity,
1626 Eigen::Vector3f& angularVelocity)
1627{
1628 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1629 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
1630
1631 if (!dynamicsRobot || robotName != dynamicsRobot->getName())
1632 {
1633 return false;
1634 }
1635
1636 double simTimeFactor = 1.0;
1638 {
1639 simTimeFactor = static_cast<double>(simTimeStepMS / simStepExecutionDurationMS);
1640 }
1641
1642 VirtualRobot::RobotPtr kinRob = dynamicsRobot->getRobot();
1643
1644 SimDynamics::BulletRobotPtr br = std::dynamic_pointer_cast<BulletRobot>(dynamicsRobot);
1645 std::vector<RobotNodePtr> rn = kinRob->getRobotNodes();
1646
1647 for (auto& i : rn)
1648 {
1649 if (i->isJoint())
1650 {
1651 jointAngles[i->getName()] = i->getJointValue();
1652
1653 // TODO: check if isNodeActuated() is needed as well as else clause.
1654 // jointSpeed should also be valid / meaningful for a passive robot
1655 if (dynamicsRobot->isNodeActuated(i))
1656 {
1657 jointVelocities[i->getName()] = dynamicsRobot->getJointSpeed(i) * simTimeFactor;
1658
1659 if (br)
1660 {
1661 jointTorques[i->getName()] = br->getJointTorque(i);
1662 }
1663 }
1664 else
1665 {
1666 jointVelocities[i->getName()] = 0;
1667 jointTorques[i->getName()] = 0;
1668 }
1669 }
1670 }
1671
1672 DynamicsObjectPtr rootDyn = dynamicsRobot->getDynamicsRobotNode(kinRob->getRootNode());
1673
1674 if (rootDyn)
1675 {
1676 linearVelocity = rootDyn->getLinearVelocity();
1677 angularVelocity = rootDyn->getAngularVelocity();
1678 }
1679 else
1680 {
1681 linearVelocity.setZero();
1682 angularVelocity.setZero();
1683 }
1684
1685 return true;
1686}
1687
1688bool
1690{
1691 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1692 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(ftInfo.robotName);
1693 if (!dynamicsRobot)
1694 {
1695 static bool printed = false;
1696 if (!printed)
1697 {
1698 ARMARX_WARNING_S << "No robot available with name " << ftInfo.robotName;
1699 printed = true;
1700 }
1701
1702 return false;
1703 }
1704
1705 // update force torque info
1706 //for (size_t i = 0; i < simReportData.robots.at(0).forceTorqueSensors.size(); i++)
1707 //{
1708 if (ftInfo.enable)
1709 {
1710 ftInfo.currentForce = ftInfo.ftSensor->getForce();
1711 ftInfo.currentTorque = ftInfo.ftSensor->getTorque();
1712
1713 // transform to local coordinates
1714 std::string nodeName = ftInfo.robotNodeName;
1715 std::string robotName = ftInfo.robotName;
1716
1717 if (!robotName.empty() && !nodeName.empty() && dynamicsRobot)
1718 {
1719 RobotNodePtr rn = dynamicsRobot->getRobot()->getRobotNode(nodeName);
1720 Eigen::Vector3f forceLocal;
1721 Eigen::Vector3f forceGlobal = ftInfo.currentForce;
1722 Eigen::Vector3f torqueLocal;
1723 Eigen::Vector3f torqueGlobal = ftInfo.currentTorque;
1724
1725 if (rn)
1726 {
1727 Eigen::Matrix3f rotMat = rn->getGlobalPose().block(0, 0, 3, 3);
1728 forceLocal = rotMat.inverse() * forceGlobal;
1729 torqueLocal = rotMat.inverse() * torqueGlobal;
1730 ftInfo.currentForce = forceLocal;
1731 ftInfo.currentTorque = torqueLocal;
1732 }
1733 }
1734 }
1735 //}
1736
1737 return true;
1738}
1739
1740bool
1742{
1743 // lock engine and data
1744 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1745 ScopedRecursiveLockPtr lockSync = getScopedSyncLock(__FUNCTION__);
1746
1747 for (auto& dynamicsObject : dynamicsObjects)
1748 {
1749 SceneObjectPtr oEngine = dynamicsObject->getSceneObject();
1750 bool objectFound = false;
1751
1752 for (auto& s : simVisuData.objects)
1753 {
1754 if (s.name == oEngine->getName())
1755 {
1756 objectFound = true;
1757 synchronizeSceneObjectPoses(oEngine, s.objectPoses);
1758 s.updated = true;
1759 break;
1760 }
1761 }
1762
1763 if (!objectFound)
1764 {
1765 ARMARX_WARNING_S << "Object with name " << oEngine->getName()
1766 << " not in synchronized list";
1767 }
1768 }
1769
1770 return true;
1771}
1772
1773std::vector<DynamicsEngine::DynamicsContactInfo>
1775{
1776 ScopedRecursiveLockPtr lockSync = getScopedSyncLock(__FUNCTION__);
1777 return contacts;
1778}
1779
1780bool
1781BulletPhysicsWorld::addObstacleEngine(VirtualRobot::SceneObjectPtr o,
1782 VirtualRobot::SceneObject::Physics::SimulationType simType)
1783{
1784 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1785
1786 ARMARX_DEBUG_S << "Adding obstacle " << o->getName();
1787 //clonedObj = o->clone(o->getName());
1788
1789 DynamicsObjectPtr dynamicsObject;
1790
1791 try
1792 {
1793 if (simType != VirtualRobot::SceneObject::Physics::eUnknown)
1794 {
1795 o->setSimulationType(simType); //clonedObj
1796 }
1797
1798 dynamicsObject = dynamicsWorld->CreateDynamicsObject(o); //clonedObj
1799 dynamicsWorld->addObject(dynamicsObject);
1800 }
1801 catch (VirtualRobotException& e)
1802 {
1803 cout << " ERROR while building dynamic object";
1804 cout << e.what();
1805 return false;
1806 }
1807
1808 dynamicsObjects.push_back(dynamicsObject);
1809
1810 // since we do not visualize this object we can skip visualization updates
1811 dynamicsObject->getSceneObject()->setUpdateVisualization(false);
1812
1813 return true;
1814}
1815
1816std::vector<std::string>
1818{
1819 std::vector<std::string> names;
1820 {
1821 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1822 std::map<std::string, DynamicsRobotInfo>::iterator it = dynamicRobots.begin();
1823 while (it != dynamicRobots.end())
1824 {
1825 names.push_back(it->first);
1826 it++;
1827 }
1828 }
1829 return names;
1830}
1831
1832void
1833BulletPhysicsWorld::setObjectSimType(const std::string& objectName,
1834 SceneObject::Physics::SimulationType simType)
1835{
1836 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1837 SimDynamics::DynamicsObjectPtr o = getObject(objectName);
1838 if (!o)
1839 {
1840 ARMARX_WARNING_S << "Could not find object with name " << objectName;
1841 return;
1842 }
1843 o->setSimType(simType);
1844}
1845
1846void
1847BulletPhysicsWorld::setRobotNodeSimType(const std::string& robotName,
1848 const std::string& robotNodeName,
1849 SceneObject::Physics::SimulationType simType)
1850{
1851 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1852 SimDynamics::DynamicsRobotPtr r = getDynamicRobot(robotName);
1853 if (!r)
1854 {
1855 ARMARX_WARNING_S << "Could not find robot with name " << robotName;
1856 return;
1857 }
1858 DynamicsObjectPtr rn = r->getDynamicsRobotNode(robotNodeName);
1859 if (!rn)
1860 {
1861 ARMARX_WARNING_S << "Could not find robot node with name " << robotNodeName;
1862 return;
1863 }
1864 rn->setSimType(simType);
1865}
1866
1867std::vector<std::string>
1869{
1870 std::vector<std::string> names;
1871 {
1872 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1873
1874 for (auto& o : dynamicsObjects)
1875 {
1876 names.push_back(o->getName());
1877 }
1878 }
1879 return names;
1880}
1881
1882bool
1884{
1885 ARMARX_VERBOSE_S << "Removing obstacle " << name;
1886 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1887 {
1888 SimDynamics::DynamicsObjectPtr o = getObject(name);
1889
1890 if (!o)
1891 {
1892 return false;
1893 }
1894
1895 std::vector<SimDynamics::DynamicsObjectPtr>::iterator it =
1896 find(dynamicsObjects.begin(), dynamicsObjects.end(), o);
1897
1898 if (it != dynamicsObjects.end())
1899 {
1900 dynamicsObjects.erase(it);
1901 }
1902 else
1903 {
1904 ARMARX_WARNING_S << "Sync error";
1905 }
1906
1907 dynamicsWorld->removeObject(o);
1908 }
1909
1910 return true;
1911}
1912
1913void
1915{
1916 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1917 ARMARX_DEBUG_S << "start sim physics";
1918
1919
1920 // IceUtil::Time startTime = IceUtil::Time::now();
1921 btScalar dt1 = btScalar(getDeltaTimeMicroseconds() / 1000.0);
1922
1923 // bulletEngine->activateAllObjects(); // avoid sleeping objects
1924
1925 // the engine has to be stepped with seconds
1926 // max 100 internal loops
1927 ARMARX_DEBUG << deactivateSpam(1) << "dt1: " << (dt1 / 1000.0)
1928 << " max substeps: " << bulletFixedTimeStepMaxNrLoops
1929 << " internal step size: " << 0.001 * bulletFixedTimeStepMS;
1930 bulletEngine->stepSimulation(
1932 simTimeStepMS = static_cast<float>(dt1);
1933 // step static robots
1934 stepStaticRobots(dt1 / 1000.0);
1935
1936
1937 currentSimTimeSec += dt1 / 1000.0;
1938 // IceUtil::Time duration = IceUtil::Time::now() - startTime;
1939 simStepExecutionDurationMS = static_cast<float>(dt1);
1940 ARMARX_DEBUG_S << "end sim physics, sim duration [ms] : " << simStepExecutionDurationMS;
1941}
1942
1943void
1945{
1946 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
1947 auto startTime = IceUtil::Time::now(); // this should always be real time and not virtual time
1948
1949 // bulletEngine->activateAllObjects(); // avoid sleeping objects
1950 // bulletFixedTimeStepMaxNrLoops = 1;
1951
1952 float stepSize = static_cast<float>(stepSizeMs / 1000.0);
1953 ARMARX_DEBUG_S << "start sim physics: " << VAROUT(stepSize) << VAROUT(stepSizeMs);
1954 // int maxSubSteps = 10;
1955 // the engine has to be stepped with seconds
1956 // better results when stepping engine by hand
1957 // for (int i = 0; i < bulletFixedTimeStepMaxNrLoops; i++)
1958 {
1959 bulletEngine->stepSimulation(static_cast<double>(stepSize),
1961 0.001 * bulletFixedTimeStepMS);
1962 }
1963 simTimeStepMS = stepSizeMs; ///*bulletFixedTimeStepMaxNrLoops **/ stepSize * 1000.0f;
1964
1965 // step static robots
1966 stepStaticRobots(/*bulletFixedTimeStepMaxNrLoops **/ static_cast<double>(stepSize));
1967
1968
1969 currentSimTimeSec += static_cast<double>(stepSize) /** (float)bulletFixedTimeStepMaxNrLoops*/;
1970
1971
1972 if (maxRealTimeSimSpeed > 0)
1973 {
1974 auto duration = (IceUtil::Time::now() - startTime).toMilliSecondsDouble();
1975 const double minStepSizeMs = static_cast<double>(stepSizeMs / maxRealTimeSimSpeed);
1976 if (duration < minStepSizeMs)
1977 {
1978 ARMARX_DEBUG << "Sim calculation took " << duration << " - Sleeping now for "
1979 << (stepSizeMs - duration);
1980 usleep(static_cast<unsigned int>(1000 * (minStepSizeMs - duration)));
1981 }
1982 }
1983
1984 IceUtil::Time duration = IceUtil::Time::now() - startTime;
1985 simStepExecutionDurationMS = static_cast<float>(duration.toMilliSecondsDouble());
1986 ARMARX_DEBUG_S << "end sim physics, sim duration [ms] : " << simStepExecutionDurationMS;
1987}
1988
1989void
1991{
1992 // step through all static robots and apply velocities
1993 for (auto dr : dynamicRobots)
1994 {
1995 DynamicsRobotInfo ri = dr.second;
1996 if (ri.isStatic)
1997 {
1998 std::map<std::string, float> targetPos;
1999 VirtualRobot::RobotPtr kinRob = ri.robot;
2000 ARMARX_DEBUG << "Applying velocities for static robot " << kinRob->getName();
2001 for (auto nv : ri.targetVelocities)
2002 {
2003 if (!kinRob->hasRobotNode(nv.first))
2004 {
2005 ARMARX_ERROR << "No rn with name " << kinRob->hasRobotNode(nv.first);
2006 continue;
2007 }
2008 double change = static_cast<double>(nv.second) * deltaInSeconds;
2009
2010 //double randomNoiseValue = distribution(generator);
2011 //change += randomNoiseValue;
2012 double newAngle =
2013 static_cast<double>(kinRob->getRobotNode(nv.first)->getJointValue()) + change;
2014 targetPos[nv.first] = static_cast<float>(newAngle);
2015 }
2016
2017 if (not targetPos.empty())
2018 {
2019 ARMARX_DEBUG << "Target joint angles : " << targetPos;
2020 actuateRobotJointsPos(kinRob->getName(), targetPos);
2021 }
2022 }
2023 }
2024}
2025
2026int
2031
2032SimDynamics::BulletEnginePtr
2037
2038std::vector<VirtualRobot::SceneObjectPtr>
2040{
2041 std::vector<VirtualRobot::SceneObjectPtr> res;
2042 for (auto o : dynamicsObjects)
2043 {
2044 res.push_back(o->getSceneObject());
2045 }
2046 return res;
2047}
2048
2049std::vector<SimDynamics::DynamicsObjectPtr>
2054
2055void
2056BulletPhysicsWorld::setupFloorEngine(bool enable, const std::string& floorTexture)
2057{
2058
2059 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
2060
2061 if (!dynamicsWorld)
2062 {
2063 return;
2064 }
2065
2066 std::string textureFile = floorTexture;
2067
2068 if (enable)
2069 {
2070 ARMARX_INFO_S << "Creating floor plane...";
2071 dynamicsWorld->createFloorPlane();
2072 }
2073}
2074
2075void
2076BulletPhysicsWorld::enableLogging(const std::string& robotName, const std::string& logFile)
2077{
2078 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
2079 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
2080 BulletRobotPtr br = std::dynamic_pointer_cast<BulletRobot>(dynamicsRobot);
2081
2082 if (!br)
2083 {
2084 ARMARX_ERROR_S << "no bullet robot to log...";
2085 return;
2086 }
2087
2088 // create rns with all bodies
2089 std::vector<RobotNodePtr> rnsBodies;
2090 std::vector<RobotNodePtr> rnsJoints;
2091 std::vector<RobotNodePtr> rnAll = br->getRobot()->getRobotNodes();
2092 std::string nameJoints = "RNS_Joints_All_logging";
2093 std::string nameBodies = "RNS_Bodies_All_logging";
2094
2095 for (auto r : rnAll)
2096 {
2097 if (r->isJoint())
2098 {
2099 rnsJoints.push_back(r);
2100 }
2101
2102 if (r->getMass() > 0)
2103 {
2104 rnsBodies.push_back(r);
2105 }
2106 }
2107
2108 RobotNodeSetPtr rnsJ = RobotNodeSet::createRobotNodeSet(br->getRobot(), nameJoints, rnsJoints);
2109 RobotNodeSetPtr rnsB = RobotNodeSet::createRobotNodeSet(br->getRobot(), nameBodies, rnsBodies);
2110
2111 robotLogger.reset(new BulletRobotLogger(bulletEngine, br, rnsJ, rnsB));
2112 robotLogger->setLogPath(logFile);
2113 robotLogger->startLogging();
2114}
2115
2116bool
2118 std::map<std::string, armarx::PoseBasePtr>& objMap)
2119{
2120 if (!currentObjEngine)
2121 {
2122 return false;
2123 }
2124
2125 PosePtr p(new Pose(currentObjEngine->getGlobalPose()));
2126 objMap[currentObjEngine->getName()] = p;
2127 std::vector<SceneObjectPtr> childrenE = currentObjEngine->getChildren();
2128
2129 for (const auto& i : childrenE)
2130 {
2131 if (!synchronizeSceneObjectPoses(i, objMap))
2132 {
2133 return false;
2134 }
2135 }
2136
2137 return true;
2138}
2139
2140bool
2142{
2143 // lock engine and data
2144 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
2145
2146 // CONTACTS
2147 if (collectContacts)
2148 {
2149 contacts = dynamicsWorld->getEngine()->getContacts();
2150 std::stringstream ss;
2151 for (auto c : contacts)
2152 {
2153 ss << c.objectAName << " < - > " << c.objectBName;
2154 }
2155 ARMARX_DEBUG << "Contacts : " << endl << ss.str();
2156 }
2157 return true;
2158}
2159
2160btScalar
2162{
2163 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
2164 btScalar dt = static_cast<btScalar>(m_clock.getTimeMicroseconds());
2165 m_clock.reset();
2166 return dt;
2167}
2168
2169int
2171{
2172 ScopedRecursiveLockPtr l = getScopedSyncLock(__FUNCTION__);
2173 return static_cast<int>(contacts.size());
2174}
2175
2176DistanceInfo
2177BulletPhysicsWorld::getRobotNodeDistance(const std::string& robotName,
2178 const std::string& robotNodeName1,
2179 const std::string& robotNodeName2)
2180{
2181 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
2182
2183 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
2184 if (!dynamicsRobot)
2185 {
2186 throw LocalException("No robot");
2187 }
2188 if (dynamicsRobot->getName() != robotName)
2189 {
2190 throw LocalException("Wrong robot name. '")
2191 << robotName << "' != '" << dynamicsRobot->getName() << "'";
2192 }
2193 VirtualRobot::RobotPtr robot = dynamicsRobot->getRobot();
2194 if (!robot->hasRobotNode(robotNodeName1))
2195 {
2196 throw LocalException("Wrong robot node name. '") << robotNodeName1 << "'";
2197 }
2198 if (!robot->hasRobotNode(robotNodeName2))
2199 {
2200 throw LocalException("Wrong robot node name. '") << robotNodeName2 << "'";
2201 }
2202
2203 // Compute distance from node to the rest of the robot (does that make sense?!)
2204 Eigen::Vector3f p1, p2;
2205 auto model1 = robot->getRobotNode(robotNodeName1)->getCollisionModel();
2206 auto model2 = robot->getRobotNode(robotNodeName2)->getCollisionModel();
2207 float d = robot->getCollisionChecker()->calculateDistance(model1, model2, p1, p2);
2208 DistanceInfo di;
2209 di.distance = d;
2210 di.p1 = new Vector3(p1);
2211 di.p2 = new Vector3(p2);
2212
2213 return di;
2214}
2215
2216DistanceInfo
2217BulletPhysicsWorld::getDistance(const std::string& robotName,
2218 const std::string& robotNodeName,
2219 const std::string& worldObjectName)
2220{
2221 ScopedRecursiveLockPtr lockEngine = getScopedEngineLock(__FUNCTION__);
2222
2223 SimDynamics::DynamicsRobotPtr dynamicsRobot = getDynamicRobot(robotName);
2224 if (!dynamicsRobot)
2225 {
2226 throw LocalException("No robot");
2227 }
2228 if (dynamicsRobot->getName() != robotName)
2229 {
2230 throw LocalException("Wrong robot name. '")
2231 << robotName << "' != '" << dynamicsRobot->getName() << "'";
2232 }
2233 VirtualRobot::RobotPtr robot = dynamicsRobot->getRobot();
2234 if (!robot->hasRobotNode(robotNodeName))
2235 {
2236 throw LocalException("Wrong robot node name. '") << robotNodeName << "'";
2237 }
2238 SimDynamics::DynamicsObjectPtr object = getObject(worldObjectName);
2239 if (!object)
2240 {
2241 throw LocalException("No object with name '") << worldObjectName << "'";
2242 }
2243 VirtualRobot::SceneObjectPtr so = object->getSceneObject();
2244 Eigen::Vector3f p1, p2;
2245
2246 float d = robot->getCollisionChecker()->calculateDistance(
2247 robot->getRobotNode(robotNodeName)->getCollisionModel(), so->getCollisionModel(), p1, p2);
2248 DistanceInfo di;
2249 di.distance = d;
2250 di.p1 = new Vector3(p1);
2251 di.p2 = new Vector3(p2);
2252
2253 return di;
2254}
2255
2258{
2259 return RobotFactory::createFlattenedModel(*robot);
2260}
#define VAROUT(x)
constexpr T c
constexpr T dt
void setRobotAngularVelocity(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &vel) override
std::vector< SimDynamics::DynamicsObjectPtr > getDynamicObjects()
void actuateRobotJoints(const std::string &robotName, const std::map< std::string, float > &angles, const std::map< std::string, float > &velocities) override
void activateObject(const std::string &objectName) override
std::map< std::string, DynamicsRobotInfo > dynamicRobots
bool removeRobotEngine(const std::string &robotName) override
void setRobotLinearVelocity(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &vel) override
SimDynamics::DynamicsWorldPtr dynamicsWorld
SimDynamics::DynamicsObjectPtr getFirstDynamicsObject(const std::string &robotName, const std::string &nodeName)
std::vector< SimDynamics::DynamicsObjectPtr > dynamicsObjects
float getRobotJointLimitLo(const std::string &robotName, const std::string &nodeName) override
float getRobotMass(const std::string &robotName) override
bool hasRobot(const std::string &robotName) override
std::map< std::string, float > getRobotJointAngles(const std::string &robotName) override
float getRobotJointAngle(const std::string &robotName, const std::string &nodeName) override
VirtualRobot::SceneObjectPtr getFloor() override
void applyForceObject(const std::string &objectName, const Eigen::Vector3f &force) override
std::vector< std::string > getRobotNames() override
ForceTorqueDataSeq getRobotForceTorqueSensors(const std::string &robotName) override
Eigen::Vector3f getRobotLinearVelocity(const std::string &robotName, const std::string &nodeName) override
armarx::DistanceInfo getRobotNodeDistance(const std::string &robotName, const std::string &robotNodeName1, const std::string &robotNodeName2) override
armarx::DistanceInfo getDistance(const std::string &robotName, const std::string &robotNodeName, const std::string &worldObjectName) override
void applyForceRobotNode(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &force) override
std::vector< std::string > getObstacleNames() override
void stepStaticRobots(double deltaInSeconds)
Eigen::Vector3f getRobotAngularVelocity(const std::string &robotName, const std::string &nodeName) override
float getRobotMaxTorque(const std::string &robotName, const std::string &nodeName) override
void actuateRobotJointsPos(const std::string &robotName, const std::map< std::string, float > &angles) override
VirtualRobot::RobotPtr getRobot(const std::string &robotName) override
Eigen::Matrix4f getRobotNodePose(const std::string &robotName, const std::string &robotNodeName) override
void stepPhysicsRealTime() override
Perform one simulation step.
float getRobotJointVelocity(const std::string &robotName, const std::string &nodeName) override
std::map< std::string, float > getRobotJointVelocities(const std::string &robotName) override
bool getRobotStatus(const std::string &robotName, NameValueMap &jointAngles, NameValueMap &jointVelocities, NameValueMap &jointTorques, Eigen::Vector3f &linearVelocity, Eigen::Vector3f &angularVelocity) override
bool synchronizeRobotNodePoses(const std::string &robotName, std::map< std::string, armarx::PoseBasePtr > &objMap) override
bool objectGraspedEngine(const std::string &robotName, const std::string &robotNodeName, const std::string &objectName, Eigen::Matrix4f &storeLocalTransform) override
create a joint
void setRobotLinearVelocityRobotRootFrame(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &vel) override
SimDynamics::DynamicsObjectPtr getObject(const std::string &objectName)
bool objectReleasedEngine(const std::string &robotName, const std::string &robotNodeName, const std::string &objectName) override
remove a joint
bool removeObstacleEngine(const std::string &name) override
bool hasRobotNode(const std::string &robotName, const std::string &robotNodeName) override
Eigen::Matrix4f getObjectPose(const std::string &objectName) override
Eigen::Matrix4f getRobotPose(const std::string &robotName) override
void enableLogging(const std::string &robotName, const std::string &logFile) override
SimDynamics::BulletEnginePtr getEngine()
bool synchronizeSimulationDataEngine() override
std::vector< SimDynamics::DynamicsEngine::DynamicsContactInfo > contacts
void applyTorqueObject(const std::string &objectName, const Eigen::Vector3f &torque) override
std::map< std::string, VirtualRobot::RobotPtr > getRobots() override
void applyTorqueRobotNode(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &torque) override
bool addObstacleEngine(VirtualRobot::SceneObjectPtr o, VirtualRobot::SceneObject::Physics::SimulationType simType) override
void setRobotMaxTorque(const std::string &robotName, const std::string &nodeName, float maxTorque) override
SimDynamics::DynamicsObjectPtr getDynamicsObject(const std::string &objectName)
void setObjectSimType(const std::string &objectName, VirtualRobot::SceneObject::Physics::SimulationType simType) override
void setRobotNodeSimType(const std::string &robotName, const std::string &robotNodeName, VirtualRobot::SceneObject::Physics::SimulationType simType) override
bool addRobotEngine(VirtualRobot::RobotPtr robot, double pid_p, double pid_i, double pid_d, const std::string &filename, bool staticRobot, bool selfCollisions) override
float getRobotJointLimitHi(const std::string &robotName, const std::string &nodeName) override
void setRobotAngularVelocityRobotRootFrame(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &vel) override
void setRobotPose(const std::string &robotName, const Eigen::Matrix4f &globalPose) override
SimDynamics::BulletRobotLoggerPtr robotLogger
void setObjectPose(const std::string &objectName, const Eigen::Matrix4f &globalPose) override
virtual void initialize(int stepSizeMS, int bulletFixedTimeStepMS, int bulletFixedTimeStepMaxNrLoops, float maxRealTimeSimSpeed=1, bool floorPlane=false, std::string floorTexture=std::string())
std::map< std::string, float > getRobotJointTorques(const std::string &robotName) override
void stepPhysicsFixedTimeStep() override
Perform one simulation step.
FramedPosePtr toFramedPose(const Eigen::Matrix4f &globalPose, const std::string &robotName, const std::string &frameName) override
toFramedPose Constructs a framed pose
std::vector< VirtualRobot::SceneObjectPtr > getObjects() override
void setupFloorEngine(bool enable, const std::string &floorTexture) override
VirtualRobot::RobotPtr adaptRobotToWorld(VirtualRobot::RobotPtr robot) override
bool hasObject(const std::string &instanceName) override
virtual SimDynamics::DynamicsRobotPtr getDynamicRobot(const std::string &robotName)
void actuateRobotJointsVel(const std::string &robotName, const std::map< std::string, float > &velocities) override
std::vector< SimDynamics::DynamicsEngine::DynamicsContactInfo > copyContacts() override
SimDynamics::BulletEnginePtr bulletEngine
bool updateForceTorqueSensor(ForceTorqueInfo &ftInfo) override
bool synchronizeSceneObjectPoses(VirtualRobot::SceneObjectPtr currentObjEngine, std::map< std::string, armarx::PoseBasePtr > &objMap) override
void actuateRobotJointsTorque(const std::string &robotName, const std::map< std::string, float > &torques) override
The FramedPose class.
Definition FramedPose.h:281
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition Logging.cpp:99
The Pose class.
Definition Pose.h:243
SimulatedWorldData simReportData
std::vector< GraspingInfo > attachedObjects
virtual ScopedRecursiveLockPtr getScopedSyncLock(const std::string &callStr)
virtual ScopedRecursiveLockPtr getScopedEngineLock(const std::string &callStr)
virtual void setupFloor(bool enable, const std::string &floorTexture)
std::shared_ptr< ScopedRecursiveLock > ScopedRecursiveLockPtr
The Vector3 class.
Definition Pose.h:113
#define ARMARX_DEBUG_S
The logging level for output that is only interesting while debugging.
Definition Logging.h:205
#define ARMARX_ERROR_S
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:216
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_INFO_S
Definition Logging.h:202
#define ARMARX_VERBOSE_S
Definition Logging.h:207
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:213
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< Pose > PosePtr
Definition Pose.h:306
IceInternal::Handle< FramedPose > FramedPosePtr
Definition FramedPose.h:272
double angle(const Point &a, const Point &b, const Point &c)
Definition point.hpp:109
std::map< std::string, float > targetVelocities
Eigen::Vector3f currentTorque
VirtualRobot::ForceTorqueSensorPtr ftSensor
Eigen::Vector3f currentForce