CollisionAvoidanceCore.cpp
Go to the documentation of this file.
2
3#include <VirtualRobot/Nodes/RobotNode.h>
4#include <VirtualRobot/Robot.h>
5#include <VirtualRobot/RobotNodeSet.h>
6
7#include <simox/control/environment/CollisionRobot.h>
8#include <simox/control/impl/simox/robot/Robot.h>
9
12
14{
15
17 const VirtualRobot::RobotPtr& rtRobot,
18 const Config& cfg,
19 const std::map<std::string, std::vector<size_t>>& velCtrlIndices) :
20 rtRobot(rtRobot)
21 {
23
24 rtCfg = cfg;
26 userCfg = rtCfg;
27 bufferCfgUserToRT.reinitAllBuffers(rtCfg);
28 velCtrlIdx = velCtrlIndices;
29
30 // Collect tcp node names
31 std::vector<std::string> tcpNodeNames;
32 for (const auto& pair : rtCfg.ctrlCfg)
33 {
34 const auto nodeset = rtRobot->getRobotNodeSet(pair.first);
35 const std::string tcpName = nodeset->getTCP()->getName();
36 tcpNodeNames.push_back(tcpName);
37 if (pair.second.selfDistanceThreshold > preFilterDistance)
38 {
39 preFilterDistance = pair.second.selfDistanceThreshold;
40 }
41 }
42
43 /// add actuated robot joints
44 /// use a robot nodeset with all actuated joints, arms including head and torso joints, which change
45 /// the position of the robot body parts for correct collision checking
46 ARMARX_CHECK(rtRobot->hasRobotNodeSet(cfg.actuatedRobotNodeSetName));
47 rtRobotNodeSet = rtRobot->getRobotNodeSet(cfg.actuatedRobotNodeSetName);
48 actuatedJointNames = rtRobotNodeSet->getNodeNames();
49
50 /// initialize simox control robot for self-collision checking
51 scRobot = std::make_unique<simox::control::simox::robot::Robot>(
52 rtRobot, actuatedJointNames, tcpNodeNames, reduceModel);
53 scRobot->setGlobalPose(Eigen::Isometry3d::Identity());
54
55 ARMARX_CHECK(scRobot->getRobot()->hasRobotNodeSet(cfg.actuatedRobotNodeSetName));
56 scRobotNodeSet = scRobot->getRobot()->getRobotNodeSet(cfg.actuatedRobotNodeSetName);
57
58 ARMARX_DEBUG << "Creating robot model for collision computation using default primitive "
59 "models and models with id "
60 << rtCfg.primitiveModelParts;
61
63 std::make_unique<simox::control::environment::CollisionRobot<hpp::fcl::OBBRSS>>(
64 *scRobot,
65 simox::control::environment::CollisionRobotParams{.loadDefaultPrimitiveModel = true,
66 .primitiveModelIDs =
67 rtCfg.primitiveModelParts,
68 .sortNodes = true});
69
70 // initialize vector to store the current joint values of all actuated joints to update
71 // the simox robots with the most recent values, so the simox control robots display the
72 // current joint configuration of the real world model
74 qposActuatedJoints.setZero();
75
76 size_t jointIdx = 0;
77 for (const auto& nodeName : actuatedJointNames)
78 {
79 const auto node = rtRobot->getRobotNode(nodeName);
80 if (node->isTranslationalJoint())
81 {
82 // convert value from mm to m for simox control robot
83 // all translational values of the simox control robots are in meter
84 translationJointIndex.push_back(jointIdx);
85 }
86 jointIdx++;
87 }
88
89 for (const auto& pair : rtCfg.ctrlCfg)
90 {
91 collLimb.try_emplace(pair.first,
92 rtRobot,
93 pair.first,
94 *scRobot,
96 rtCfg,
97 velCtrlIdx.at(pair.first));
98 }
99
100 // Store all indices
101 ARMARX_DEBUG << "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 CollisionAvoidanceBase";
145 }
146
148 const std::string& robotNodeSetName,
149 const SCRobot& scRobot,
151 const Config& c,
152 const std::vector<size_t>& velCtrlIndex) :
153 nodeSetName(robotNodeSetName),
154 rtRNS(rtRobot->getRobotNodeSet(robotNodeSetName)),
155 controller(scRobot.getSubNodeSet(robotNodeSetName)),
157 {
159 ARMARX_CHECK_GREATER(c.maxCollisionPairs, 0);
160
161 reset(c, velCtrlIndex);
162
163 dynamicsModel = scRobot.createDynamicsModel(robotNodeSetName);
164
165 bufferRTtoPublish.reinitAllBuffers(rts);
166 }
167
168 void
170 const std::vector<size_t>& velCtrlIndex)
171 {
172 rts.reset(c.ctrlCfg.at(rtRNS->getName()),
173 controller.numNodes(),
174 c.maxCollisionPairs,
175 rtRNS,
176 velCtrlIndex);
177 rStateSelfColl.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.rStateSelfColl.reset();
187 }
188 }
189
190 void
192 {
193 for (auto& pair : collLimb)
194 {
195 pair.second.reset(rtCfg, velCtrlIdx.at(pair.first));
196 }
197 }
198
199 void
201 {
202 /// Running in rt thread.
203 rtCfg = bufferCfgUserToRT.getUpToDateReadBuffer();
205 }
206
207 void
209 {
210 // Directly set Simox robot inside and then update the joints of simox control robot
211 scRobotNodeSet->setJointValues(rtRobotNodeSet->getJointValuesEigen());
212 scRobot->update();
213
214 /// ----------------- calculation of robot collision pairs ---------------------------------
215 const auto time = IceUtil::Time::now();
216 collisionRobot->update(false); // update pose
217 collisionRobot->computeMinimumSelfCollisionDistance(collisionPairs, selfColAvoidanceArgs);
218 const double collisionPairTime = (IceUtil::Time::now() - time).toMicroSecondsDouble();
219
220 for (auto& pair : collLimb)
221 {
222 pair.second.rts.collisionPairTime = collisionPairTime;
223 pair.second.rts.collisionPairsNum = collisionPairs.size();
224 }
225 }
226
227 void
228 CollisionAvoidanceBase::rtLimbControllerRun(const std::string& robotNodeSetName,
229 const Eigen::VectorXf& qpos,
230 const Eigen::VectorXf& qvelFiltered,
231 float torqueLimit,
232 const Eigen::VectorXf& impedanceJointTorque,
233 double deltaT)
234 {
235 auto& arm = collLimb.at(robotNodeSetName);
236
237 ARMARX_CHECK_EQUAL(arm.rts.impedanceJointTorque.size(), impedanceJointTorque.size());
238 arm.rts.impedanceJointTorque = impedanceJointTorque;
239 arm.controller.run(rtCfg.ctrlCfg.at(robotNodeSetName),
240 arm.rts,
241 arm.rStateSelfColl,
242 arm.collisionPairs,
243 arm.collisionRobotIndices,
244 *arm.dynamicsModel,
245 qpos,
246 qvelFiltered,
247 torqueLimit,
248 deltaT);
249 arm.bufferRTtoPublish.getWriteBuffer() = arm.rts;
250 arm.bufferRTtoPublish.commitWrite();
251 }
252
253 void
255 {
256 ARMARX_CHECK_NONNEGATIVE(cfg.maxCollisionPairs);
257 ARMARX_CHECK_NOT_EMPTY(cfg.primitiveModelParts);
258 ARMARX_CHECK_NOT_EMPTY(cfg.actuatedRobotNodeSetName);
259 for (auto& pair : cfg.ctrlCfg)
260 {
262 }
263 }
264
265 void
267 {
268 userCfg = cfg;
270 bufferCfgUserToRT.getWriteBuffer() = userCfg;
271 bufferCfgUserToRT.commitWrite();
272 }
273
274} // namespace armarx::control::njoint_controller::core
uint8_t index
#define ARMARX_CHECK_NOT_EMPTY(c)
constexpr T c
law::CollisionAvoidanceController::DistanceResults DistanceResults
Eigen::VectorXd qposActuatedJoints
TODO, rename to actuatedJointNames, Not needed anymore?
void rtLimbControllerRun(const std::string &robotNodeSetName, const Eigen::VectorXf &qpos, const Eigen::VectorXf &qvelFiltered, float torqueLimit, const Eigen::VectorXf &impedanceJointTorque, double deltaT)
CollisionAvoidanceBase(const VirtualRobot::RobotPtr &rtRobot, const Config &cfg, const std::map< std::string, std::vector< size_t > > &velCtrlIndices)
#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_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)
VirtualRobot::RobotNodeSetPtr rtRNS
!!!!!!! Note that, all the data below should only be accessed in rt thread !!!!!!!
void reset(const Config &c, const std::vector< size_t > &velCtrlIndex)
std::unique_ptr< DynamicsModel > dynamicsModel
self-collision avoidance
NodeSetData(const VirtualRobot::RobotPtr &rtRobot, const std::string &robotNodeSetName, const SCRobot &scRobot, const DistanceResults &collisionPairs, const Config &c, const std::vector< size_t > &velCtrlIndex)