ObjectCollisionAvoidanceVelCore.cpp
Go to the documentation of this file.
2
3#include <VirtualRobot/Nodes/RobotNode.h>
4#include <VirtualRobot/RobotNodeSet.h>
5
6#include <simox/control/environment/CollisionRobot.h>
7#include <simox/control/impl/simox/robot/Robot.h>
8
11
13
16
18{
19
21 const VirtualRobot::RobotPtr& rtRobot,
22 const Config& cfg) :
23 rtRobot(rtRobot)
24 {
26
27 rtCfg = cfg;
29 userCfg = rtCfg;
30 bufferCfgUserToRT.reinitAllBuffers(rtCfg);
31
32 // Collect tcp node names
33 std::vector<std::string> tcpNodeNames;
34 for (const auto& pair : rtCfg.ctrlCfg)
35 {
36 const auto nodeset = rtRobot->getRobotNodeSet(pair.first);
37 const std::string tcpName = nodeset->getTCP()->getName();
38 tcpNodeNames.push_back(tcpName);
39 if (pair.second.selfDistanceThreshold > preFilterDistance)
40 {
41 preFilterDistance = pair.second.selfDistanceThreshold;
42 }
43 if (pair.second.objectDistanceThreshold > preFilterDistance)
44 {
45 preFilterDistance = pair.second.objectDistanceThreshold;
46 }
47 }
48
49 /// add actuated robot joints
50 /// use a robot nodeset with all actuated joints, arms including head and torso joints, which change
51 /// the position of the robot body parts for correct collision checking
52 ARMARX_CHECK(rtRobot->hasRobotNodeSet(cfg.actuatedRobotNodeSetName));
53 rtRobotNodeSet = rtRobot->getRobotNodeSet(cfg.actuatedRobotNodeSetName);
54 actuatedJointNames = rtRobotNodeSet->getNodeNames();
55
56 /// initialize simox control robot for self-collision checking
57 scRobot = std::make_unique<simox::control::simox::robot::Robot>(
58 rtRobot, actuatedJointNames, tcpNodeNames, reduceModel);
59 scRobot->setGlobalPose(Eigen::Isometry3d::Identity());
60
61 ARMARX_CHECK(scRobot->getRobot()->hasRobotNodeSet(cfg.actuatedRobotNodeSetName));
62 scRobotNodeSet = scRobot->getRobot()->getRobotNodeSet(cfg.actuatedRobotNodeSetName);
63
64 ARMARX_DEBUG << "Creating robot model for collision computation using default primitive "
65 "models and models with id "
66 << rtCfg.primitiveModelParts;
67
69 std::make_unique<simox::control::environment::CollisionRobot<hpp::fcl::OBBRSS>>(
70 *scRobot,
71 simox::control::environment::CollisionRobotParams{.loadDefaultPrimitiveModel = true,
72 .primitiveModelIDs =
73 rtCfg.primitiveModelParts,
74 .sortNodes = true});
75
76 // initialize vector to store the current joint values of all actuated joints to update
77 // the simox robots with the most recent values, so the simox control robots display the
78 // current joint configuration of the real world model
80 qposActuatedJoints.setZero();
81
82 size_t jointIdx = 0;
83 for (const auto& nodeName : actuatedJointNames)
84 {
85 const auto node = rtRobot->getRobotNode(nodeName);
86 if (node->isTranslationalJoint())
87 {
88 // convert value from mm to m for simox control robot
89 // all translational values of the simox control robots are in meter
90 translationJointIndex.push_back(jointIdx);
91 }
92 jointIdx++;
93 }
94
95 for (const auto& pair : rtCfg.ctrlCfg)
96 {
97 collLimb.try_emplace(pair.first, rtRobot, pair.first, *scRobot, collisionPairs, rtCfg);
98 }
99
100 // Store all indices
101 ARMARX_INFO << "Creating index to node mapping for collision robot:";
102 std::unordered_set<unsigned int> consideredIndices;
103 for (auto& [name, data] : collLimb)
104 {
105 collisionRobot->getIndices(data.controller.getNodeSet(), data.collisionRobotIndices);
106 for (const auto& [index, node] : data.collisionRobotIndices)
107 {
108 ARMARX_DEBUG << "Mapping index " << index << " to node " << node->getName()
109 << " for limb " << name;
110 consideredIndices.insert(index);
111 }
112 }
113
114 ARMARX_DEBUG << "Initial computation of all self collision pairs";
115
116 selfColAvoidanceArgs =
117 simox::control::environment::CompDistArgs{.updatePose = false,
118 .nearestPoints = true,
119 .individualColObjects = true,
120 .allowIndices = consideredIndices};
121
122 // Compute number of collision pairs
123 // This will not change if no objects are attached and the args are not changed
124 collisionRobot->update(false); // update pose
125 const DistanceResults distanceResults =
126 collisionRobot->computeMinimumSelfCollisionDistance(selfColAvoidanceArgs);
127 const int nElements = distanceResults.size();
128
129 for (const auto& distanceResult : distanceResults)
130 {
131 ARMARX_DEBUG << "Considering distance between "
132 << collisionRobot->getNodes().at(distanceResult.node1).getName() << " and "
133 << collisionRobot->getNodes().at(distanceResult.node2).getName()
134 << ". Initial distance: " << distanceResult.minDistance << "m";
135 }
136
137 ARMARX_DEBUG << "Reserving space for " << nElements << " collision pairs";
138 ARMARX_CHECK_EXPRESSION(nElements < rtCfg.maxCollisionPairs);
139 collisionPairs.reserve(nElements);
140 }
141
143 {
144 ARMARX_IMPORTANT << "destruction of ObjectCollisionAvoidanceVelBase";
145 }
146
148 const std::string& robotNodeSetName,
149 const SCRobot& scRobot,
151 const Config& c) :
152 nodeSetName(robotNodeSetName),
153 rtRNS(rtRobot->getRobotNodeSet(robotNodeSetName)),
154 controller(scRobot.getSubNodeSet(robotNodeSetName)),
156 {
158 ARMARX_CHECK_GREATER(c.maxCollisionPairs, 0);
159
160 reset(c);
161
162 dynamicsModel = scRobot.createDynamicsModel(robotNodeSetName);
163
164 bufferRTtoPublish.reinitAllBuffers(rts);
165 }
166
167 void
169 {
170 rts.reset(
171 c.ctrlCfg.at(rtRNS->getName()), controller.numNodes(), c.maxCollisionPairs, rtRNS);
172 rts.objectCollisionNullSpaceWeights =
174 c.ctrlCfg.at(rtRNS->getName()).objectCollActivatorZ1,
175 c.ctrlCfg.at(rtRNS->getName()).objectCollActivatorZ2);
176 recoveryStateObjColl.reset();
177 recoveryStateSelfColl.reset();
178 }
179
180 void
182 {
183 for (auto& pair : collLimb)
184 {
185 pair.second.rts.rtPreActivate(userCfg.ctrlCfg.at(pair.first));
186 pair.second.recoveryStateObjColl.reset();
187 pair.second.recoveryStateSelfColl.reset();
188 }
189 }
190
191 void
193 {
194 for (auto& pair : collLimb)
195 {
196 pair.second.reset(rtCfg);
197 }
198 }
199
200 void
202 {
203 /// Running in rt thread.
204 rtCfg = bufferCfgUserToRT.getUpToDateReadBuffer();
206 }
207
208 void
210 {
211 // /// ----------------- update joint values for simox Robots ---------------------------------
212 // qposActuatedJoints = rtRobot->getRobotNodeSet(rtCfg.actuatedRobotNodeSetName)
213 // ->getJointValuesEigen()
214 // .cast<double>();
215 //
216 // // convert value from mm to m for simox control robot
217 // // all translational values of the simox control robots are in meter
218 // for (unsigned int i : translationJointIndex)
219 // {
220 // qposActuatedJoints(i) *= 0.001;
221 // }
222 //
223 // /// ----------------- update Simox robots --------------------------------------------------
224 // ///
225 // /// a VectorXd is needed with nodeSet size (size of actuated joints in order of vector,
226 // /// which has been used for initialization in init
227 // ///
228 // /// It is very important that the simox robots map the current joint configuration of the
229 // /// real-world robot
230 // scRobot->setConfig(qposActuatedJoints);
231
232 // Directly set Simox robot inside and then update the joints of simox control robot
233 scRobotNodeSet->setJointValues(rtRobotNodeSet->getJointValuesEigen());
234 scRobot->update();
235 globalPose = rtRobot->getGlobalPose().matrix().cast<double>();
236 globalPose.block<3, 1>(0, 3) /= 1000.0;
237 scRobot->setGlobalPose(simox::control::Pose(globalPose), true);
238
239 /// ----------------- calculation of robot collision pairs ---------------------------------
240 const auto time = IceUtil::Time::now();
241 // TODO update is also called in computeMinimumSelfCollisionDistance if updatePose = true in selfColAvoidanceArgs
242 collisionRobot->update(false); // update pose
243 collisionRobot->computeMinimumSelfCollisionDistance(collisionPairs, selfColAvoidanceArgs);
244 const double collisionPairTime = (IceUtil::Time::now() - time).toMicroSecondsDouble();
245
246 for (auto& pair : collLimb)
247 {
248 pair.second.rts.collisionPairTime = collisionPairTime;
249 pair.second.rts.collisionPairsNum = collisionPairs.size();
250 }
251
252 /// ----------------- calculation of collision pairs between the robot and the environment -----------------
253 collisionRobot->computeMinimumDistance(
254 rtCollisionObjects, externalCollisionPairs, compDistArgs);
255 }
256
257 void
258 ObjectCollisionAvoidanceVelBase::rtLimbControllerRun(const std::string& robotNodeSetName,
259 const Eigen::VectorXf& qpos,
260 const Eigen::VectorXf& qvelFiltered,
261 float velocityLimit,
262 const Eigen::VectorXf& trajFollowJointVel,
263 double deltaT)
264 {
265 auto& arm = collLimb.at(robotNodeSetName);
266
267 ARMARX_CHECK_EQUAL(arm.rts.trajFollowJointVel.size(), trajFollowJointVel.size());
268 arm.rts.trajFollowJointVel = trajFollowJointVel;
269 arm.controller.run(rtCfg.ctrlCfg.at(robotNodeSetName),
270 arm.rts,
271 arm.recoveryStateSelfColl,
272 arm.recoveryStateObjColl,
273 arm.collisionPairs,
275 arm.collisionRobotIndices,
276 *arm.dynamicsModel,
277 qpos,
278 qvelFiltered,
279 velocityLimit,
280 deltaT);
281 arm.bufferRTtoPublish.getWriteBuffer() = arm.rts;
282 arm.bufferRTtoPublish.commitWrite();
283
284 arm.bufferRecoveryStateSelfColl.getWriteBuffer() = arm.recoveryStateSelfColl;
285 arm.bufferRecoveryStateSelfColl.commitWrite();
286 }
287
288 void
290 {
291 ARMARX_CHECK_NONNEGATIVE(cfg.maxCollisionPairs);
292 ARMARX_CHECK_NOT_EMPTY(cfg.primitiveModelParts);
293 ARMARX_CHECK_NOT_EMPTY(cfg.actuatedRobotNodeSetName);
294 for (auto& pair : cfg.ctrlCfg)
295 {
297 }
298 }
299
300 void
302 {
303 userCfg = cfg;
305 bufferCfgUserToRT.getWriteBuffer() = userCfg;
306 bufferCfgUserToRT.commitWrite();
307 }
308
309 void
311 {
312 /// Running in rt thread.
313 std::tie(externalCollisionPairs, rtCollisionObjects) =
314 bufferCollisionObjectsUserToRt.getUpToDateReadBuffer();
315 }
316
317 void
319 {
320 userCollisionObjects.clear();
321 auto& writeBuffer = bufferCollisionObjectsUserToRt.getWriteBuffer();
322 std::get<0>(writeBuffer).reserve(0);
323 std::get<1>(writeBuffer) = userCollisionObjects;
324 bufferCollisionObjectsUserToRt.commitWrite();
325 }
326
327 void
329 const std::vector<hpp::fcl::CollisionObject>& collisionObjects)
330 {
331 const unsigned int nElements =
332 collisionRobot->computeNElements(compDistArgs, collisionObjects);
333 ARMARX_INFO << "There are " << collisionObjects.size() << " collision objects";
334 ARMARX_INFO << "Reserving space for " << nElements << " collision pairs";
335
336 userCollisionObjects = collisionObjects;
337 auto& writeBuffer = bufferCollisionObjectsUserToRt.getWriteBuffer();
338 std::get<0>(writeBuffer).reserve(nElements);
339 std::get<1>(writeBuffer) = collisionObjects;
340 bufferCollisionObjectsUserToRt.commitWrite();
341 }
342
343
344} // namespace armarx::control::njoint_controller::core
uint8_t index
#define ARMARX_CHECK_NOT_EMPTY(c)
constexpr T c
ObjectCollisionAvoidanceVelBase(const VirtualRobot::RobotPtr &rtRobot, const Config &cfg)
armarx::TripleBuffer< std::tuple< DistanceResults, std::vector< hpp::fcl::CollisionObject > > > bufferCollisionObjectsUserToRt
void rtLimbControllerRun(const std::string &robotNodeSetName, const Eigen::VectorXf &qpos, const Eigen::VectorXf &qvelFiltered, float velocityLimit, const Eigen::VectorXf &trajFollowJointVel, double deltaT)
#define ARMARX_CHECK_GREATER(lhs, rhs)
This macro evaluates whether lhs is greater (>) than rhs and if it turns out to be false it will thro...
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_NONNEGATIVE(number)
Check whether number is nonnegative (>= 0).
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
void validateConfigData(const arondto::CollisionAvoidanceConfig &cfg)
Eigen::Vector4f calculateTransitionWeights(float z1, float z2)
helper functions
Definition utils.cpp:25
VirtualRobot::RobotNodeSetPtr rtRNS
!!!!!!! Note that, all the data below should only be accessed in rt thread !!!!!!!
NodeSetData(const VirtualRobot::RobotPtr &rtRobot, const std::string &robotNodeSetName, const SCRobot &scRobot, const DistanceResults &collisionPairs, const Config &c)