NJointBimanualObjLevelVelController.cpp
Go to the documentation of this file.
2
3#include <VirtualRobot/MathTools.h>
4#include <VirtualRobot/VirtualRobot.h>
5
8
9// Simox
10#include <VirtualRobot/IK/DifferentialIK.h>
11#include <VirtualRobot/Nodes/RobotNode.h>
12#include <VirtualRobot/Robot.h>
13#include <VirtualRobot/RobotNodeSet.h>
14
15// armarx
24
26{
27 NJointControllerRegistration<NJointBimanualObjLevelVelController>
29 "NJointBimanualObjLevelVelController");
30
32 const RobotUnitPtr& robUnit,
33 const armarx::NJointControllerConfigPtr& config,
35 {
36 ARMARX_INFO << "Preparing ... bimanual ";
37 ARMARX_INFO << "I am here";
38
40 cfg = NJointBimanualObjLevelVelControllerConfigPtr::dynamicCast(config);
41 // ARMARX_CHECK_EXPRESSION(prov);
42 // RobotUnitPtr robotUnit = RobotUnitPtr::dynamicCast(prov);
43 // ARMARX_CHECK_EXPRESSION(robotUnit);
44 leftRNS = rtGetRobot()->getRobotNodeSet("LeftArm");
45
46 for (size_t i = 0; i < leftRNS->getSize(); ++i)
47 {
48 std::string jointName = leftRNS->getNode(i)->getName();
49 leftJointNames.push_back(jointName);
50 ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
51 const SensorValueBase* sv = useSensorValue(jointName);
52 leftTargets.push_back(ct->asA<ControlTarget1DoFActuatorVelocity>());
53 const SensorValue1DoFActuatorVelocity* velocitySensor =
54 sv->asA<SensorValue1DoFActuatorVelocity>();
55 const SensorValue1DoFActuatorPosition* positionSensor =
56 sv->asA<SensorValue1DoFActuatorPosition>();
57
58 if (!velocitySensor)
59 {
60 ARMARX_WARNING << "No velocitySensor available for " << jointName;
61 }
62 if (!positionSensor)
63 {
64 ARMARX_WARNING << "No positionSensor available for " << jointName;
65 }
66
67
68 leftVelocitySensors.push_back(velocitySensor);
69 leftPositionSensors.push_back(positionSensor);
70 };
71
72 rightRNS = rtGetRobot()->getRobotNodeSet("RightArm");
73
74 for (size_t i = 0; i < rightRNS->getSize(); ++i)
75 {
76 std::string jointName = rightRNS->getNode(i)->getName();
77 rightJointNames.push_back(jointName);
78 ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
79 const SensorValueBase* sv = useSensorValue(jointName);
80 rightTargets.push_back(ct->asA<ControlTarget1DoFActuatorVelocity>());
81
82 const SensorValue1DoFActuatorVelocity* velocitySensor =
83 sv->asA<SensorValue1DoFActuatorVelocity>();
84 const SensorValue1DoFActuatorPosition* positionSensor =
85 sv->asA<SensorValue1DoFActuatorPosition>();
86
87 if (!velocitySensor)
88 {
89 ARMARX_WARNING << "No velocitySensor available for " << jointName;
90 }
91 if (!positionSensor)
92 {
93 ARMARX_WARNING << "No positionSensor available for " << jointName;
94 }
95
96 rightVelocitySensors.push_back(velocitySensor);
97 rightPositionSensors.push_back(positionSensor);
98 };
99
100 leftIK.reset(new VirtualRobot::DifferentialIK(
101 leftRNS, leftRNS->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
102 rightIK.reset(new VirtualRobot::DifferentialIK(rightRNS,
103 rightRNS->getRobot()->getRootNode(),
104 VirtualRobot::JacobiProvider::eSVDDamped));
105
106
107 leftTCPController.reset(new CartesianVelocityController(leftRNS, leftRNS->getTCP()));
108 rightTCPController.reset(new CartesianVelocityController(rightRNS, rightRNS->getTCP()));
109
110 double phaseL = 10;
111 double phaseK = 10;
112 double phaseDist0 = 50;
113 double phaseDist1 = 10;
114 double phaseKpPos = 1;
115 double phaseKpOri = 0.1;
116 double posToOriRatio = 10;
117 tsvmp::TaskSpaceDMPControllerConfig taskSpaceDMPConfig;
118 taskSpaceDMPConfig.motionTimeDuration = cfg->timeDuration;
119 taskSpaceDMPConfig.DMPKernelSize = cfg->kernelSize;
120 taskSpaceDMPConfig.DMPMode = cfg->dmpMode;
121 taskSpaceDMPConfig.DMPStyle = cfg->dmpType;
122 taskSpaceDMPConfig.DMPAmplitude = 1.0;
123 taskSpaceDMPConfig.phaseStopParas.Dori = 0;
124 taskSpaceDMPConfig.phaseStopParas.Dpos = 0;
125 taskSpaceDMPConfig.phaseStopParas.goDist = phaseDist0;
126 taskSpaceDMPConfig.phaseStopParas.backDist = phaseDist1;
127 taskSpaceDMPConfig.phaseStopParas.Kpos = phaseKpPos;
128 taskSpaceDMPConfig.phaseStopParas.Kori = phaseKpOri;
129 taskSpaceDMPConfig.phaseStopParas.mm2radi = posToOriRatio;
130 taskSpaceDMPConfig.phaseStopParas.maxValue = phaseL;
131 taskSpaceDMPConfig.phaseStopParas.slop = phaseK;
132
133
134 objectDMP.reset(new tsvmp::TaskSpaceDMPController("boxDMP", taskSpaceDMPConfig, false));
135 ARMARX_IMPORTANT << "dmp finished";
136
137 tcpLeft = leftRNS->getTCP();
138 tcpRight = rightRNS->getTCP();
139
140 //initialize control parameters
141 KpImpedance.setZero(cfg->KpImpedance.size());
142 ARMARX_CHECK_EQUAL(cfg->KpImpedance.size(), 6);
143
144 for (int i = 0; i < KpImpedance.size(); ++i)
145 {
146 KpImpedance(i) = cfg->KpImpedance.at(i);
147 }
148
149 KdImpedance.setZero(cfg->KdImpedance.size());
150 ARMARX_CHECK_EQUAL(cfg->KdImpedance.size(), 6);
151
152 for (int i = 0; i < KdImpedance.size(); ++i)
153 {
154 KdImpedance(i) = cfg->KdImpedance.at(i);
155 }
156
157 Inferface2rtData initInt2rtData;
158 initInt2rtData.KpImpedance = KpImpedance;
159 initInt2rtData.KdImpedance = KdImpedance;
160 interface2rtBuffer.reinitAllBuffers(initInt2rtData);
161
162 leftDesiredJointValues.resize(leftTargets.size());
163 ARMARX_CHECK_EQUAL(cfg->leftDesiredJointValues.size(), leftTargets.size());
164
165 for (size_t i = 0; i < leftTargets.size(); ++i)
166 {
167 leftDesiredJointValues(i) = cfg->leftDesiredJointValues.at(i);
168 }
169
170 rightDesiredJointValues.resize(rightTargets.size());
171 ARMARX_CHECK_EQUAL(cfg->rightDesiredJointValues.size(), rightTargets.size());
172
173 for (size_t i = 0; i < rightTargets.size(); ++i)
174 {
175 rightDesiredJointValues(i) = cfg->rightDesiredJointValues.at(i);
176 }
177
178 virtualPose = Eigen::Matrix4f::Identity();
179 ARMARX_INFO << "got controller params";
180
181 rt2ControlData initSensorData;
182 initSensorData.deltaT = 0;
183 initSensorData.currentTime = 0;
184 initSensorData.currentPose = leftRNS->getTCP()->getPoseInRootFrame();
185 initSensorData.currentTwist.setZero();
186 rt2ControlBuffer.reinitAllBuffers(initSensorData);
187
188
189 ControlInterfaceData initInterfaceData;
190 initInterfaceData.currentLeftPose = tcpLeft->getPoseInRootFrame();
191 initInterfaceData.currentRightPose = tcpRight->getPoseInRootFrame();
192 initInterfaceData.currentObjPose = leftRNS->getTCP()->getPoseInRootFrame();
193 initInterfaceData.currentObjVel.setZero();
194 controlInterfaceBuffer.reinitAllBuffers(initInterfaceData);
195
196
197 leftInitialPose = tcpLeft->getPoseInRootFrame();
198 rightInitialPose = tcpRight->getPoseInRootFrame();
199 leftInitialPose.block<3, 1>(0, 3) = leftInitialPose.block<3, 1>(0, 3);
200 rightInitialPose.block<3, 1>(0, 3) = rightInitialPose.block<3, 1>(0, 3);
201
202 // TODO the following is only predefined for balance ball
203 fixedLeftRightRotOffset = Eigen::Matrix3f::Identity();
204
205 Eigen::Matrix4f rightLeveledRotation =
206 VirtualRobot::MathTools::quat2eigen4f(0.5, -0.5, -0.5, -0.5);
207 Eigen::Matrix4f leftLeveledRotation =
208 VirtualRobot::MathTools::quat2eigen4f(0.5, 0.5, 0.5, -0.5);
209 fixedLeftRightRotOffset = leftLeveledRotation.block<3, 3>(0, 0).transpose() *
210 rightLeveledRotation.block<3, 3>(0, 0);
211
212
213 boxInitialPose = leftInitialPose;
214 boxInitialPose(0, 3) = (leftInitialPose(0, 3) + rightInitialPose(0, 3)) / 2;
215 boxInitialPose(1, 3) = (leftInitialPose(1, 3) + rightInitialPose(1, 3)) / 2;
216 boxInitialPose(2, 3) = (leftInitialPose(2, 3) + rightInitialPose(2, 3)) / 2;
217
219 initData.boxPose = boxInitialPose;
220 reinitTripleBuffer(initData);
221
222 dmpGoal = boxInitialPose;
223
224 firstLoop = true;
225 ARMARX_INFO << "left initial pose: \n"
226 << leftInitialPose << "\n right initial pose: \n"
227 << rightInitialPose;
228 dmpStarted = false;
229 objCom2TCPLeftInObjFrame.setZero();
230 objCom2TCPRightInObjFrame.setZero();
231 }
232
233 void
235 const Ice::Current&)
236 {
237 objectDMP->setWeights(weights);
238 }
239
240 DoubleSeqSeq
242 {
243 DMP::DVec2d res = objectDMP->getWeights();
244 DoubleSeqSeq resvec;
245 for (size_t i = 0; i < res.size(); ++i)
246 {
247 std::vector<double> cvec;
248 for (size_t j = 0; j < res[i].size(); ++j)
249 {
250 cvec.push_back(res[i][j]);
251 }
252 resvec.push_back(cvec);
253 }
254
255 return resvec;
256 }
257
258 void
260 const Ice::Current&)
261 {
262 objectDMP->setRotWeights(weights);
263 }
264
265 DoubleSeqSeq
267 {
268 DMP::DVec2d res = objectDMP->getRotWeights();
269 DoubleSeqSeq resvec;
270 for (size_t i = 0; i < res.size(); ++i)
271 {
272 std::vector<double> cvec;
273 for (size_t j = 0; j < res[i].size(); ++j)
274 {
275 cvec.push_back(res[i][j]);
276 }
277 resvec.push_back(cvec);
278 }
279
280 return resvec;
281 }
282
283 void
285 {
286 Eigen::Matrix4f boxInitPose = Eigen::Matrix4f::Identity();
287 Eigen::Matrix4f leftPose = tcpLeft->getPoseInRootFrame();
288 Eigen::Matrix4f rightPose = tcpRight->getPoseInRootFrame();
289 leftPose.block<3, 1>(0, 3) = leftPose.block<3, 1>(0, 3);
290 rightPose.block<3, 1>(0, 3) = rightPose.block<3, 1>(0, 3);
291 boxInitPose.block<3, 1>(0, 3) =
292 0.5 * (leftPose.block<3, 1>(0, 3) + rightPose.block<3, 1>(0, 3));
293 boxInitPose.block<3, 3>(0, 0) = leftPose.block<3, 3>(0, 0);
294
296 initData.boxPose = boxInitPose;
297 reinitTripleBuffer(initData);
298 }
299
300 std::string
302 {
303 return "NJointBimanualObjLevelVelController";
304 }
305
306 void
308 {
309 if (!rt2ControlBuffer.updateReadBuffer() || !dmpStarted)
310 {
311 return;
312 }
313
314 double deltaT = rt2ControlBuffer.getReadBuffer().deltaT;
315 Eigen::Matrix4f currentPose = rt2ControlBuffer.getReadBuffer().currentPose;
316 Eigen::VectorXf currentTwist = rt2ControlBuffer.getReadBuffer().currentTwist;
317
318 if (objectDMP->canVal < 0)
319 {
320 finished = true;
321 dmpStarted = false;
323 getWriterControlStruct().boxPose = dmpGoal;
325 }
326 else
327 {
328 objectDMP->flow(deltaT, currentPose, currentTwist);
329 // VirtualRobot::MathTools::Quaternion quat = VirtualRobot::MathTools::eigen4f2quat(objectDMP->getTargetPoseMat());
331 getWriterControlStruct().boxPose = objectDMP->getTargetPoseMat();
333 }
334 }
335
336 Eigen::VectorXf
337 NJointBimanualObjLevelVelController::calcIK(VirtualRobot::DifferentialIKPtr ik,
338 const Eigen::MatrixXf& jacobi,
339 const Eigen::VectorXf& cartesianVel,
340 const Eigen::VectorXf& nullspaceVel)
341 {
342 Eigen::FullPivLU<Eigen::MatrixXf> lu_decomp(jacobi);
343
344 Eigen::MatrixXf nullspace = lu_decomp.kernel();
345 Eigen::VectorXf nsv = Eigen::VectorXf::Zero(nullspace.rows());
346 for (int i = 0; i < nullspace.cols(); i++)
347 {
348 float squaredNorm = nullspace.col(i).squaredNorm();
349 // Prevent division by zero
350 if (squaredNorm > 1.0e-32f)
351 {
352 nsv += nullspace.col(i) * nullspace.col(i).dot(nullspaceVel) /
353 nullspace.col(i).squaredNorm();
354 }
355 }
356
357 Eigen::MatrixXf inv = ik->computePseudoInverseJacobianMatrix(
358 jacobi, ik->getJacobiRegularization(VirtualRobot::IKSolver::CartesianSelection::All));
359 Eigen::VectorXf jointVel = inv * cartesianVel;
360 return jointVel;
361 }
362
363 void
364 NJointBimanualObjLevelVelController::rtRun(const IceUtil::Time& sensorValuesTimestamp,
365 const IceUtil::Time& timeSinceLastIteration)
366 {
367 Eigen::Matrix4f currentLeftPose = tcpLeft->getPoseInRootFrame();
368 Eigen::Matrix4f currentRightPose = tcpRight->getPoseInRootFrame();
369
370 double deltaT = timeSinceLastIteration.toSecondsDouble();
371
372 if (firstLoop)
373 {
374 Eigen::Matrix4f leftPose = tcpLeft->getPoseInRootFrame();
375 Eigen::Matrix4f rightPose = tcpRight->getPoseInRootFrame();
376
377 leftPose.block<3, 1>(0, 3) = leftPose.block<3, 1>(0, 3);
378 rightPose.block<3, 1>(0, 3) = rightPose.block<3, 1>(0, 3);
379
380 virtualPose.block<3, 1>(0, 3) =
381 0.5 * (leftPose.block<3, 1>(0, 3) + rightPose.block<3, 1>(0, 3));
382 virtualPose.block<3, 3>(0, 0) = leftPose.block<3, 3>(0, 0);
383 // fixedLeftRightRotOffset = virtualPose.block<3, 3>(0, 0).transpose() * rightPose.block<3, 3>(0, 0);
384
385 Eigen::Vector3f objCom2TCPLeftInGlobal =
386 leftPose.block<3, 1>(0, 3) - virtualPose.block<3, 1>(0, 3);
387 Eigen::Vector3f objCom2TCPRightInGlobal =
388 rightPose.block<3, 1>(0, 3) - virtualPose.block<3, 1>(0, 3);
389
390 objCom2TCPLeftInObjFrame =
391 virtualPose.block<3, 3>(0, 0).transpose() * objCom2TCPLeftInGlobal;
392 objCom2TCPRightInObjFrame =
393 virtualPose.block<3, 3>(0, 0).transpose() * objCom2TCPRightInGlobal;
394 firstLoop = false;
395 }
396
397 // --------------------------------------------- get control parameters ---------------------------------------
398 KpImpedance = interface2rtBuffer.getUpToDateReadBuffer().KpImpedance;
399 KdImpedance = interface2rtBuffer.getUpToDateReadBuffer().KdImpedance;
400
401 // --------------------------------------------- grasp matrix ---------------------------------------------
402
403 Eigen::MatrixXf graspMatrix;
404 graspMatrix.setZero(6, 12);
405 graspMatrix.block<3, 3>(0, 0) = Eigen::MatrixXf::Identity(3, 3);
406 graspMatrix.block<3, 3>(0, 6) = Eigen::MatrixXf::Identity(3, 3);
407 Eigen::Vector3f rvec = virtualPose.block<3, 3>(0, 0) * objCom2TCPLeftInObjFrame;
408 graspMatrix.block<3, 3>(3, 0) = skew(rvec);
409
410 rvec = virtualPose.block<3, 3>(0, 0) * objCom2TCPRightInObjFrame;
411 graspMatrix.block<3, 3>(3, 6) = skew(rvec);
412
413 float lambda = 1;
414 Eigen::MatrixXf pinvGraspMatrixT =
415 leftIK->computePseudoInverseJacobianMatrix(graspMatrix.transpose(), lambda);
416
417 // ---------------------------------------------- object pose ----------------------------------------------
418 Eigen::Matrix4f boxCurrentPose = currentLeftPose;
419 boxCurrentPose.block<3, 1>(0, 3) =
420 0.5 * (currentLeftPose.block<3, 1>(0, 3) + currentRightPose.block<3, 1>(0, 3));
421 Eigen::VectorXf boxCurrentTwist;
422 boxCurrentTwist.setZero(6);
423
424 // -------------------------------------- get Jacobian matrix and qpos -------------------------------------
425 Eigen::MatrixXf I = Eigen::MatrixXf::Identity(leftTargets.size(), leftTargets.size());
426 // Jacobian matrices
427 Eigen::MatrixXf jacobiL =
428 leftIK->getJacobianMatrix(tcpLeft, VirtualRobot::IKSolver::CartesianSelection::All);
429 Eigen::MatrixXf jacobiR =
430 rightIK->getJacobianMatrix(tcpRight, VirtualRobot::IKSolver::CartesianSelection::All);
431
432 // qpos, qvel
433 Eigen::VectorXf leftqpos;
434 Eigen::VectorXf leftqvel;
435 leftqpos.resize(leftPositionSensors.size());
436 leftqvel.resize(leftVelocitySensors.size());
437 for (size_t i = 0; i < leftVelocitySensors.size(); ++i)
438 {
439 leftqpos(i) = leftPositionSensors[i]->position;
440 leftqvel(i) = leftVelocitySensors[i]->velocity;
441 }
442
443 Eigen::VectorXf rightqpos;
444 Eigen::VectorXf rightqvel;
445 rightqpos.resize(rightPositionSensors.size());
446 rightqvel.resize(rightVelocitySensors.size());
447
448 for (size_t i = 0; i < rightVelocitySensors.size(); ++i)
449 {
450 rightqpos(i) = rightPositionSensors[i]->position;
451 rightqvel(i) = rightVelocitySensors[i]->velocity;
452 }
453
454 // -------------------------------------- compute TCP and object velocity -------------------------------------
455 Eigen::VectorXf currentLeftTwist = jacobiL * leftqvel;
456 Eigen::VectorXf currentRightTwist = jacobiR * rightqvel;
457
458 Eigen::VectorXf currentTwist(12);
459 currentTwist << currentLeftTwist, currentRightTwist;
460 boxCurrentTwist = pinvGraspMatrixT * currentTwist;
461
462 rt2ControlBuffer.getWriteBuffer().currentPose = boxCurrentPose;
463 rt2ControlBuffer.getWriteBuffer().currentTwist = boxCurrentTwist;
464 rt2ControlBuffer.getWriteBuffer().deltaT = deltaT;
465 rt2ControlBuffer.getWriteBuffer().currentTime += deltaT;
466 rt2ControlBuffer.commitWrite();
467
468 // pass sensor value to statechart
469 controlInterfaceBuffer.getWriteBuffer().currentObjPose = boxCurrentPose;
470 controlInterfaceBuffer.getWriteBuffer().currentObjVel = boxCurrentTwist.head<3>();
471 controlInterfaceBuffer.getWriteBuffer().currentLeftPose = currentLeftPose;
472 controlInterfaceBuffer.getWriteBuffer().currentRightPose = currentRightPose;
473 controlInterfaceBuffer.commitWrite();
474
475
476 // --------------------------------------------- get MP target ---------------------------------------------
477 virtualPose = rtGetControlStruct().boxPose;
478 // Eigen::VectorXf boxTwist = rtGetControlStruct().boxTwist;
479
480 // --------------------------------------------- convert to tcp pose ---------------------------------------------
481 Eigen::Matrix4f tcpTargetPoseLeft = virtualPose;
482 Eigen::Matrix4f tcpTargetPoseRight = virtualPose;
483
484 tcpTargetPoseRight.block<3, 3>(0, 0) =
485 virtualPose.block<3, 3>(0, 0) * fixedLeftRightRotOffset;
486 tcpTargetPoseLeft.block<3, 1>(0, 3) +=
487 virtualPose.block<3, 3>(0, 0) * objCom2TCPLeftInObjFrame;
488 tcpTargetPoseRight.block<3, 1>(0, 3) +=
489 virtualPose.block<3, 3>(0, 0) * objCom2TCPRightInObjFrame;
490
491 // --------------------------------------------- Velocity control ---------------------------------------------
492
493 Eigen::Matrix3f diffMatLeft =
494 tcpTargetPoseLeft.block<3, 3>(0, 0) * currentLeftPose.block<3, 3>(0, 0).inverse();
495 Eigen::Vector3f errorRPYLeft = VirtualRobot::MathTools::eigen3f2rpy(diffMatLeft);
496 Eigen::Matrix3f diffMatRight =
497 tcpTargetPoseRight.block<3, 3>(0, 0) * currentRightPose.block<3, 3>(0, 0).inverse();
498 Eigen::Vector3f errorRPYRight = VirtualRobot::MathTools::eigen3f2rpy(diffMatRight);
499
500 Eigen::Vector6f leftTargetVel, rightTargetVel;
501 for (size_t i = 0; i < 3; ++i)
502 {
503 leftTargetVel(i) = KpImpedance(i) * (tcpTargetPoseLeft(i, 3) - currentLeftPose(i, 3)) +
504 KdImpedance(i) * (-currentLeftTwist(i));
505 leftTargetVel(i + 3) = KpImpedance(i + 3) * errorRPYLeft(i) +
506 KdImpedance(i + 3) * (-currentLeftTwist(i + 3));
507 rightTargetVel(i) =
508 KpImpedance(i) * (tcpTargetPoseRight(i, 3) - currentRightPose(i, 3)) +
509 KdImpedance(i) * (-currentRightTwist(i));
510 rightTargetVel(i + 3) = KpImpedance(i + 3) * errorRPYRight(i) +
511 KdImpedance(i + 3) * (-currentRightTwist(i + 3));
512 }
513
514
515 Eigen::VectorXf leftJointNullSpaceVel =
516 cfg->knull * (leftDesiredJointValues - leftqpos) - cfg->dnull * leftqvel +
517 cfg->jointLimitAvoidanceKp * leftTCPController->calculateJointLimitAvoidance();
518 Eigen::VectorXf leftJointTargetVel =
519 calcIK(leftIK, jacobiL, leftTargetVel, leftJointNullSpaceVel);
520
521
522 Eigen::VectorXf rightJointNullSpaceVel =
523 cfg->knull * (rightDesiredJointValues - rightqpos) - cfg->dnull * rightqvel +
524 cfg->jointLimitAvoidanceKp * rightTCPController->calculateJointLimitAvoidance();
525 Eigen::VectorXf rightJointTargetVel =
526 calcIK(rightIK, jacobiR, rightTargetVel, rightJointNullSpaceVel);
527
528 for (size_t i = 0; i < leftTargets.size(); ++i)
529 {
530 float desiredVel = leftJointTargetVel(i);
531 debugOutputData.getWriteBuffer().desired_vels[leftJointNames[i]] = desiredVel;
532
533 if (fabs(desiredVel) > cfg->jointVelLimit || isnan(desiredVel))
534 {
535 desiredVel = 0.0;
536 }
537
538 leftTargets.at(i)->velocity = desiredVel;
539 }
540
541 for (size_t i = 0; i < rightTargets.size(); ++i)
542 {
543 float desiredVel = rightJointTargetVel(i);
544 debugOutputData.getWriteBuffer().desired_vels[rightJointNames[i]] = desiredVel;
545
546 if (fabs(desiredVel) > cfg->jointVelLimit || isnan(desiredVel))
547 {
548 desiredVel = 0.0;
549 }
550
551 rightTargets.at(i)->velocity = desiredVel;
552 }
553
554
555 // --------------------------------------------- debug output ---------------------------------------------
556 debugOutputData.getWriteBuffer().virtualPose_x = virtualPose(0, 3);
557 debugOutputData.getWriteBuffer().virtualPose_y = virtualPose(1, 3);
558 debugOutputData.getWriteBuffer().virtualPose_z = virtualPose(2, 3);
559
560 debugOutputData.getWriteBuffer().currentPoseLeft_x = currentLeftPose(0, 3);
561 debugOutputData.getWriteBuffer().currentPoseLeft_y = currentLeftPose(1, 3);
562 debugOutputData.getWriteBuffer().currentPoseLeft_z = currentLeftPose(2, 3);
563
564
565 VirtualRobot::MathTools::Quaternion leftQuat =
566 VirtualRobot::MathTools::eigen4f2quat(currentLeftPose);
567 debugOutputData.getWriteBuffer().leftQuat_w = leftQuat.w;
568 debugOutputData.getWriteBuffer().leftQuat_x = leftQuat.x;
569 debugOutputData.getWriteBuffer().leftQuat_y = leftQuat.y;
570 debugOutputData.getWriteBuffer().leftQuat_z = leftQuat.y;
571
572 debugOutputData.getWriteBuffer().currentPoseRight_x = currentRightPose(0, 3);
573 debugOutputData.getWriteBuffer().currentPoseRight_y = currentRightPose(1, 3);
574 debugOutputData.getWriteBuffer().currentPoseRight_z = currentRightPose(2, 3);
575
576 VirtualRobot::MathTools::Quaternion rightQuat =
577 VirtualRobot::MathTools::eigen4f2quat(currentRightPose);
578 debugOutputData.getWriteBuffer().rightQuat_w = rightQuat.w;
579 debugOutputData.getWriteBuffer().rightQuat_x = rightQuat.x;
580 debugOutputData.getWriteBuffer().rightQuat_y = rightQuat.y;
581 debugOutputData.getWriteBuffer().rightQuat_z = rightQuat.y;
582
583
584 debugOutputData.getWriteBuffer().dmpBoxPose_x = virtualPose(0, 3);
585 debugOutputData.getWriteBuffer().dmpBoxPose_y = virtualPose(1, 3);
586 debugOutputData.getWriteBuffer().dmpBoxPose_z = virtualPose(2, 3);
587
588 VirtualRobot::MathTools::Quaternion dmpQuat =
589 VirtualRobot::MathTools::eigen4f2quat(virtualPose);
590 debugOutputData.getWriteBuffer().dmpBoxPose_qx = dmpQuat.x;
591 debugOutputData.getWriteBuffer().dmpBoxPose_qy = dmpQuat.y;
592 debugOutputData.getWriteBuffer().dmpBoxPose_qz = dmpQuat.z;
593 debugOutputData.getWriteBuffer().dmpBoxPose_qw = dmpQuat.w;
594 debugOutputData.commitWrite();
595 }
596
597 void
599 const Ice::Current&)
600 {
601 objectDMP->learnDMPFromFiles(fileNames);
602 }
603
604 void
606 const Ice::Current& ice)
607 {
608 LockGuardType guard(controllerMutex);
609 objectDMP->setGoalPoseVec(goals);
610 dmpGoal = VirtualRobot::MathTools::quat2eigen4f(goals[4], goals[5], goals[6], goals[3]);
611 dmpGoal(0, 3) = goals[0];
612 dmpGoal(1, 3) = goals[1];
613 dmpGoal(2, 3) = goals[2];
614 }
615
616 void
618 Ice::Double timeDuration,
619 const Ice::Current&)
620 {
621 while (!controlInterfaceBuffer.updateReadBuffer())
622 {
623 usleep(1000);
624 }
625
626 Eigen::Matrix4f leftPose = controlInterfaceBuffer.getUpToDateReadBuffer().currentLeftPose;
627 Eigen::Matrix4f rightPose = controlInterfaceBuffer.getUpToDateReadBuffer().currentRightPose;
628
629 VirtualRobot::MathTools::Quaternion boxOri =
630 VirtualRobot::MathTools::eigen4f2quat(leftPose);
631 Eigen::Vector3f boxPosi = (leftPose.block<3, 1>(0, 3) + rightPose.block<3, 1>(0, 3)) / 2;
632
633
634 std::vector<double> boxInitialPose;
635 for (size_t i = 0; i < 3; ++i)
636 {
637 boxInitialPose.push_back(boxPosi(i)); //Important: mm -> m
638 }
639 boxInitialPose.push_back(boxOri.w);
640 boxInitialPose.push_back(boxOri.x);
641 boxInitialPose.push_back(boxOri.y);
642 boxInitialPose.push_back(boxOri.z);
643
644 dmpGoal = VirtualRobot::MathTools::quat2eigen4f(goals[4], goals[5], goals[6], goals[3]);
645 dmpGoal(0, 3) = goals[0];
646 dmpGoal(1, 3) = goals[1];
647 dmpGoal(2, 3) = goals[2];
648
649 objectDMP->prepareExecution(boxInitialPose, goals);
650 objectDMP->canVal = timeDuration;
651 objectDMP->config.motionTimeDuration = timeDuration;
652
653
654 finished = false;
655 dmpStarted = true;
656 }
657
658 void
660 const Ice::DoubleSeq& goals,
661 Ice::Double timeDuration,
662 const Ice::Current&)
663 {
664 while (!controlInterfaceBuffer.updateReadBuffer())
665 {
666 usleep(1000);
667 }
668 ARMARX_IMPORTANT << "obj level control: setup dmp ...";
669
670 dmpGoal = VirtualRobot::MathTools::quat2eigen4f(goals[4], goals[5], goals[6], goals[3]);
671 dmpGoal(0, 3) = goals[0];
672 dmpGoal(1, 3) = goals[1];
673 dmpGoal(2, 3) = goals[2];
674
675 objectDMP->prepareExecution(starts, goals);
676 objectDMP->canVal = timeDuration;
677 objectDMP->config.motionTimeDuration = timeDuration;
678
679 finished = false;
680 dmpStarted = true;
681
682 ARMARX_IMPORTANT << "obj level control: run dmp with virtual start.";
683 }
684
685 void
687 const Ice::DoubleSeq& viapoint,
688 const Ice::Current&)
689 {
690 // LockGuardType guard(controllerMutex);
691 ARMARX_INFO << "setting via points ";
692 objectDMP->setViaPose(u, viapoint);
693 }
694
695 void
697 {
698 objectDMP->removeAllViaPoints();
699 }
700
701 void
703 const Ice::Current&)
704 {
705
706 Eigen::VectorXf setpoint;
707 setpoint.setZero(value.size());
708 ARMARX_CHECK_EQUAL(value.size(), 6);
709
710 for (size_t i = 0; i < value.size(); ++i)
711 {
712 setpoint(i) = value.at(i);
713 }
714
715 LockGuardType guard{interfaceDataMutex};
716 interface2rtBuffer.getWriteBuffer().KpImpedance = setpoint;
717 interface2rtBuffer.commitWrite();
718 }
719
720 void
722 const Ice::Current&)
723 {
724 Eigen::VectorXf setpoint;
725 setpoint.setZero(value.size());
726 ARMARX_CHECK_EQUAL(value.size(), 6);
727
728 for (size_t i = 0; i < value.size(); ++i)
729 {
730 setpoint(i) = value.at(i);
731 }
732
733 LockGuardType guard{interfaceDataMutex};
734 interface2rtBuffer.getWriteBuffer().KdImpedance = setpoint;
735 interface2rtBuffer.commitWrite();
736 }
737
738 std::vector<float>
740 {
741 Eigen::Vector3f tvel = controlInterfaceBuffer.getUpToDateReadBuffer().currentObjVel;
742 std::vector<float> tvelvec = {tvel(0), tvel(1), tvel(2)};
743 return tvelvec;
744 }
745
746 void
749 const DebugObserverInterfacePrx& debugObs)
750 {
751
752 StringVariantBaseMap datafields;
753 auto values = debugOutputData.getUpToDateReadBuffer().desired_vels;
754 for (auto& pair : values)
755 {
756 datafields[pair.first] = new Variant(pair.second);
757 }
758
759
760 datafields["virtualPose_x"] =
761 new Variant(debugOutputData.getUpToDateReadBuffer().virtualPose_x);
762 datafields["virtualPose_y"] =
763 new Variant(debugOutputData.getUpToDateReadBuffer().virtualPose_y);
764 datafields["virtualPose_z"] =
765 new Variant(debugOutputData.getUpToDateReadBuffer().virtualPose_z);
766
767 datafields["currentPoseLeft_x"] =
768 new Variant(debugOutputData.getUpToDateReadBuffer().currentPoseLeft_x);
769 datafields["currentPoseLeft_y"] =
770 new Variant(debugOutputData.getUpToDateReadBuffer().currentPoseLeft_y);
771 datafields["currentPoseLeft_z"] =
772 new Variant(debugOutputData.getUpToDateReadBuffer().currentPoseLeft_z);
773
774 datafields["leftQuat_w"] = new Variant(debugOutputData.getUpToDateReadBuffer().leftQuat_w);
775 datafields["leftQuat_x"] = new Variant(debugOutputData.getUpToDateReadBuffer().leftQuat_x);
776 datafields["leftQuat_y"] = new Variant(debugOutputData.getUpToDateReadBuffer().leftQuat_y);
777 datafields["leftQuat_z"] = new Variant(debugOutputData.getUpToDateReadBuffer().leftQuat_z);
778
779
780 datafields["currentPoseRight_x"] =
781 new Variant(debugOutputData.getUpToDateReadBuffer().currentPoseRight_x);
782 datafields["currentPoseRight_y"] =
783 new Variant(debugOutputData.getUpToDateReadBuffer().currentPoseRight_y);
784 datafields["currentPoseRight_z"] =
785 new Variant(debugOutputData.getUpToDateReadBuffer().currentPoseRight_z);
786 datafields["rightQuat_w"] =
787 new Variant(debugOutputData.getUpToDateReadBuffer().rightQuat_w);
788 datafields["rightQuat_x"] =
789 new Variant(debugOutputData.getUpToDateReadBuffer().rightQuat_x);
790 datafields["rightQuat_y"] =
791 new Variant(debugOutputData.getUpToDateReadBuffer().rightQuat_y);
792 datafields["rightQuat_z"] =
793 new Variant(debugOutputData.getUpToDateReadBuffer().rightQuat_z);
794
795 datafields["dmpBoxPose_x"] =
796 new Variant(debugOutputData.getUpToDateReadBuffer().dmpBoxPose_x);
797 datafields["dmpBoxPose_y"] =
798 new Variant(debugOutputData.getUpToDateReadBuffer().dmpBoxPose_y);
799 datafields["dmpBoxPose_z"] =
800 new Variant(debugOutputData.getUpToDateReadBuffer().dmpBoxPose_z);
801
802 datafields["dmpBoxPose_qx"] =
803 new Variant(debugOutputData.getUpToDateReadBuffer().dmpBoxPose_qx);
804 datafields["dmpBoxPose_qy"] =
805 new Variant(debugOutputData.getUpToDateReadBuffer().dmpBoxPose_qy);
806 datafields["dmpBoxPose_qz"] =
807 new Variant(debugOutputData.getUpToDateReadBuffer().dmpBoxPose_qz);
808 datafields["dmpBoxPose_qw"] =
809 new Variant(debugOutputData.getUpToDateReadBuffer().dmpBoxPose_qw);
810
811 debugObs->setDebugChannel("BimanualForceController", datafields);
812 }
813
814 void
816 {
817
818
819 ARMARX_INFO << "init ...";
820 runTask("NJointBimanualObjLevelVelController",
821 [&]
822 {
823 CycleUtil c(1);
824 getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted);
825 while (getState() == eManagedIceObjectStarted)
826 {
827 if (isControllerActive())
828 {
830 }
831 c.waitForCycleDuration();
832 }
833 });
834 }
835
836 void
841} // namespace armarx::control::deprecated_njoint_mp_controller::bimanual
constexpr T c
Brief description of class JointControlTargetBase.
This util class helps with keeping a cycle time during a control cycle.
Definition CycleUtil.h:41
ArmarXObjectSchedulerPtr getObjectScheduler() const
int getState() const
Retrieve current state of the ManagedIceObject.
bool isControllerActive(const Ice::Current &=Ice::emptyCurrent) const final override
const SensorValueBase * useSensorValue(const std::string &sensorDeviceName) const
Get a const ptr to the given SensorDevice's SensorValue.
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
ControlTargetBase * useControlTarget(const std::string &deviceName, const std::string &controlMode)
Declares to calculate the ControlTarget for the given ControlDevice in the given ControlMode when rtR...
The SensorValueBase class.
const T * asA() const
The Variant class is described here: Variants.
Definition Variant.h:224
void runDMPWithVirtualStart(const Ice::DoubleSeq &starts, const Ice::DoubleSeq &goals, Ice::Double timeDuration, const Ice::Current &)
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
TODO make protected and use attorneys.
NJointBimanualObjLevelVelController(const RobotUnitPtr &, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
void runDMP(const Ice::DoubleSeq &goals, Ice::Double timeDuration, const Ice::Current &)
Eigen::VectorXf calcIK(VirtualRobot::DifferentialIKPtr ik, const Eigen::MatrixXf &jacobi, const Eigen::VectorXf &cartesianVel, const Eigen::VectorXf &nullspaceVel)
virtual void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &)
#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_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
Matrix< float, 6, 1 > Vector6f
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
NJointControllerRegistration< NJointBimanualObjLevelVelController > registrationControllerNJointBimanualObjLevelVelController("NJointBimanualObjLevelVelController")
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
std::vector< std::vector< T > > transpose(const std::vector< std::vector< T > > &src, Thrower thrower)
IceUtil::Handle< class RobotUnit > RobotUnitPtr
Definition FTSensor.h:34
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl