10 #include <boost/tokenizer.hpp>
12 #include <VirtualRobot/MathTools.h>
24 nlohmann::json& defaultConfig,
25 const std::string& entryName,
29 if (userConfig.find(entryName) != userConfig.end())
31 auto vec = userConfig[entryName].get<std::vector<float>>();
34 return Eigen::Map<Eigen::VectorXf>(vec.data(), vec.size());
38 return Eigen::VectorXf::Ones(size) *
value;
41 <<
" have size 0, fall back to default";
44 auto vec = defaultConfig[entryName].get<std::vector<float>>();
45 return Eigen::Map<Eigen::VectorXf>(vec.data(), vec.size());
49 getEigenMatrix(nlohmann::json& userConfig,
const std::string& entryName, Eigen::MatrixXf& mat)
51 if (userConfig.find(entryName) != userConfig.end())
53 auto vec = userConfig[entryName].get<std::vector<std::vector<float>>>();
54 int rows = vec.size();
55 int cols = vec[0].size();
59 mat.resize(rows, cols);
60 for (
int i = 0; i < rows; i++)
62 for (
int j = 0; j < cols; j++)
64 mat(i, j) = vec[i][j];
77 Eigen::VectorXf defaultValue,
78 const std::string& entryName)
80 if (userConfig.find(entryName) != userConfig.end())
82 auto vec = userConfig[entryName].get<std::vector<float>>();
83 if (vec.size() ==
static_cast<unsigned>(defaultValue.size()))
85 return Eigen::Map<Eigen::VectorXf>(vec.data(), vec.size());
87 ARMARX_WARNING <<
"size of the user defined parameter " << entryName
88 <<
" doesn't correspond to default size, use default value instead";
95 Eigen::Vector3d& targetPosition,
100 Eigen::Matrix4d currentPosed = currentPose.cast<
double>();
101 Eigen::Vector3d currentPosid = currentPosed.block<3, 1>(0, 3);
102 posiError = (currentPosid - targetPosition).
norm();
105 oriError = targetQuaternion.angularDistance(currentOrientation);
108 oriError = 2 *
M_PI - oriError;
115 Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen4f2rpy(pose);
116 datafields[name +
"_x"] =
new Variant(pose(0, 3));
117 datafields[name +
"_y"] =
new Variant(pose(1, 3));
118 datafields[name +
"_z"] =
new Variant(pose(2, 3));
119 datafields[name +
"_rx"] =
new Variant(rpy(0));
120 datafields[name +
"_ry"] =
new Variant(rpy(1));
121 datafields[name +
"_rz"] =
new Variant(rpy(2));
127 for (
int i = 0; i < vec.size(); i++)
136 for (
size_t i = 0; i < vec.size(); i++)
145 j = nlohmann::json{{
"qw", fp.orientation->qw},
146 {
"qx", fp.orientation->qx},
147 {
"qy", fp.orientation->qy},
148 {
"qz", fp.orientation->qz},
149 {
"x", fp.position->x},
150 {
"y", fp.position->y},
151 {
"z", fp.position->z}};
157 j.at(
"qw").get_to(fp.orientation->qw);
158 j.at(
"qx").get_to(fp.orientation->qx);
159 j.at(
"qy").get_to(fp.orientation->qy);
160 j.at(
"qz").get_to(fp.orientation->qz);
161 j.at(
"x").get_to(fp.position->x);
162 j.at(
"y").get_to(fp.position->y);
163 j.at(
"z").get_to(fp.position->z);
176 to_json(nlohmann::json& j,
const PoseBasePtr& fp)
180 to_json(j, PosePtr::dynamicCast(fp));
199 Eigen::Block<Eigen::Matrix4f, 3, 3>
202 return matrix.block<3, 3>(0, 0);
208 return matrix.block<3, 3>(0, 0);
211 Eigen::Block<Eigen::Matrix4f, 3, 1>
214 return matrix.block<3, 1>(0, 3);
220 return matrix.block<3, 1>(0, 3);
233 Eigen::Matrix4f mat = VirtualRobot::MathTools::quat2eigen4f(
static_cast<float>(dvec[4]),
234 static_cast<float>(dvec[5]),
235 static_cast<float>(dvec[6]),
236 static_cast<float>(dvec[3]));
237 mat(0, 3) =
static_cast<float>(dvec[0]);
238 mat(1, 3) =
static_cast<float>(dvec[1]);
239 mat(2, 3) =
static_cast<float>(dvec[2]);
254 std::vector<double> result;
257 for (
size_t i = 0; i < 3; ++i)
259 result.at(i) =
static_cast<double>(mat(i, 3));
264 result.at(3) =
static_cast<double>(quat.w);
265 result.at(4) =
static_cast<double>(quat.x);
266 result.at(5) =
static_cast<double>(quat.y);
267 result.at(6) =
static_cast<double>(quat.z);
282 std::vector<float> result;
285 for (
size_t i = 0; i < 3; ++i)
287 result.at(i) = mat(i, 3);
292 result.at(3) = quat.w;
293 result.at(4) = quat.x;
294 result.at(5) = quat.y;
295 result.at(6) = quat.z;
304 for (
const double& d : dvec)
314 return Eigen::Map<Eigen::VectorXf>(vec.data(), vec.size());
318 sVecToString(
const std::vector<std::string>& vec,
const std::string& delimiter)
321 for (
size_t i = 0; i < vec.size(); ++i)
335 std::vector<double> timesteps;
336 std::vector<std::vector<double>> trajPoses;
338 std::ifstream f(filepath.c_str());
345 using Tokenizer = boost::tokenizer<boost::escaped_list_separator<char>>;
351 double current_time = 0;
353 std::vector<std::string> stringVec;
354 while (getline(f, line))
356 if (containsHeader && i == 1)
363 stringVec.assign(tok.begin(), tok.end());
365 if (stringVec.size() == 0)
367 std::cout <<
"Line " << i <<
" is invalid skipping: " << line << std::endl;
373 armarx::control::common::mp::arondto::MPTraj traj;
376 int size = stringVec.size() - 1;
381 timesteps.push_back(current_time);
382 current_time += 0.01;
383 size = stringVec.size();
388 timesteps.push_back(std::stod(stringVec[0]));
393 std::vector<double> currentPose;
395 for (
unsigned int k = j; k < stringVec.size(); ++k)
397 currentPose.push_back(std::stod(stringVec[k]));
401 trajPoses.push_back(currentPose);
407 if (timesteps.size() != trajPoses.size())
409 ARMARX_ERROR <<
"consistency error in reading trajectory";
411 armarx::control::common::mp::arondto::MPTraj taskTraj;
412 taskTraj.time.setZero(timesteps.size());
413 taskTraj.traj.setZero(timesteps.size(), trajPoses.at(0).size());
416 for (
unsigned int l = 0; l < timesteps.size(); l++)
418 taskTraj.time(l) = timesteps.at(l);
419 for (
size_t j = 0; j < trajPoses.at(0).size(); ++j)
420 taskTraj.traj(l, j) = trajPoses.at(l).at(j);
428 mp::arondto::MPTraj traj;
429 traj.time = Eigen::VectorXd::LinSpaced(timesteps, 0, 1);
430 traj.traj = Eigen::MatrixXd::Zero(timesteps, dimension);
434 mp::arondto::MPConfig
436 const std::string& name,
437 const std::string& nodeSetName,
438 const double& durationSec,
439 const std::vector<mp::arondto::MPTraj>& mpTraj,
440 const std::vector<mp::arondto::ListViaPoint>& viaPointList)
444 "armarx_control",
"controller_config/mp/default_mp_" + className +
".json");
446 auto cfg = armarx::readFromJson<mp::arondto::MPConfig>(configPath.
toSystemPath());
448 cfg.nodeSetName = nodeSetName;
449 if (durationSec > 0.0)
450 cfg.durationSec = durationSec;
451 if (mpTraj.size() > 0)
452 cfg.trajectoryList = mpTraj;
453 if (viaPointList.size() > 0)
454 cfg.viaPoints = viaPointList;
458 mp::arondto::MPConfig
460 const std::string& name,
461 const std::string& nodeSetName,
462 const double& durationSec,
463 const std::vector<std::string>& mpTraj,
464 const std::vector<mp::arondto::ListViaPoint>& viaPointList)
466 std::vector<mp::arondto::MPTraj> mpTrajList{};
467 for (
auto& f : mpTraj)
471 return getDefaultMPConfig(mpType, name, nodeSetName, durationSec, mpTrajList, viaPointList);
476 const double& canValue,
477 const std::vector<double>& viaPoint)
479 auto vp = mp::arondto::ListViaPoint();
480 vp.canonicalValue = canValue;
481 vp.viaPointValue = viaPoint;
482 cfg.viaPoints.push_back(vp);
487 const double& canValue,
488 const std::vector<float>& viaPoint)
490 std::vector<double> viaPointVec;
493 std::back_inserter(viaPointVec),
494 [](
float value) { return static_cast<double>(value); });
499 addViaPoint(mp::arondto::MPConfig& cfg,
const double& canValue,
const Eigen::VectorXf& viaPoint)
501 std::vector<double> viaPointVec;
503 viaPoint.data() + viaPoint.size(),
504 std::back_inserter(viaPointVec),
505 [](
float value) { return static_cast<double>(value); });
519 if (viaPoint.size() != 7 || viaPointReference.size() != 7)
521 ARMARX_ERROR <<
"Both viapoints must have exactly 7 elements";
524 bool allDifferentSigns =
true;
527 for (
int i = 3; i < 7; ++i)
529 if ((viaPoint[i] * viaPointReference[i]) >= 0)
531 allDifferentSigns =
false;
537 if (allDifferentSigns)
539 ARMARX_INFO <<
"===> Viapoints for TS Orientation on two hemisphere, flipping sign";
540 for (
int i = 3; i < 7; ++i)
542 viaPoint[i] = -viaPoint[i];
549 const double canonicalValue,
550 const std::vector<double>& viaPoint)
552 mp::arondto::ListViaPoint vp;
553 vp.canonicalValue = canonicalValue;
554 vp.viaPointValue = viaPoint;
555 vpList.push_back(vp);
560 const double canonicalValue,
561 const std::vector<float>& viaPoint)
563 std::vector<double> viaPointVec;
566 std::back_inserter(viaPointVec),
567 [](
float value) { return static_cast<double>(value); });
573 const double canonicalValue,
574 const Eigen::VectorXf& viaPoint)
576 std::vector<double> viaPointVec;
578 viaPoint.data() + viaPoint.size(),
579 std::back_inserter(viaPointVec),
580 [](
float value) { return static_cast<double>(value); });
586 const double canonicalValue,
597 Eigen::AngleAxisf oriDiffAngleAxis;
598 oriDiffAngleAxis.fromRotationMatrix(poseDiffMatImp);
599 float angle = VirtualRobot::MathTools::angleModPI(oriDiffAngleAxis.angle());
617 return (desiredPose.block<3, 1>(0, 3) - currentPose.block<3, 1>(0, 3)).norm() >
619 angle > VirtualRobot::MathTools::deg2rad(angleThrDeg);
626 const std::string& namePose1,
627 const std::string& namePose2)
629 auto quat1 = VirtualRobot::MathTools::eigen4f2quat(pose1);
630 auto quat2 = VirtualRobot::MathTools::eigen4f2quat(pose2);
632 << namePose2 <<
" (x, y, z, qw, qx, qy, qz) \n\n"
634 << pose2(0, 3) <<
", " << pose2(1, 3) <<
", " << pose2(2, 3) <<
", "
635 << quat2.w <<
", " << quat2.x <<
", " << quat2.y <<
", " << quat2.z
637 <<
" is too far away from the "
638 << namePose1 <<
" (x, y, z, qw, qx, qy, qz) \n\n"
640 << pose1(0, 3) <<
", " << pose1(1, 3) <<
", " << pose1(2, 3) <<
", "
641 << quat1.w <<
", " << quat1.x <<
", " << quat1.y <<
", " << quat1.z
648 const std::string& namePose1,
649 const std::string& namePose2,
652 const std::string& who)
655 float dist = (pose2.block<3, 1>(0, 3) - pose1.block<3, 1>(0, 3)).
norm();
658 dist > positionThrMM or
angle > VirtualRobot::MathTools::deg2rad(angleThrDeg);
672 convert << 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1;
673 return sourcePose.cwiseProduct(
convert);
680 convert << 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1;
681 return sourcePose.cwiseProduct(
convert);
688 convert << 1, -1, -1, -1, 1, 1, -1, 1, 1;
689 return sourcePose.cwiseProduct(
convert);