25 #include <VirtualRobot/MathTools.h>
26 #include <VirtualRobot/Nodes/RobotNode.h>
27 #include <VirtualRobot/RobotNodeSet.h>
44 NJointControllerRegistration<NJointTaskspaceZeroTorqueOrVelocityController>
46 "NJointTaskspaceZeroTorqueOrVelocityController");
54 arm->kinematicChainName = nodeSetName;
55 VirtualRobot::RobotNodeSetPtr rtRns =
56 rtGetRobot()->getRobotNodeSet(arm->kinematicChainName);
57 VirtualRobot::RobotNodeSetPtr nonRtRns =
58 nonRtRobotPtr->getRobotNodeSet(arm->kinematicChainName);
62 <<
"Creating Taskspace Zero Torque or Velocity Controller with kinematic chain: "
63 << arm->kinematicChainName <<
" with num of joints: (RT robot) " << rtRns->getSize()
64 <<
", and (non-RT robot) " << nonRtRns->getSize();
66 std::vector<size_t> jointIDTorqueMode;
67 std::vector<size_t> jointIDVelocityMode;
68 arm->jointNames.clear();
69 for (
size_t i = 0; i < rtRns->getSize(); ++i)
72 std::string jointName = rtRns->getNode(i)->getName();
73 arm->jointNames.push_back(jointName);
75 bool foundControlDevice =
false;
77 cfg.jointNameListTorque.begin(), cfg.jointNameListTorque.end(), jointName);
78 if (it != cfg.jointNameListTorque.end())
82 auto* casted_ct = ct->
asA<ControlTarget1DoFActuatorZeroTorque>();
84 arm->targetsTorque.push_back(casted_ct);
85 jointIDTorqueMode.push_back(i);
86 foundControlDevice =
true;
90 cfg.jointNameListVelocity.begin(), cfg.jointNameListVelocity.end(), jointName);
91 if (it != cfg.jointNameListVelocity.end())
95 auto* casted_ct = ct->
asA<ControlTarget1DoFActuatorZeroVelocity>();
97 arm->targetsVel.push_back(casted_ct);
98 jointIDVelocityMode.push_back(i);
99 foundControlDevice =
true;
101 if (not foundControlDevice)
103 ARMARX_INFO << jointName <<
" is not selected for " << arm->kinematicChainName;
107 ARMARX_INFO <<
"Robot node set '" << arm->kinematicChainName
108 <<
"' has torque controlled joints [" << namesTorque
109 <<
"] and velocity controlled joints [" << namesVelocity <<
"].";
113 const auto* torqueSensor = sv->
asA<SensorValue1DoFActuatorTorque>();
114 const auto* velocitySensor = sv->
asA<SensorValue1DoFActuatorVelocity>();
115 const auto* positionSensor = sv->
asA<SensorValue1DoFActuatorPosition>();
117 if (torqueSensor ==
nullptr)
121 if (velocitySensor ==
nullptr)
123 ARMARX_WARNING <<
"No velocity sensor available for " << jointName;
125 if (positionSensor ==
nullptr)
127 ARMARX_WARNING <<
"No position sensor available for " << jointName;
131 arm->sensorDevices.torqueSensors.push_back(torqueSensor);
132 arm->sensorDevices.velocitySensors.push_back(velocitySensor);
133 arm->sensorDevices.positionSensors.push_back(positionSensor);
135 ARMARX_DEBUG <<
"Number of torque controlled joints " << jointIDTorqueMode.size();
136 ARMARX_DEBUG <<
"Number of velocity controlled joints " << jointIDVelocityMode.size();
140 arm->controller.initialize(nonRtRns, rtRns, jointIDTorqueMode, jointIDVelocityMode);
141 arm->controller.ftsensor.initialize(rtRns,
robotUnit, cfg.ftConfig);
145 arm->nonRtConfig = cfg;
150 const NJointControllerConfigPtr& config,
156 ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
158 userConfig = ::armarx::fromAronDict<ConfigDict, ConfigDict>(cfg->config);
166 limb.emplace(pair.first, std::make_unique<ArmData>());
174 return "NJointTaskspaceZeroTorqueOrVelocityController";
185 double timeMeasure = IceUtil::Time::now().toMicroSecondsDouble();
186 arm->rtConfig = arm->bufferNonRtToRt.getUpToDateReadBuffer();
187 double time_update_non_rt_buffer =
188 IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
190 if (arm->rtFirstRun.load())
192 arm->rtFirstRun.store(
false);
193 arm->rtReady.store(
true);
195 arm->controller.ftsensor.updateStatus(arm->rtConfig.ftConfig,
196 arm->rtStatus.currentForceTorque,
197 arm->rtStatus.deltaT,
198 arm->rtFirstRun.load());
200 double time_update_ft = IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
202 size_t nDoF = arm->sensorDevices.positionSensors.size();
203 double time_update_size = IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
204 for (
size_t i = 0; i < nDoF; ++i)
206 arm->rtStatus.jointPosition[i] = arm->sensorDevices.positionSensors[i]->position;
207 arm->rtStatus.jointVelocity[i] = arm->sensorDevices.velocitySensors[i]->velocity;
208 arm->rtStatus.jointTorque[i] = arm->sensorDevices.torqueSensors[i]->torque;
211 double time_update_js = IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
212 arm->rtStatus.deltaT = deltaT;
213 double time_update_rt_status = IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
215 arm->bufferRtToNonRt.getWriteBuffer() = arm->rtStatus;
216 arm->bufferRtToNonRt.commitWrite();
217 arm->bufferRtStatusToUser.getWriteBuffer() = arm->rtStatus;
218 arm->bufferRtStatusToUser.commitWrite();
219 double time_write_rt_buffer = IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
221 arm->controller.run(arm->rtConfig, arm->rtStatus);
222 double time_run_rt = IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
224 for (
unsigned int i = 0; i < arm->rtStatus.nDoFTorque; i++)
226 auto jointIdx = arm->controller.jointIDTorqueMode[i];
227 arm->targetsTorque.at(i)->torque = arm->rtStatus.desiredJointTorques(jointIdx);
228 if (!arm->targetsTorque.at(i)->isValid())
230 arm->targetsTorque.at(i)->torque = 0;
233 for (
unsigned int i = 0; i < arm->rtStatus.nDoFVelocity; i++)
235 auto jointIdx = arm->controller.jointIDVelocityMode[i];
236 arm->targetsVel.at(i)->velocity = arm->rtStatus.desiredJointVelocity(jointIdx);
238 if (!arm->targetsVel.at(i)->isValid())
240 arm->targetsVel.at(i)->velocity = 0;
243 arm->bufferRtStatusToOnPublish.getWriteBuffer() = arm->rtStatus;
244 arm->bufferRtStatusToOnPublish.commitWrite();
246 arm->bufferRtConfigToOnPublish.getWriteBuffer() = arm->rtConfig;
247 arm->bufferRtConfigToOnPublish.commitWrite();
249 arm->bufferRtConfigToUser.getWriteBuffer() = arm->rtConfig;
250 arm->bufferRtConfigToUser.commitWrite();
251 double time_rt_status_buffer = IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
252 timeMeasure = IceUtil::Time::now().toMicroSecondsDouble() - timeMeasure;
254 if (timeMeasure > 100)
257 "update_non_rt_buffer: %.2f\n"
259 "update_size: %.2f\n"
261 "update_rt_status: %.2f\n"
262 "write_rt_buffer: %.2f\n"
264 "rt_status_buffer: %.2f\n"
266 time_update_non_rt_buffer,
267 time_update_ft - time_update_non_rt_buffer,
268 time_update_size - time_update_ft,
269 time_update_js - time_update_size,
270 time_update_rt_status - time_update_non_rt_buffer,
271 time_write_rt_buffer - time_update_rt_status,
272 time_run_rt - time_write_rt_buffer,
273 time_rt_status_buffer - time_run_rt,
283 double deltaT = timeSinceLastIteration.toSecondsDouble();
284 for (
auto& pair :
limb)
286 limbRT(pair.second, deltaT);
293 const Ice::Current& iceCurrent)
301 limb.at(pair.first)->bufferUserToNonRt.getWriteBuffer() = pair.second;
302 limb.at(pair.first)->bufferUserToNonRt.commitWrite();
309 for (
auto& pair :
limb)
312 pair.second->bufferRtConfigToUser.getUpToDateReadBuffer();
321 const auto checkNonNegative = [](
const auto&
v) {
ARMARX_CHECK(
v >= 0); };
322 const auto checkVecNonNegative = [](
const auto&
v)
325 checkVecNonNegative(configData.kpCartesianVel);
326 checkVecNonNegative(configData.kdCartesianVel);
328 checkNonNegative(configData.torqueLimit);
329 checkNonNegative(configData.velocityLimit);
330 checkNonNegative(configData.qvelFilter);
331 checkNonNegative(configData.cartesianLinearVelLimit);
332 checkNonNegative(configData.cartesianAngularVelLimit);
341 auto rtConfig = arm->bufferRtConfigToOnPublish.getUpToDateReadBuffer();
342 auto rtStatus = arm->bufferRtStatusToOnPublish.getUpToDateReadBuffer();
347 datafields[
"velocityLimit"] =
new Variant(rtConfig.velocityLimit);
350 debugObs->setDebugChannel(
"ZT-ZV_" + arm->kinematicChainName, datafields);
359 for (
auto& pair :
limb)
368 for (
auto& pair :
limb)
370 pair.second->rtReady.store(
false);
377 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(arm->kinematicChainName);
379 arm->bufferUserToNonRt.reinitAllBuffers(arm->rtConfig);
381 arm->nonRtConfig = arm->rtConfig;
382 arm->bufferNonRtToRt.reinitAllBuffers(arm->rtConfig);
383 arm->bufferRtConfigToOnPublish.reinitAllBuffers(arm->rtConfig);
384 arm->bufferRtConfigToUser.reinitAllBuffers(arm->rtConfig);
387 const auto nDoF = rns->getSize();
388 const auto nDoFTorque = arm->controller.jointIDTorqueMode.size();
389 const auto nDoFVelocity = arm->controller.jointIDVelocityMode.size();
391 arm->rtStatus.nDoFTorque = nDoFTorque;
392 arm->rtStatus.nDoFVelocity = nDoFVelocity;
393 arm->rtStatus.numJoints = nDoF;
394 arm->rtStatus.desiredJointTorques.setZero(nDoF);
395 arm->rtStatus.desiredJointVelocity.setZero(nDoF);
396 arm->rtStatus.cartesianVelTarget.setZero();
398 arm->rtStatus.jointPosition.resize(nDoF, 0.);
399 arm->rtStatus.jointVelocity.resize(nDoF, 0.);
400 arm->rtStatus.jointTorque.resize(nDoF, 0.);
401 for (
size_t i = 0; i < nDoF; ++i)
403 arm->rtStatus.jointPosition[i] = arm->sensorDevices.positionSensors[i]->position;
404 arm->rtStatus.jointVelocity[i] = arm->sensorDevices.velocitySensors[i]->velocity;
405 arm->rtStatus.jointTorque[i] = arm->sensorDevices.torqueSensors[i]->torque;
408 arm->rtStatus.qpos = rns->getJointValuesEigen();
409 arm->rtStatus.qvel.setZero(nDoF);
410 arm->rtStatus.qvelFiltered.setZero(nDoF);
412 arm->rtStatus.currentTwist.setZero();
413 arm->rtStatus.jacobi.setZero(6, nDoF);
415 arm->rtStatus.deltaT = 0.0;
416 arm->rtStatus.rtSafe =
false;
418 arm->rtStatus.currentForceTorque.setZero();
420 arm->rtStatusInNonRT = arm->rtStatus;
421 arm->bufferRtStatusToOnPublish.reinitAllBuffers(arm->rtStatus);
422 arm->bufferRtToNonRt.reinitAllBuffers(arm->rtStatus);
423 arm->bufferRtStatusToUser.reinitAllBuffers(arm->rtStatus);
426 arm->controller.preactivateInit(rns);
432 for (
auto& pair :
limb)
434 ARMARX_INFO <<
"rtPreActivateController for " << pair.first;
436 userConfig.limbs.at(pair.first) = pair.second->rtConfig;
452 const std::map<std::string, ConstControlDevicePtr>& controlDevices,
453 const std::map<std::string, ConstSensorDevicePtr>&)
459 ::armarx::WidgetDescription::WidgetSeq widgets;
460 auto addSlider = [&](
const std::string& label,
float min,
float max,
float defaultValue)
462 widgets.emplace_back(
new Label(
false, label));
467 c_x->defaultValue = defaultValue;
469 widgets.emplace_back(c_x);
474 LabelPtr label =
new Label;
475 label->text =
"ZeroTorque (L/R)";
477 StringComboBoxPtr boxZeroTorqueLeft =
new StringComboBox;
478 boxZeroTorqueLeft->name =
"ZeroTorqueLeft";
479 boxZeroTorqueLeft->defaultIndex = 0;
480 boxZeroTorqueLeft->multiSelect =
true;
482 StringComboBoxPtr boxZeroTorqueRight =
new StringComboBox;
483 boxZeroTorqueRight->name =
"ZeroTorqueRight";
484 boxZeroTorqueRight->defaultIndex = 0;
485 boxZeroTorqueRight->multiSelect =
true;
488 LabelPtr labelZVMode =
new Label;
489 labelZVMode->text =
"ZeroVelocity (L/R)";
491 StringComboBoxPtr boxZeroVelocityLeft =
new StringComboBox;
492 boxZeroVelocityLeft->name =
"ZeroVelocityLeft";
493 boxZeroVelocityLeft->defaultIndex = 0;
494 boxZeroVelocityLeft->multiSelect =
true;
496 StringComboBoxPtr boxZeroVelocityRight =
new StringComboBox;
497 boxZeroVelocityRight->name =
"ZeroVelocityRight";
498 boxZeroVelocityRight->defaultIndex = 0;
499 boxZeroVelocityRight->multiSelect =
true;
503 std::map<std::string, StringComboBoxPtr> boxes;
504 boxes.insert({
"zv_left", boxZeroVelocityLeft});
505 boxes.insert({
"zv_right", boxZeroVelocityRight});
506 boxes.insert({
"zt_left", boxZeroTorqueLeft});
507 boxes.insert({
"zt_right", boxZeroTorqueRight});
510 for (
auto&
c : controlDevices)
513 if (
c.first.find(
"ArmL") != std::string::npos)
517 else if (
c.first.find(
"ArmR") != std::string::npos)
526 if (
c.second->hasJointController(ControlModes::ZeroTorque1DoF))
528 boxes.at(
"zt_" + mode)->options.push_back(
c.first);
530 else if (
c.second->hasJointController(ControlModes::ZeroVelocity1DoF))
532 boxes.at(
"zv_" + mode)->options.push_back(
c.first);
537 layout->children.emplace_back(label);
538 layout->children.emplace_back(boxZeroTorqueLeft);
539 layout->children.emplace_back(boxZeroTorqueRight);
540 layout->children.emplace_back(labelZVMode);
541 layout->children.emplace_back(boxZeroVelocityLeft);
542 layout->children.emplace_back(boxZeroVelocityRight);
544 addSlider(
"maxTorque", 0, 100, 10);
545 addSlider(
"maxVeloicty", 0, 3.14, 2.0);
548 layout->children.insert(layout->children.end(), widgets.begin(), widgets.end());
559 "controller_config/NJointTaskspaceZeroTorqueOrVelocityController/default.json");
561 auto cfgDTO = armarx::readFromJson<ConfigDict>(configPath.
toSystemPath());
563 ARMARX_WARNING_S <<
"Left arm of armar7 is not yet calibrated, the default is set to "
564 "RightArm for safety reason!";
566 auto varZTLeft = VariantPtr::dynamicCast(
values.at(
"ZeroTorqueLeft"));
567 auto varZTRight = VariantPtr::dynamicCast(
values.at(
"ZeroTorqueRight"));
568 auto varZVLeft = VariantPtr::dynamicCast(
values.at(
"ZeroVelocityLeft"));
569 auto varZVRight = VariantPtr::dynamicCast(
values.at(
"ZeroVelocityRight"));
575 cfgDTO.limbs.at(
"RightArm").jointNameListTorque =
577 cfgDTO.limbs.at(
"RightArm").jointNameListVelocity =
579 cfgDTO.limbs.at(
"RightArm").torqueLimit =
values.at(
"maxTorque")->getFloat();
580 cfgDTO.limbs.at(
"RightArm").velocityLimit =
values.at(
"maxVeloicty")->getFloat();
585 cfgDTO.limbs.at(
"RightArm").jointNameListVelocity);
586 if (cfgDTO.limbs.at(
"RightArm").jointNameListTorque.size() > 0)
588 ARMARX_INFO_S <<
"'RightArm' has torque controlled joints [" << namesTorque <<
"].";
590 if (cfgDTO.limbs.at(
"RightArm").jointNameListVelocity.size() > 0)
592 ARMARX_INFO_S <<
"'RightArm' has velocity controlled joints [" << namesVelocity <<
"].";
595 ARMARX_INFO_S <<
"torque limit: " << cfgDTO.limbs.at(
"RightArm").torqueLimit
596 <<
"velocity limit: " << cfgDTO.limbs.at(
"RightArm").velocityLimit;
599 return new ConfigurableNJointControllerConfig{cfgDTO.toAronDTO()};