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>
48 #include <armarx/control/interface/ConfigurableNJointControllerInterface.h>
49 #include <armarx/control/njoint_controller/joint_space/aron/WholeBodyTrajectoryControllerConfig.aron.generated.h>
51 #include <range/v3/view/zip.hpp>
60 const NJointControllerConfigPtr& config,
63 pidPlatform_(initialConfigData().pidPlatform.Kp,
64 initialConfigData().pidPlatform.Ki,
65 initialConfigData().pidPlatform.Kd,
66 initialConfigData().pidPlatform.maxControlValue,
67 initialConfigData().pidPlatform.maxDerivation),
68 opidPlatform_(initialConfigData().opidPlatform.Kp,
69 initialConfigData().opidPlatform.Ki,
70 initialConfigData().opidPlatform.Kd,
71 initialConfigData().opidPlatform.maxControlValue,
72 initialConfigData().opidPlatform.maxDerivation,
91 controlTargets_.platformTarget =
93 ControlModes::HolonomicPlatformVelocity)
96 <<
"The actuator " << robotUnit->getRobotPlatformName() <<
" has no control mode "
97 << ControlModes::HolonomicPlatformVelocity;
101 auto*
const controlTarget = useControlTarget<ControlTarget1DoFActuatorVelocity>(
102 jointName, ControlModes::Velocity1DoF);
105 controlTargets_.jointTargets.push_back(controlTarget);
111 auto*
const controlTarget = useControlTarget<ControlTarget1DoFActuatorPosition>(
112 jointName, ControlModes::Position1DoF);
115 controlTargets_.handTargets.push_back(controlTarget);
137 svGlobalRobotLocalization_ =
146 std::vector<bool> isJointLimitless;
149 const auto node = robot_->getRobotNode(jointName);
150 isJointLimitless.push_back(node->isLimitless());
162 pidArm_->preallocate(nDofArm);
181 const std::string tcpNodeName =
"Hand R TCP";
185 debugRobot_ = robot->clone();
189 publishTcpNode_ = debugRobot_->getRobotNode(tcpNodeName);
192 rtTcpNode_ = robot_->getRobotNode(tcpNodeName);
208 .platformPosDiff = 0,
209 .platformOriDiff = 0,
211 .targetState = trajectory_->initialPoint(),
212 .currentTcpPose = Eigen::Isometry3f{rtTcpNode_->getGlobalPose()},
213 .currentPlatformPose = Eigen::Isometry3f{robot_->getGlobalPose()},
214 .isControllerActive =
false};
238 const std::int64_t timestamp =
armarx::rtNow().toMicroSeconds();
262 const auto trajPointOpt = trajectory_->at(timestamp);
266 if (not trajPointOpt.has_value())
271 controlTargets_.platformTarget->velocityX = 0;
272 controlTargets_.platformTarget->velocityY = 0;
273 controlTargets_.platformTarget->velocityRotation = 0;
276 for (
auto*
const jointControlTarget : controlTargets_.jointTargets)
278 jointControlTarget->velocity = 0;
287 debugData.localTimestamp = trajPoint.timestampMicroSeconds;
288 debugData.targetState = trajPoint;
289 debugData.currentTcpPose = Eigen::Isometry3f{rtTcpNode_->getGlobalPose()};
290 debugData.currentPlatformPose = Eigen::Isometry3f{robot_->getGlobalPose()};
298 const Eigen::Vector2f global_P_robot_target{trajPoint.jointValuesPlatform.at(0),
299 trajPoint.jointValuesPlatform.at(1)};
300 const double targetOrientationGlobal = trajPoint.jointValuesPlatform.at(2);
303 const auto global_T_robot = svGlobalRobotLocalization_->
global_T_root;
304 const Eigen::Vector3f rpy = simox::math::mat4f_to_rpy(global_T_robot);
305 const float globalOrientation = rpy.z();
306 const Eigen::Vector2f global_P_robot = global_T_robot.block<2, 1>(0, 3);
308 const float measuredOrientation = globalOrientation;
311 timeSinceLastIteration.toSecondsDouble(), global_P_robot, global_P_robot_target);
312 opidPlatform_.
update(timeSinceLastIteration.toSecondsDouble(),
313 static_cast<double>(measuredOrientation),
314 targetOrientationGlobal);
317 debugData.platformPosDiff = (global_P_robot_target - global_P_robot).
norm();
318 debugData.platformOriDiff =
319 static_cast<float>(targetOrientationGlobal) - measuredOrientation;
329 const Eigen::Rotation2Df local_R_global(-measuredOrientation);
330 const Eigen::Vector2f& vPosError = local_R_global * pidPlatform_.
getControlValue();
331 const Eigen::Vector2f vVelFFRobotFrame =
332 local_R_global * Eigen::Vector2f(trajPoint.jointVelocitiesPlatform.at(0),
333 trajPoint.jointVelocitiesPlatform.at(1));
335 const auto& vFF = trajPoint.jointVelocitiesPlatform;
347 constexpr
float ffFactorPlatform = 1.0;
352 controlTargets_.platformTarget->velocityX =
353 ffFactorPlatform * vVelFFRobotFrame.x() + vPosError.x();
354 controlTargets_.platformTarget->velocityY =
355 ffFactorPlatform * vVelFFRobotFrame.y() + vPosError.y();
361 controlTargets_.platformTarget->velocityRotation =
362 ffFactorPlatform * vFF.at(2) +
370 ARMARX_CHECK_EQUAL(controlTargets_.jointTargets.size(), trajPoint.jointValues.size());
372 trajPoint.jointVelocities.size());
377 const auto toEigen = [](
const std::vector<double>& vec) -> Eigen::VectorXf
379 Eigen::VectorXf eigenVec(vec.size());
380 for (std::size_t i = 0; i < vec.size(); i++)
382 eigenVec(i) =
static_cast<float>(vec.at(i));
390 const Eigen::VectorXf jointPositionTargets =
toEigen(trajPoint.jointValues);
393 Eigen::VectorXf jointPositionMeasured(jointSensorValues_.size());
394 for (std::size_t i = 0; i < jointSensorValues_.size(); i++)
396 jointPositionMeasured(i) = jointSensorValues_.at(i)->position;
401 for (std::size_t i = 0; i < jointSensorValues_.size(); i++)
403 debugData.jointPosDiff.at(i) =
404 std::abs(jointPositionTargets(i) - jointPositionMeasured(i));
408 pidArm_->update(timeSinceLastIteration.toSecondsDouble(),
409 jointPositionMeasured,
410 jointPositionTargets);
413 const Eigen::VectorXf& jointVelocityForPosError = pidArm_->getControlValue();
415 for (std::size_t i = 0; i < controlTargets_.jointTargets.size(); i++)
417 auto*
const jointControlTarget = controlTargets_.jointTargets.at(i);
421 const double jointVelTarget = trajPoint.jointVelocities.at(i);
425 jointControlTarget->velocity =
426 static_cast<float>(jointVelTarget) + jointVelocityForPosError(i);
428 if (not jointControlTarget->isValid())
431 <<
". Value: " << jointControlTarget->velocity;
440 trajPoint.handJointValues.size());
441 for (std::size_t i = 0; i < controlTargets_.handTargets.size(); i++)
443 auto*
const handControlTarget = controlTargets_.handTargets.at(i);
444 const double jointPosTarget = trajPoint.handJointValues.at(i);
445 handControlTarget->position =
static_cast<float>(jointPosTarget);
460 const std::int64_t timestampMicroSeconds =
armarx::rtNow().toMicroSeconds();
462 trajectory_->setStartTime(timestampMicroSeconds);
477 datafields[
"localTimestamp"] =
new Variant(debugData.localTimestamp);
479 datafields[
"platform/dpos"] =
new Variant(debugData.platformPosDiff);
480 datafields[
"platform/dori"] =
new Variant(debugData.platformOriDiff);
483 for (
const auto& [jointName, diff] :
484 ranges::views::zip(jointNames_, debugData.jointPosDiff))
486 datafields[jointName +
"/dpos"] =
new Variant(diff);
489 const float tcpDiff = [&]() ->
float
491 namespace rv = ranges::views;
494 std::map<std::string, float> targetJointValues;
495 for (
const auto& [jointName, jointValue] :
496 rv::zip(jointNames_, debugData.targetState.jointValues))
498 targetJointValues.emplace(jointName, jointValue);
501 const Eigen::Isometry3f targetGlobalPose =
502 Eigen::Translation3f{
503 static_cast<float>(debugData.targetState.jointValuesPlatform.at(0)),
504 static_cast<float>(debugData.targetState.jointValuesPlatform.at(1)),
507 static_cast<float>(debugData.targetState.jointValuesPlatform.at(2)),
508 Eigen::Vector3f::UnitZ()};
510 debugRobot_->setJointValues(targetJointValues);
511 debugRobot_->setGlobalPose(targetGlobalPose.matrix());
513 const Eigen::Isometry3f targetTcpPose(publishTcpNode_->getGlobalPose());
515 const Eigen::Isometry3f tcpDiffTf = debugData.currentTcpPose.inverse() * targetTcpPose;
517 auto batchPrx = debugDrawer->ice_batchOneway();
522 batchPrx->setSphereDebugLayerVisu(
525 ::armarx::DrawColor{1, 0, 0, 0},
528 batchPrx->setSphereDebugLayerVisu(
530 new armarx::Vector3(Eigen::Vector3f{debugData.currentTcpPose.translation()}),
531 ::armarx::DrawColor{0, 1, 0, 0},
534 batchPrx->setPoseDebugLayerVisu(
"tcp_target_pose",
toIce(targetTcpPose.matrix()));
535 batchPrx->setPoseDebugLayerVisu(
"tcp_current_pose",
536 toIce(debugData.currentTcpPose.matrix()));
541 batchPrx->setSphereDebugLayerVisu(
544 ::armarx::DrawColor{1, 0, 0, 0},
547 batchPrx->setSphereDebugLayerVisu(
"platform_current",
549 debugData.currentPlatformPose.translation()}),
550 ::armarx::DrawColor{0, 1, 0, 0},
553 batchPrx->setPoseDebugLayerVisu(
"platform_target_pose",
554 toIce(targetGlobalPose.matrix()));
556 batchPrx->setPoseDebugLayerVisu(
"platform_current_pose",
557 toIce(debugData.currentPlatformPose.matrix()));
560 batchPrx->ice_flushBatchRequests();
564 return tcpDiffTf.translation().norm();
567 datafields[
"tcpDiff"] =
new Variant(tcpDiff);
574 if (whateverFlag_.load())
576 whatever_.push_back(debugData);
583 to_json(nlohmann::json& j,
const TrajectoryPoint& trajectoryPoint)
585 j[
"timestampMicroSeconds"] = trajectoryPoint.timestampMicroSeconds;
586 j[
"jointValues"] = trajectoryPoint.jointValues;
587 j[
"jointValuesPlatform"] = trajectoryPoint.jointValuesPlatform;
588 j[
"handJointValues"] = trajectoryPoint.handJointValues;
589 j[
"jointVelocities"] = trajectoryPoint.jointVelocities;
590 j[
"jointVelocitiesPlatform"] = trajectoryPoint.jointVelocitiesPlatform;
611 whateverFlag_.store(
false);
614 j[
"data"] = whatever_;
619 "controller_execution/" +
filename};
621 ARMARX_INFO <<
"Writing debug data to " << packagePath.toSystemPath();
623 std::ofstream ofs(packagePath.toSystemPath());
624 ofs << std::setw(4) << j << std::endl;