28 #include <SimoxUtility/algorithm/string/string_conversion_eigen.h>
29 #include <SimoxUtility/json/eigen_conversion.h>
30 #include <SimoxUtility/json/json.h>
31 #include <SimoxUtility/math/convert/mat4f_to_rpy.h>
54 #include <armarx/control/interface/ConfigurableNJointControllerInterface.h>
55 #include <armarx/control/njoint_controller/joint_space/aron/WholeBodyTrajectoryControllerConfig.aron.generated.h>
57 #include <range/v3/view/zip.hpp>
66 const NJointControllerConfigPtr& config,
69 pidPlatform_(initialConfigData().pidPlatform.Kp,
70 initialConfigData().pidPlatform.Ki,
71 initialConfigData().pidPlatform.Kd,
72 initialConfigData().pidPlatform.maxControlValue,
73 initialConfigData().pidPlatform.maxDerivation),
74 opidPlatform_(initialConfigData().opidPlatform.Kp,
75 initialConfigData().opidPlatform.Ki,
76 initialConfigData().opidPlatform.Kd,
77 initialConfigData().opidPlatform.maxControlValue,
78 initialConfigData().opidPlatform.maxDerivation,
97 controlTargets_.platformTarget =
99 ControlModes::HolonomicPlatformVelocity)
102 <<
"The actuator " << robotUnit->getRobotPlatformName() <<
" has no control mode "
103 << ControlModes::HolonomicPlatformVelocity;
107 auto*
const controlTarget = useControlTarget<ControlTarget1DoFActuatorVelocity>(
108 jointName, ControlModes::Velocity1DoF);
111 controlTargets_.jointTargets.push_back(controlTarget);
117 auto*
const controlTarget = useControlTarget<ControlTarget1DoFActuatorPosition>(
118 jointName, ControlModes::Position1DoF);
121 controlTargets_.handTargets.push_back(controlTarget);
143 svGlobalRobotLocalization_ =
152 std::vector<bool> isJointLimitless;
155 const auto node = robot_->getRobotNode(jointName);
156 isJointLimitless.push_back(node->isLimitless());
168 pidArm_->preallocate(nDofArm);
187 const std::string tcpNodeName =
"Hand R TCP";
191 debugRobot_ = robot->clone();
195 publishTcpNode_ = debugRobot_->getRobotNode(tcpNodeName);
198 rtTcpNode_ = robot_->getRobotNode(tcpNodeName);
214 .platformPosDiff = 0,
215 .platformOriDiff = 0,
217 .targetState = trajectory_->initialPoint(),
218 .currentTcpPose = Eigen::Isometry3f{rtTcpNode_->getGlobalPose()},
219 .currentPlatformPose = Eigen::Isometry3f{robot_->getGlobalPose()},
220 .isControllerActive =
false};
244 const std::int64_t timestamp =
armarx::rtNow().toMicroSeconds();
268 const auto trajPointOpt = trajectory_->at(timestamp);
272 if (not trajPointOpt.has_value())
277 controlTargets_.platformTarget->velocityX = 0;
278 controlTargets_.platformTarget->velocityY = 0;
279 controlTargets_.platformTarget->velocityRotation = 0;
282 for (
auto*
const jointControlTarget : controlTargets_.jointTargets)
284 jointControlTarget->velocity = 0;
293 debugData.localTimestamp = trajPoint.timestampMicroSeconds;
294 debugData.targetState = trajPoint;
295 debugData.currentTcpPose = Eigen::Isometry3f{rtTcpNode_->getGlobalPose()};
296 debugData.currentPlatformPose = Eigen::Isometry3f{robot_->getGlobalPose()};
304 const Eigen::Vector2f global_P_robot_target{trajPoint.jointValuesPlatform.at(0),
305 trajPoint.jointValuesPlatform.at(1)};
306 const double targetOrientationGlobal = trajPoint.jointValuesPlatform.at(2);
309 const auto global_T_robot = svGlobalRobotLocalization_->
global_T_root;
310 const Eigen::Vector3f rpy = simox::math::mat4f_to_rpy(global_T_robot);
311 const float globalOrientation = rpy.z();
312 const Eigen::Vector2f global_P_robot = global_T_robot.block<2, 1>(0, 3);
314 const float measuredOrientation = globalOrientation;
317 timeSinceLastIteration.toSecondsDouble(), global_P_robot, global_P_robot_target);
318 opidPlatform_.
update(timeSinceLastIteration.toSecondsDouble(),
319 static_cast<double>(measuredOrientation),
320 targetOrientationGlobal);
323 debugData.platformPosDiff = (global_P_robot_target - global_P_robot).
norm();
324 debugData.platformOriDiff =
325 static_cast<float>(targetOrientationGlobal) - measuredOrientation;
335 const Eigen::Rotation2Df local_R_global(-measuredOrientation);
336 const Eigen::Vector2f& vPosError = local_R_global * pidPlatform_.
getControlValue();
337 const Eigen::Vector2f vVelFFRobotFrame =
338 local_R_global * Eigen::Vector2f(trajPoint.jointVelocitiesPlatform.at(0),
339 trajPoint.jointVelocitiesPlatform.at(1));
341 const auto& vFF = trajPoint.jointVelocitiesPlatform;
353 constexpr
float ffFactorPlatform = 1.0;
358 controlTargets_.platformTarget->velocityX =
359 ffFactorPlatform * vVelFFRobotFrame.x() + vPosError.x();
360 controlTargets_.platformTarget->velocityY =
361 ffFactorPlatform * vVelFFRobotFrame.y() + vPosError.y();
367 controlTargets_.platformTarget->velocityRotation =
368 ffFactorPlatform * vFF.at(2) +
376 ARMARX_CHECK_EQUAL(controlTargets_.jointTargets.size(), trajPoint.jointValues.size());
378 trajPoint.jointVelocities.size());
383 const auto toEigen = [](
const std::vector<double>& vec) -> Eigen::VectorXf
385 Eigen::VectorXf eigenVec(vec.size());
386 for (std::size_t i = 0; i < vec.size(); i++)
388 eigenVec(i) =
static_cast<float>(vec.at(i));
396 const Eigen::VectorXf jointPositionTargets =
toEigen(trajPoint.jointValues);
399 Eigen::VectorXf jointPositionMeasured(jointSensorValues_.size());
400 for (std::size_t i = 0; i < jointSensorValues_.size(); i++)
402 jointPositionMeasured(i) = jointSensorValues_.at(i)->position;
407 for (std::size_t i = 0; i < jointSensorValues_.size(); i++)
409 debugData.jointPosDiff.at(i) =
410 std::abs(jointPositionTargets(i) - jointPositionMeasured(i));
414 pidArm_->update(timeSinceLastIteration.toSecondsDouble(),
415 jointPositionMeasured,
416 jointPositionTargets);
419 const Eigen::VectorXf& jointVelocityForPosError = pidArm_->getControlValue();
421 for (std::size_t i = 0; i < controlTargets_.jointTargets.size(); i++)
423 auto*
const jointControlTarget = controlTargets_.jointTargets.at(i);
427 const double jointVelTarget = trajPoint.jointVelocities.at(i);
431 jointControlTarget->velocity =
432 static_cast<float>(jointVelTarget) + jointVelocityForPosError(i);
434 if (not jointControlTarget->isValid())
437 <<
". Value: " << jointControlTarget->velocity;
446 trajPoint.handJointValues.size());
447 for (std::size_t i = 0; i < controlTargets_.handTargets.size(); i++)
449 auto*
const handControlTarget = controlTargets_.handTargets.at(i);
450 const double jointPosTarget = trajPoint.handJointValues.at(i);
451 handControlTarget->position =
static_cast<float>(jointPosTarget);
466 const std::int64_t timestampMicroSeconds =
armarx::rtNow().toMicroSeconds();
468 trajectory_->setStartTime(timestampMicroSeconds);
483 datafields[
"localTimestamp"] =
new Variant(debugData.localTimestamp);
485 datafields[
"platform/dpos"] =
new Variant(debugData.platformPosDiff);
486 datafields[
"platform/dori"] =
new Variant(debugData.platformOriDiff);
489 for (
const auto& [jointName, diff] :
490 ranges::views::zip(jointNames_, debugData.jointPosDiff))
492 datafields[jointName +
"/dpos"] =
new Variant(diff);
495 const float tcpDiff = [&]() ->
float
497 namespace rv = ranges::views;
500 std::map<std::string, float> targetJointValues;
501 for (
const auto& [jointName, jointValue] :
502 rv::zip(jointNames_, debugData.targetState.jointValues))
504 targetJointValues.emplace(jointName, jointValue);
507 const Eigen::Isometry3f targetGlobalPose =
508 Eigen::Translation3f{
509 static_cast<float>(debugData.targetState.jointValuesPlatform.at(0)),
510 static_cast<float>(debugData.targetState.jointValuesPlatform.at(1)),
513 static_cast<float>(debugData.targetState.jointValuesPlatform.at(2)),
514 Eigen::Vector3f::UnitZ()};
516 debugRobot_->setJointValues(targetJointValues);
517 debugRobot_->setGlobalPose(targetGlobalPose.matrix());
519 const Eigen::Isometry3f targetTcpPose(publishTcpNode_->getGlobalPose());
521 const Eigen::Isometry3f tcpDiffTf = debugData.currentTcpPose.inverse() * targetTcpPose;
523 auto batchPrx = debugDrawer->ice_batchOneway();
528 batchPrx->setSphereDebugLayerVisu(
531 ::armarx::DrawColor{1, 0, 0, 0},
534 batchPrx->setSphereDebugLayerVisu(
536 new armarx::Vector3(Eigen::Vector3f{debugData.currentTcpPose.translation()}),
537 ::armarx::DrawColor{0, 1, 0, 0},
540 batchPrx->setPoseDebugLayerVisu(
"tcp_target_pose",
toIce(targetTcpPose.matrix()));
541 batchPrx->setPoseDebugLayerVisu(
"tcp_current_pose",
542 toIce(debugData.currentTcpPose.matrix()));
547 batchPrx->setSphereDebugLayerVisu(
550 ::armarx::DrawColor{1, 0, 0, 0},
553 batchPrx->setSphereDebugLayerVisu(
"platform_current",
555 debugData.currentPlatformPose.translation()}),
556 ::armarx::DrawColor{0, 1, 0, 0},
559 batchPrx->setPoseDebugLayerVisu(
"platform_target_pose",
560 toIce(targetGlobalPose.matrix()));
562 batchPrx->setPoseDebugLayerVisu(
"platform_current_pose",
563 toIce(debugData.currentPlatformPose.matrix()));
566 batchPrx->ice_flushBatchRequests();
570 return tcpDiffTf.translation().norm();
573 datafields[
"tcpDiff"] =
new Variant(tcpDiff);
580 if (whateverFlag_.load())
582 whatever_.push_back(debugData);
589 to_json(nlohmann::json& j,
const TrajectoryPoint& trajectoryPoint)
591 j[
"timestampMicroSeconds"] = trajectoryPoint.timestampMicroSeconds;
592 j[
"jointValues"] = trajectoryPoint.jointValues;
593 j[
"jointValuesPlatform"] = trajectoryPoint.jointValuesPlatform;
594 j[
"handJointValues"] = trajectoryPoint.handJointValues;
595 j[
"jointVelocities"] = trajectoryPoint.jointVelocities;
596 j[
"jointVelocitiesPlatform"] = trajectoryPoint.jointVelocitiesPlatform;
617 whateverFlag_.store(
false);
620 j[
"data"] = whatever_;
625 "controller_execution/" +
filename};
627 ARMARX_INFO <<
"Writing debug data to " << packagePath.toSystemPath();
629 std::ofstream ofs(packagePath.toSystemPath());
630 ofs << std::setw(4) << j << std::endl;