DSRTController.h
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 DSController::ArmarXObjects::DSRTController
17 * @author Mahdi Khoramshahi ( m80 dot khoramshahi at gmail dot com )
18 * @date 2018
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#ifndef _ARMARX_LIB_DSController_DSRTController_H
24#define _ARMARX_LIB_DSController_DSRTController_H
25
26#include <VirtualRobot/VirtualRobot.h>
27
29
34
35#include <armarx/control/ds_controller/DSControllerInterface.h>
36
37#include "GMRDynamics.h"
38#include "MathLib.h"
39
41{
43 {
44 public:
45 Eigen::Vector3f tcpDesiredLinearVelocity;
46 Eigen::Vector3f tcpDesiredAngularError;
47 };
48
50 {
51 int K_gmm_;
52 int dim_;
53 std::vector<double> Priors_;
54 std::vector<double> Mu_;
55 std::vector<double> Sigma_;
56 std::vector<double> attractor_;
57 double dt_;
58 };
59
61 {
62 public:
64 {
65 }
66
67 GMMMotionGen(const std::string& fileName)
68 {
70 }
71
74 Eigen::Vector3f desiredDefaultTarget;
75 float scaling;
76
77 float belief;
78 float v_max;
79
80 void
81 getGMMParamsFromJsonFile(const std::string& fileName)
82 {
83 std::ifstream infile{fileName};
84 std::string objDefs = {std::istreambuf_iterator<char>(infile),
85 std::istreambuf_iterator<char>()};
86 JSONObjectPtr json = new JSONObject();
87 json->fromString(objDefs);
88
89
90 gmmParas.K_gmm_ = json->getInt("K");
91 gmmParas.dim_ = json->getInt("dim");
92 json->getArray<double>("Priors", gmmParas.Priors_);
93 json->getArray<double>("Mu", gmmParas.Mu_);
94 json->getArray<double>("attractor", gmmParas.attractor_);
95 json->getArray<double>("Sigma", gmmParas.Sigma_);
96
97 scaling = json->getDouble("Scaling");
98 belief = json->getDouble("InitBelief");
99 belief = 0;
100 v_max = json->getDouble("MaxVelocity");
101
102 gmm.reset(new GMRDynamics(gmmParas.K_gmm_,
103 gmmParas.dim_,
104 gmmParas.dt_,
105 gmmParas.Priors_,
106 gmmParas.Mu_,
107 gmmParas.Sigma_));
108 gmm->initGMR(0, 2, 3, 5);
109
110 if (gmmParas.attractor_.size() < 3)
111 {
112 ARMARX_ERROR << "attractor in json file should be 6 dimension vector ... ";
113 }
114
115 for (int i = 0; i < 3; ++i)
116 {
117 desiredDefaultTarget(i) = gmmParas.attractor_.at(i);
118 }
119 }
120
121 void
122 updateDesiredVelocity(const Eigen::Vector3f& currentPositionInMeter,
123 float positionErrorToleranceInMeter)
124 {
125 Eigen::Vector3f PositionError = currentPositionInMeter - desiredDefaultTarget;
126 if (PositionError.norm() < positionErrorToleranceInMeter)
127 {
128 PositionError.setZero();
129 }
130
131 MathLib::Vector position_error;
132 position_error.Resize(3);
133
134 for (int i = 0; i < 3; ++i)
135 {
136 position_error(i) = PositionError(i);
137 }
138
139 MathLib::Vector desired_vel;
140 desired_vel.Resize(3);
141 desired_vel = gmm->getVelocity(position_error);
142
143 Eigen::Vector3f tcpDesiredLinearVelocity;
144 tcpDesiredLinearVelocity << desired_vel(0), desired_vel(1), desired_vel(2);
145
146 currentDesiredVelocity = scaling * tcpDesiredLinearVelocity;
147
148
149 float lenVec = tcpDesiredLinearVelocity.norm();
150 if (std::isnan(lenVec))
151 {
152 tcpDesiredLinearVelocity.setZero();
153 }
154
155 if (lenVec > v_max)
156 {
157 tcpDesiredLinearVelocity = (v_max / lenVec) * tcpDesiredLinearVelocity;
158 }
159 }
160
161 Eigen::Vector3f currentDesiredVelocity;
162 };
163
165
167 {
168 public:
170 float epsilon;
171
173 {
174 }
175
176 DSAdaptor(std::vector<GMMMotionGenPtr> gmmMotionGenList, float epsilon)
177 {
178 task0_belief = 1;
179 this->gmmMotionGenList = gmmMotionGenList;
180
181 ARMARX_INFO << "epsilon: " << epsilon;
182 this->epsilon = epsilon;
183
184 totalDesiredVelocity.setZero();
185 }
186
187 Eigen::Vector3f totalDesiredVelocity;
188 std::vector<GMMMotionGenPtr> gmmMotionGenList;
189
190 void
191 updateDesiredVelocity(const Eigen::Vector3f& currentPositionInMeter,
192 float positionErrorToleranceInMeter)
193 {
194 totalDesiredVelocity.setZero();
195 for (size_t i = 0; i < gmmMotionGenList.size(); ++i)
196 {
197 gmmMotionGenList[i]->updateDesiredVelocity(currentPositionInMeter,
198 positionErrorToleranceInMeter);
200 gmmMotionGenList[i]->belief * gmmMotionGenList[i]->currentDesiredVelocity;
201 }
202 }
203
204 void
205 updateBelief(const Eigen::Vector3f& realVelocity)
206 {
207 std::vector<float> beliefUpdate;
208 beliefUpdate.resize(gmmMotionGenList.size());
209
210 float nullInnerSimilarity = 0;
211 for (size_t i = 0; i < gmmMotionGenList.size(); ++i)
212 {
213
214 GMMMotionGenPtr currentGMM = gmmMotionGenList[i];
215
216 float belief = currentGMM->belief;
217 Eigen::Vector3f OtherTasks =
218 totalDesiredVelocity - belief * currentGMM->currentDesiredVelocity;
219 float innerSimilarity = 2 * OtherTasks.dot(currentGMM->currentDesiredVelocity);
220 float outerDisSimilarity =
221 (realVelocity - currentGMM->currentDesiredVelocity).squaredNorm();
222
223 if (innerSimilarity > nullInnerSimilarity)
224 {
225 nullInnerSimilarity = innerSimilarity;
226 }
227
228 beliefUpdate[i] = -outerDisSimilarity - innerSimilarity;
229 }
230
231
232 float nullOuterSimilarity = realVelocity.squaredNorm();
233 float zeroTaskRawBeliefUpdate = -nullInnerSimilarity - nullOuterSimilarity;
234
235 if (zeroTaskRawBeliefUpdate < 0.2)
236 {
237 zeroTaskRawBeliefUpdate -= 1000;
238 }
239
240
241 beliefUpdate.insert(beliefUpdate.begin(), zeroTaskRawBeliefUpdate);
242
243 WinnerTakeAll(beliefUpdate);
244 task0_belief += epsilon * beliefUpdate[0];
245 if (task0_belief > 1)
246 {
247 task0_belief = 1;
248 }
249 else if (task0_belief < 0)
250 {
251 task0_belief = 0;
252 }
253
254 float beliefSum = task0_belief;
255
256 for (size_t i = 0; i < gmmMotionGenList.size(); ++i)
257 {
258 gmmMotionGenList[i]->belief += epsilon * beliefUpdate[i + 1];
259
260
261 if (gmmMotionGenList[i]->belief > 1)
262 {
263 gmmMotionGenList[i]->belief = 1;
264 }
265 else if (gmmMotionGenList[i]->belief < 0)
266 {
267 gmmMotionGenList[i]->belief = 0;
268 }
269
270 beliefSum += gmmMotionGenList[i]->belief;
271 }
272
273 for (size_t i = 0; i < gmmMotionGenList.size(); ++i)
274 {
275 gmmMotionGenList[i]->belief /= beliefSum;
276 }
277
278 task0_belief /= beliefSum;
279 }
280
281 private:
282 void
283 WinnerTakeAll(std::vector<float>& UpdateBeliefs_)
284 {
285 // std::fill(UpdateBeliefs_.begin(), UpdateBeliefs_.end(), 0);
286
287 size_t winner_index = 0;
288
289 for (size_t i = 1; i < UpdateBeliefs_.size(); i++)
290 {
291 if (UpdateBeliefs_[i] > UpdateBeliefs_[winner_index])
292 {
293 winner_index = i;
294 }
295 }
296
297 float winner_belief = task0_belief;
298
299 if (winner_index != 0)
300 {
301 winner_belief = gmmMotionGenList[winner_index - 1]->belief;
302 }
303
304 if (winner_belief == 1)
305 {
306 return;
307 }
308
309 int runnerUp_index = 0;
310
311 if (winner_index == 0)
312 {
313 runnerUp_index = 1;
314 }
315
316 for (size_t i = 0; i < UpdateBeliefs_.size(); i++)
317 {
318 if (i == winner_index)
319 {
320 continue;
321 }
322
323 if (UpdateBeliefs_[i] > UpdateBeliefs_[runnerUp_index])
324 {
325 runnerUp_index = i;
326 }
327 }
328
329 float offset = 0.5 * (UpdateBeliefs_[winner_index] + UpdateBeliefs_[runnerUp_index]);
330
331 for (size_t i = 0; i < UpdateBeliefs_.size(); i++)
332 {
333 UpdateBeliefs_[i] -= offset;
334 }
335
336 float UpdateSum = 0;
337
338 for (size_t i = 0; i < UpdateBeliefs_.size(); i++)
339 {
340 float belief = task0_belief;
341 if (i != 0)
342 {
343 belief = gmmMotionGenList[i - 1]->belief;
344 }
345
346 if (belief != 0 || UpdateBeliefs_[i] > 0)
347 {
348 UpdateSum += UpdateBeliefs_[i];
349 }
350 }
351
352 UpdateBeliefs_[winner_index] -= UpdateSum;
353 }
354 };
355
357
358 /**
359 * @defgroup Library-DSRTController DSRTController
360 * @ingroup armarx_control
361 * A description of the library DSRTController.
362 *
363 * @class DSRTController
364 * @ingroup Library-DSRTController
365 * @brief Brief description of class DSRTController.
366 *
367 * Detailed description of class DSRTController.
368 */
370 public NJointControllerWithTripleBuffer<DSRTControllerControlData>,
372 {
373
374 // ManagedIceObject interface
375 protected:
378
379
380 void controllerRun();
381
382
383 // NJointControllerInterface interface
384 public:
385 using ConfigPtrT = DSControllerConfigPtr;
386
387 DSRTController(const RobotUnitPtr& robotUnit,
388 const NJointControllerConfigPtr& config,
390
391 std::string
392 getClassName(const Ice::Current&) const
393 {
394 return "DSRTController";
395 }
396
397 // NJointController interface
398 void rtRun(const IceUtil::Time& sensorValuesTimestamp,
399 const IceUtil::Time& timeSinceLastIteration);
400
401 private:
402 // PeriodicTask<DSRTController>::pointer_type controllerTask;
403
404 struct DSRTControllerSensorData
405 {
406 Eigen::Matrix4f tcpPose;
407 double currentTime;
408
409 Eigen::Vector3f linearVelocity;
410 };
411
412 TripleBuffer<DSRTControllerSensorData> controllerSensorData;
413
414 struct DSRTDebugInfo
415 {
416 StringFloatDictionary desired_torques;
417 float desiredForce_x;
418 float desiredForce_y;
419 float desiredForce_z;
420 float tcpDesiredTorque_x;
421 float tcpDesiredTorque_y;
422 float tcpDesiredTorque_z;
423
424 float tcpDesiredAngularError_x;
425 float tcpDesiredAngularError_y;
426 float tcpDesiredAngularError_z;
427
428 float currentTCPAngularVelocity_x;
429 float currentTCPAngularVelocity_y;
430 float currentTCPAngularVelocity_z;
431
432 float currentTCPLinearVelocity_x;
433 float currentTCPLinearVelocity_y;
434 float currentTCPLinearVelocity_z;
435
436 float belief0;
437 float belief1;
438 float belief2;
439 };
440
441 TripleBuffer<DSRTDebugInfo> debugDataInfo;
442
443 std::vector<const SensorValue1DoFActuatorTorque*> torqueSensors;
444 std::vector<const SensorValue1DoFGravityTorque*> gravityTorqueSensors;
445 std::vector<const SensorValue1DoFActuatorVelocity*> velocitySensors;
446 std::vector<const SensorValue1DoFActuatorPosition*> positionSensors;
447
448 std::vector<ControlTarget1DoFActuatorTorque*> targets;
449
450
451 VirtualRobot::RobotNodePtr tcp;
452
453 VirtualRobot::DifferentialIKPtr ik;
454 Eigen::MatrixXf jacobip;
455 Eigen::MatrixXf jacobio;
456
457 Eigen::Vector3f desiredPosition;
458
459 Eigen::Quaternionf desiredQuaternion;
460 Eigen::Vector3f oldPosition;
461
462 Eigen::Matrix3f oldOrientation;
463
464 Eigen::Vector3f currentTCPLinearVelocity_filtered;
465 Eigen::Vector3f currentTCPAngularVelocity_filtered;
466
467 float filterTimeConstant;
468
469 std::vector<std::string> jointNames;
470
471 float posiKp;
472 float v_max;
473 float posiDamping;
474 float torqueLimit;
475
476 float oriKp;
477 float oriDamping;
478
479 float nullspaceKp;
480 float nullspaceDamping;
481
482 Eigen::VectorXf qnullspace;
483
484 std::vector<GMMMotionGenPtr> gmmMotionGenList;
485
486 DSAdaptorPtr dsAdaptorPtr;
487
488 float positionErrorTolerance;
489
490
491 // NJointController interface
492 protected:
493 void onPublish(const SensorAndControl&,
496
497 // NJointController interface
498 protected:
501 };
502
503} // namespace armarx::control::ds_controller
504
505#endif
boost::shared_ptr< GMRDynamics > GMMPtr
Definition GMRDynamics.h:66
The JSONObject class is used to represent and (de)serialize JSON objects.
Definition JSONObject.h:44
NJointControllerWithTripleBuffer(const DSRTControllerControlData &initialCommands=DSRTControllerControlData())
A simple triple buffer for lockfree comunication between a single writer and a single reader.
DSAdaptor(std::vector< GMMMotionGenPtr > gmmMotionGenList, float epsilon)
void updateBelief(const Eigen::Vector3f &realVelocity)
std::vector< GMMMotionGenPtr > gmmMotionGenList
void updateDesiredVelocity(const Eigen::Vector3f &currentPositionInMeter, float positionErrorToleranceInMeter)
void rtPreActivateController()
This function is called before the controller is activated.
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
TODO make protected and use attorneys.
void rtPostDeactivateController()
This function is called after the controller is deactivated.
std::string getClassName(const Ice::Current &) const
DSRTController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &)
GMMMotionGen(const std::string &fileName)
void getGMMParamsFromJsonFile(const std::string &fileName)
void updateDesiredVelocity(const Eigen::Vector3f &currentPositionInMeter, float positionErrorToleranceInMeter)
Brief description of class targets.
Definition targets.h:39
#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
Quaternion< float, 0 > Quaternionf
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
boost::shared_ptr< GMMMotionGen > GMMMotionGenPtr
boost::shared_ptr< DSAdaptor > DSAdaptorPtr
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
IceInternal::Handle< JSONObject > JSONObjectPtr
Definition JSONObject.h:34
IceUtil::Handle< class RobotUnit > RobotUnitPtr
Definition FTSensor.h:34
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl