TrajectoryControllerSubUnit.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotAPI::ArmarXObjects::TrajectoryControllerSubUnit
17 * @author Stefan Reither ( stef dot reither at web dot de )
18 * @date 2017
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
25using namespace armarx;
26
27void
29{
30 kinematicUnitName = getProperty<std::string>("KinematicUnitName").getValue();
31 usingProxy(kinematicUnitName);
32 robotPoseUnitEnabled = getProperty<bool>("EnableRobotPoseUnit").getValue();
33 robotPoseUnitName = getProperty<std::string>("RobotPoseUnitName").getValue();
34
35 kp = getProperty<float>("Kp").getValue();
36 ki = getProperty<float>("Ki").getValue();
37 kd = getProperty<float>("Kd").getValue();
38 maxVelocity = getProperty<float>("absMaximumVelocity").getValue() / 180 *
39 M_PI; // config expects value in rad/sec
40
41 offeringTopic("DebugDrawerUpdates");
42}
43
44void
46{
47 kinematicUnit = getProxy<KinematicUnitInterfacePrx>(kinematicUnitName);
48 debugDrawer = getTopic<armarx::DebugDrawerInterfacePrx>("DebugDrawerUpdates");
49}
50
51void
53{
54 debugDrawer->clearLayer("Preview");
55}
56
57bool
59{
60 ARMARX_DEBUG << "Starting TrajectoryPlayer ...";
61
62 ARMARX_CHECK_EXPRESSION(jointTraj) << "No trajectory loaded!";
63 assureTrajectoryController();
64
65 jointTrajController->setTrajectory(this->jointTraj, c);
66 jointTraj = jointTrajController->getTrajectoryCopy();
67 jointTrajController->activateController();
68
69 if (isPreview)
70 {
71 std::string fileName = kinematicUnit->getRobotFilename();
72 ARMARX_INFO << "robot file name : " << fileName;
73 debugDrawer->setRobotVisu("Preview",
74 "previewRobot",
75 fileName,
76 fileName.substr(0, fileName.find("/")),
77 armarx::CollisionModel);
78 debugDrawer->updateRobotColor("Preview", "previewRobot", DrawColor{0, 1, 0, 0.5});
79
80 previewTask =
82 &TrajectoryControllerSubUnit::previewRun,
83 20,
84 false,
85 "TrajectoryControllerSubUnitPreviewTask",
86 false);
87 previewTask->start();
88 }
89
90 return true;
91}
92
93bool
95{
96 if (controllerExists())
97 {
98 if (jointTrajController->isControllerActive())
99 {
100 ARMARX_DEBUG << "Pausing TrajectoryPlayer ...";
101 jointTrajController->deactivateController();
102 }
103 else
104 {
105 ARMARX_DEBUG << "Resuming TrajectoryPlayer ...";
106 jointTrajController->activateController();
107 }
108 }
109 return true;
110}
111
112bool
114{
115 ARMARX_DEBUG << "Stopping TrajectoryPlayer ...";
116
117 if (controllerExists())
118 {
119 if (isPreview)
120 {
121 previewTask->stop();
122 debugDrawer->clearLayer("Preview");
123 }
124
125 jointTrajController->deactivateController();
126 while (jointTrajController->isControllerActive())
127 {
128 }
129 jointTrajController->deleteController();
130 }
131 return true;
132}
133
134bool
135TrajectoryControllerSubUnit::resetTrajectoryPlayer(bool moveToFrameZeroPose, const Ice::Current& c)
136{
137 ARMARX_DEBUG << "Resetting TrajectoryPlayer ...";
138
139 if (controllerExists() && jointTrajController->isControllerActive())
140 {
141 jointTrajController->deactivateController();
142 while (jointTrajController->isControllerActive())
143 {
144 }
145 }
146
147 if (!jointTraj)
148 {
149 ARMARX_INFO << "No trajectory loaded! Cannot reset to FrameZeroPose!";
150 return false;
151 }
152
153 assureTrajectoryController();
154
155 jointTrajController->setTrajectory(this->jointTraj, c);
156 if (moveToFrameZeroPose)
157 {
158 std::vector<Ice::DoubleSeq> states = jointTraj->getAllStates(0.0f, 1);
159 NameValueMap frameZeroPositions;
160 NameControlModeMap controlModes;
161
162 auto dimNames = jointTraj->getDimensionNames();
163 for (size_t i = 0; i < dimNames.size(); i++)
164 {
165 const auto& jointName = dimNames.at(i);
166 if (std::find(usedJoints.begin(), usedJoints.end(), jointName) != usedJoints.end())
167 {
168 frameZeroPositions[jointName] = states[i][0];
169 controlModes[jointName] = ePositionControl;
170 }
171 }
172
173 kinematicUnit->switchControlMode(controlModes);
174 kinematicUnit->setJointAngles(frameZeroPositions);
175 }
176 return true;
177}
178
179void
180TrajectoryControllerSubUnit::loadJointTraj(const TrajectoryBasePtr& jointTraj,
181 const Ice::Current& c)
182{
183 ARMARX_DEBUG << "Loading Trajectory ...";
184
185 std::unique_lock lock(dataMutex);
186
187 this->jointTraj = TrajectoryPtr::dynamicCast(jointTraj);
188
189 if (!this->jointTraj)
190 {
191 ARMARX_ERROR << "Error when loading TrajectoryPlayer: cannot load jointTraj !!!";
192 return;
193 }
194
195 if (this->jointTraj->size() == 0)
196 {
197 ARMARX_ERROR << "Error when loading TrajectoryPlayer: trajectory is empty !!!";
198 return;
199 }
200 ARMARX_INFO << VAROUT(this->jointTraj->getDimensionNames());
201
202 auto startTime = this->jointTraj->begin()->getTimestamp();
203 this->jointTraj->shiftTime(-startTime);
204 bool differentJointSet = usedJoints.size() != this->jointTraj->getDimensionNames().size();
205 if (!differentJointSet)
206 {
207 for (size_t i = 0; i < usedJoints.size(); i++)
208 {
209 if (usedJoints.at(i) != this->jointTraj->getDimensionNames().at(i))
210 {
211 differentJointSet = true;
212 break;
213 }
214 }
215 }
216 usedJoints = this->jointTraj->getDimensionNames();
217 ARMARX_INFO << VAROUT(usedJoints);
218
219 if (usedJoints.size() != this->jointTraj->dim())
220 {
221 ARMARX_ERROR << "Not all trajectory dimensions are named !!! (would cause problems when "
222 "using kinematicUnit)";
223 return;
224 }
225
226 if (!jointTrajController || differentJointSet || recreateController)
227 {
228 jointTrajController = createTrajectoryController(usedJoints, true);
229 }
230 jointTrajController->setTrajectory(this->jointTraj, c);
231
232 endTime = jointTrajController->getTrajEndTime();
233 trajEndTime = endTime;
234}
235
236void
237TrajectoryControllerSubUnit::loadBasePoseTraj(const TrajectoryBasePtr& basePoseTraj,
238 const Ice::Current& c)
239{
240 this->basePoseTraj = TrajectoryPtr::dynamicCast(basePoseTraj);
241}
242
243void
244TrajectoryControllerSubUnit::setLoopPlayback(bool loop, const Ice::Current& c)
245{
246 std::unique_lock lock(dataMutex);
247
248 if (!controllerExists())
249 {
250 ARMARX_WARNING << "No trajectory has been loaded and therefore no controller exists.";
251 return;
252 }
253 jointTrajController->setLooping(loop);
254}
255
256double
258{
259 return endTime;
260}
261
262double
264{
265 return trajEndTime;
266}
267
268double
270{
271 std::unique_lock lock(dataMutex);
272
273 if (!controllerExists())
274 {
275 ARMARX_WARNING << "No trajectory has been loaded and therefore no controller exists.";
276 return 0.0;
277 }
278 return jointTrajController->getCurrentTrajTime();
279}
280
281void
282TrajectoryControllerSubUnit::setEndTime(Ice::Double end, const Ice::Current& c)
283{
284 ARMARX_DEBUG << "Setting end-time ...";
285
286 std::unique_lock lock(dataMutex);
287
288 if (!jointTraj)
289 {
290 ARMARX_WARNING << "No trajectory has been loaded!";
291 return;
292 }
293 assureTrajectoryController();
294
295 if (jointTrajController->isControllerActive())
296 {
297 ARMARX_WARNING << "TrajectoryController already running. Please reset it before setting a "
298 "new end-time.";
299 return;
300 }
301
302 if (endTime == end)
303 {
304 return;
305 }
306
307 bool b = considerConstraintsForTrajectoryOptimization;
308 considerConstraintsForTrajectoryOptimization = false;
309
310 endTime = end;
311 jointTraj = jointTraj->normalize(0, endTime);
312 if (basePoseTraj)
313 {
314 basePoseTraj = basePoseTraj->normalize(0, endTime);
315 }
316
317 jointTrajController->setTrajectory(jointTraj, c);
318
319 considerConstraintsForTrajectoryOptimization = b;
320}
321
322void
323TrajectoryControllerSubUnit::setIsPreview(bool isPreview, const Ice::Current& c)
324{
325 if (controllerExists() && jointTrajController->isControllerActive())
326 {
327 ARMARX_WARNING << "TrajectoryController already running. Please reset it before setting "
328 "whether the controller is only for preview.";
329 return;
330 }
331 this->isPreview = isPreview;
332
333 if (jointTraj)
334 {
335 jointTrajController = createTrajectoryController(usedJoints, true);
336 jointTrajController->setTrajectory(jointTraj, c);
337 }
338}
339
340bool
342 bool isInUse,
343 const Ice::Current& c)
344{
345 ARMARX_DEBUG << "Setting joints in use ...";
346
347 std::unique_lock lock(dataMutex);
348
349 if (controllerExists())
350 {
351 ARMARX_WARNING << "TrajectoryController already running. Please reset it before setting "
352 "joints in use.";
353 }
354 else
355 {
356 if (isInUse &&
357 (std::find(usedJoints.begin(), usedJoints.end(), jointName) == usedJoints.end()))
358 {
359 usedJoints.push_back(jointName);
360 }
361 else if (!isInUse)
362 {
363 auto it = std::find(usedJoints.begin(), usedJoints.end(), jointName);
364 if (it != usedJoints.end())
365 {
366 std::swap(*it, usedJoints.back());
367 usedJoints.pop_back();
368 }
369 }
370
371 if (jointTraj)
372 {
373 jointTrajController = createTrajectoryController(usedJoints, true);
374 jointTrajController->setTrajectory(jointTraj, c);
375 }
376 }
377
378 return isInUse;
379}
380
381void
382TrajectoryControllerSubUnit::enableRobotPoseUnit(bool isRobotPose, const Ice::Current& c)
383{
384 ARMARX_WARNING << "NYI : TrajectoryControllerSubUnit::enableRobotPoseUnit()";
385}
386
387void
391
392void
393TrajectoryControllerSubUnit::considerConstraints(bool consider, const Ice::Current& c)
394{
395 if (controllerExists() && jointTrajController->isControllerActive())
396 {
397 ARMARX_WARNING << "TrajectoryController already running. Please reset it before setting "
398 "whether constraints should be considered.";
399 return;
400 }
401 considerConstraintsForTrajectoryOptimization = consider;
402
403 if (jointTraj)
404 {
405 jointTrajController = createTrajectoryController(usedJoints, false);
406 jointTrajController->setTrajectory(jointTraj, c);
407 }
408}
409
410NJointTrajectoryControllerPtr
411TrajectoryControllerSubUnit::createTrajectoryController(std::vector<std::string>& jointNames,
412 bool deleteIfAlreadyExist)
413{
414 std::unique_lock lock(controllerMutex);
415
416 if (controllerExists() && deleteIfAlreadyExist)
417 {
418 jointTrajController->deactivateController();
419 while (jointTrajController->isControllerActive())
420 {
421 usleep(500);
422 }
423 jointTrajController->deleteController();
424 while (getArmarXManager()->getIceManager()->isObjectReachable(controllerName))
425 {
426 usleep(500);
427 }
428 }
429
430 NJointTrajectoryControllerPtr trajController = jointTrajController;
431 if (!controllerExists() || deleteIfAlreadyExist)
432 {
433 recreateController = false;
434 NJointTrajectoryControllerConfigPtr config = new NJointTrajectoryControllerConfig();
435 ARMARX_INFO << VAROUT(kp) << VAROUT(ki) << VAROUT(kd);
436 config->PID_p = kp;
437 config->PID_i = ki;
438 config->PID_d = kd;
439 config->maxVelocity = maxVelocity;
440 config->jointNames = jointNames;
441 config->considerConstraints = considerConstraintsForTrajectoryOptimization;
442 config->isPreview = isPreview;
443 controllerName = this->getName() + "_" + "JointTrajectory" + IceUtil::generateUUID();
444 trajController =
445 NJointTrajectoryControllerPtr::dynamicCast(robotUnit->createNJointController(
446 "NJointTrajectoryController", controllerName, config, true, true));
447
448 while (!getArmarXManager()->getIceManager()->isObjectReachable(controllerName))
449 {
450 usleep(500);
451 }
452 }
453 return trajController;
454}
455
456void
457TrajectoryControllerSubUnit::assureTrajectoryController()
458{
459 std::unique_lock lock(controllerMutex);
460
461 if (!controllerExists())
462 {
463 jointTrajController = createTrajectoryController(usedJoints, false);
464 }
465 ARMARX_CHECK_EXPRESSION(jointTrajController);
466}
467
468bool
469TrajectoryControllerSubUnit::controllerExists()
470{
471 std::unique_lock lock(controllerMutex);
472
473 auto allNJointControllers =
474 robotUnit->getNJointControllersNotNull(robotUnit->getNJointControllerNames());
475 NJointTrajectoryControllerPtr trajController;
476 for (const auto& controller : allNJointControllers)
477 {
478 trajController = NJointTrajectoryControllerPtr::dynamicCast(controller);
479 if (!trajController)
480 {
481 continue;
482 }
483 if (trajController->getName() == controllerName)
484 {
485 jointTrajController = trajController;
486 return true;
487 }
488 }
489 return false;
490}
491
492void
493TrajectoryControllerSubUnit::previewRun()
494{
495 if (controllerExists())
496 {
497 if (jointTrajController->isControllerActive())
498 {
499 std::vector<Ice::DoubleSeq> states =
500 jointTraj->getAllStates(jointTrajController->getCurrentTrajTime(), 1);
501 NameValueMap targetPositionValues;
502
503 auto dimNames = jointTraj->getDimensionNames();
504 for (size_t i = 0; i < dimNames.size(); i++)
505 {
506 const auto& jointName = dimNames.at(i);
507 if (std::find(usedJoints.begin(), usedJoints.end(), jointName) != usedJoints.end())
508 {
509 targetPositionValues[jointName] = states[i][0];
510 }
511 }
512 debugDrawer->updateRobotConfig("Preview", "previewRobot", targetPositionValues);
513 }
514 }
515}
516
517void
519{
520 ARMARX_CHECK_EXPRESSION(!robotUnit);
522 robotUnit = rUnit;
523}
524
525void
527 const std::set<std::string>& changedProperties)
528{
529 ARMARX_INFO << "Changning properties";
530 if (changedProperties.count("Kp"))
531 {
532 ARMARX_INFO << "Changning property Kp";
533 kp = getProperty<float>("Kp").getValue();
534 recreateController = true;
535 }
536
537 if (changedProperties.count("Kd"))
538 {
539 ARMARX_INFO << "Changning property Kd";
540 kd = getProperty<float>("Kd").getValue();
541 recreateController = true;
542 }
543
544 if (changedProperties.count("Ki"))
545 {
546 ARMARX_INFO << "Changning property Ki";
547 ki = getProperty<float>("Ki").getValue();
548 recreateController = true;
549 }
550}
#define M_PI
Definition MathTools.h:17
#define VAROUT(x)
constexpr T c
Property< PropertyType > getProperty(const std::string &name)
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
TopicProxyType getTopic(const std::string &name)
Returns a proxy of the specified topic.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
std::string getName() const
Retrieve name of object.
IceManagerPtr getIceManager() const
Returns the IceManager.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
The periodic task executes one thread method repeatedly using the time period specified in the constr...
The RobotUnit class manages a robot and its controllers.
Definition RobotUnit.h:192
Ice::Double getTrajEndTime(const Ice::Current &=Ice::emptyCurrent) override
void considerConstraints(bool, const Ice::Current &=Ice::emptyCurrent) override
void onInitComponent() override
Pure virtual hook for the subclass.
bool startTrajectoryPlayer(const Ice::Current &=Ice::emptyCurrent) override
Ice::Double getCurrentTime(const Ice::Current &=Ice::emptyCurrent) override
virtual void componentPropertiesUpdated(const std::set< std::string > &changedProperties) override
Implement this function if you would like to react to changes in the properties.
void loadBasePoseTraj(const TrajectoryBasePtr &basePoseTraj, const Ice::Current &=Ice::emptyCurrent) override
void onDisconnectComponent() override
Hook for subclass.
void update(const SensorAndControl &sc, const JointAndNJointControllers &c) override
bool stopTrajectoryPlayer(const Ice::Current &=Ice::emptyCurrent) override
bool pauseTrajectoryPlayer(const Ice::Current &=Ice::emptyCurrent) override
Ice::Double getEndTime(const Ice::Current &=Ice::emptyCurrent) override
void onConnectComponent() override
Pure virtual hook for the subclass.
bool resetTrajectoryPlayer(bool moveToFrameZeroPose, const Ice::Current &=Ice::emptyCurrent) override
void setIsPreview(bool, const Ice::Current &=Ice::emptyCurrent) override
void enableRobotPoseUnit(bool, const Ice::Current &=Ice::emptyCurrent) override
void setEndTime(Ice::Double, const Ice::Current &=Ice::emptyCurrent) override
bool setJointsInUse(const std::string &, bool, const Ice::Current &=Ice::emptyCurrent) override
void setLoopPlayback(bool loop, const Ice::Current &=Ice::emptyCurrent) override
void loadJointTraj(const TrajectoryBasePtr &jointTraj, const Ice::Current &=Ice::emptyCurrent) override
#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_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
This file offers overloads of toIce() and fromIce() functions for STL container types.
detail::ControlThreadOutputBufferEntry SensorAndControl
Structure used by the RobotUnit to swap lists of Joint and NJoint controllers.