31 #include <type_traits>
32 #include <console_bridge/console.h>
48 template bool isIdentical<std::string>(
const std::vector<std::string>&,
49 const std::vector<std::string>&,
51 const std::function<
bool(
const std::string&,
const std::string&)>&,
52 const std::function<
bool(
const std::string&,
const std::string&)>&);
53 template bool isIdentical<Eigen::Index>(
const std::vector<Eigen::Index>&,
54 const std::vector<Eigen::Index>&,
56 const std::function<
bool(
const Eigen::Index&,
const Eigen::Index&)>&,
57 const std::function<
bool(
const Eigen::Index&,
const Eigen::Index&)>&);
70 const auto* p =
dynamic_cast<const std::nested_exception*
>(std::addressof(e));
71 if (p && p->nested_ptr())
77 std::ifstream ifs(filepath.c_str());
80 ifs.seekg(0, std::ios::end);
81 contents.reserve(ifs.tellg());
82 ifs.seekg(0, std::ios::beg);
84 contents.assign(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
91 void twistChangeRefPoint(Eigen::Ref<Eigen::VectorXd> twist,
const Eigen::Ref<const Eigen::Vector3d>& ref_point)
93 twist(0) += twist(4) * ref_point(2) - twist(5) * ref_point(1);
94 twist(1) += twist(5) * ref_point(0) - twist(3) * ref_point(2);
95 twist(2) += twist(3) * ref_point(1) - twist(4) * ref_point(0);
98 void twistChangeBase(Eigen::Ref<Eigen::VectorXd> twist,
const Eigen::Isometry3d& change_base)
100 twist.head(3) = change_base.linear() * twist.head(3);
101 twist.tail(3) = change_base.linear() * twist.tail(3);
106 assert(jacobian.rows() == 6);
107 for (
int i = 0; i < jacobian.cols(); i++)
113 assert(jacobian.rows() == 6);
114 for (
int i = 0; i < jacobian.cols(); i++)
119 Eigen::VectorXd
concat(
const Eigen::VectorXd& a,
const Eigen::VectorXd& b)
121 Eigen::VectorXd out(a.size() + b.size());
122 out.topRows(a.size()) = a;
123 out.middleRows(a.size(), b.size()) = b;
129 Eigen::Quaterniond q(R);
130 Eigen::AngleAxisd r12(q);
134 int s = (q.vec().dot(r12.axis()) < 0) ? -1 : 1;
137 const static double two_pi = 2.0 * M_PI;
138 double angle = s * r12.angle();
139 Eigen::Vector3d axis{ s * r12.axis() };
140 angle = copysign(fmod(fabs(angle), two_pi), angle);
143 else if (angle > M_PI)
146 assert(std::abs(angle) <= M_PI);
148 return { axis, angle };
154 return data.first * data.second;
159 Eigen::Isometry3d pose_err = t1.inverse() * t2;
164 const Eigen::Isometry3d& source,
165 const Eigen::Isometry3d& source_perturbed)
167 Eigen::Isometry3d pose_err = target.inverse() * source;
169 Eigen::VectorXd err =
concat(pose_err.translation(), pose_rotation_err.first * pose_rotation_err.second);
171 Eigen::Isometry3d perturbed_pose_err = target.inverse() * source_perturbed;
172 std::pair<Eigen::Vector3d, double> perturbed_pose_rotation_err =
176 if (perturbed_pose_rotation_err.first.dot(pose_rotation_err.first) < 0)
178 perturbed_pose_rotation_err.first *= -1;
179 perturbed_pose_rotation_err.second *= -1;
183 Eigen::VectorXd perturbed_err;
184 if (perturbed_pose_rotation_err.second > M_PI_2 && pose_rotation_err.second < -M_PI_2)
185 perturbed_err =
concat(perturbed_pose_err.translation(),
186 perturbed_pose_rotation_err.first * (perturbed_pose_rotation_err.second - (2 * M_PI)));
187 else if (perturbed_pose_rotation_err.second < -M_PI_2 && pose_rotation_err.second > M_PI_2)
188 perturbed_err =
concat(perturbed_pose_err.translation(),
189 perturbed_pose_rotation_err.first * (perturbed_pose_rotation_err.second + (2 * M_PI)));
191 perturbed_err =
concat(perturbed_pose_err.translation(),
192 perturbed_pose_rotation_err.first * perturbed_pose_rotation_err.second);
194 return (perturbed_err - err);
198 const Eigen::Isometry3d& target_perturbed,
199 const Eigen::Isometry3d& source,
200 const Eigen::Isometry3d& source_perturbed)
202 Eigen::Isometry3d pose_err = target.inverse() * source;
204 Eigen::VectorXd err =
concat(pose_err.translation(), pose_rotation_err.first * pose_rotation_err.second);
206 Eigen::Isometry3d perturbed_pose_err = target_perturbed.inverse() * source_perturbed;
207 std::pair<Eigen::Vector3d, double> perturbed_pose_rotation_err =
212 if (std::abs(pose_rotation_err.second) > 0.01 && perturbed_pose_rotation_err.first.dot(pose_rotation_err.first) < 0)
213 throw std::runtime_error(
"calcJacobianTransformErrorDiff, angle axes are pointing in oposite directions!");
217 Eigen::VectorXd perturbed_err;
218 if (perturbed_pose_rotation_err.second > M_PI_2 && pose_rotation_err.second < -M_PI_2)
219 perturbed_err =
concat(perturbed_pose_err.translation(),
220 perturbed_pose_rotation_err.first * (perturbed_pose_rotation_err.second - (2 * M_PI)));
221 else if (perturbed_pose_rotation_err.second < -M_PI_2 && pose_rotation_err.second > M_PI_2)
222 perturbed_err =
concat(perturbed_pose_err.translation(),
223 perturbed_pose_rotation_err.first * (perturbed_pose_rotation_err.second + (2 * M_PI)));
225 perturbed_err =
concat(perturbed_pose_err.translation(),
226 perturbed_pose_rotation_err.first * perturbed_pose_rotation_err.second);
228 return (perturbed_err - err);
239 c[0] = (rand() % 100) / 100.0;
240 c[1] = (rand() % 100) / 100.0;
241 c[2] = (rand() % 100) / 100.0;
248 std::cerr << std::string(static_cast<unsigned>(2 * level),
' ') <<
"exception: " << e.what() <<
"\n";
253 catch (
const std::exception& e)
264 return std::filesystem::temp_directory_path().string() + std::string(1, std::filesystem::path::preferred_separator);
272 std::stringstream ss;
273 ss.imbue(std::locale::classic());
280 return !ss.fail() && ss.eof();
285 return std::all_of(sv.cbegin(), sv.cend(), [](
const std::string& s) { return isNumeric(s); });
290 Eigen::VectorXd joint_values;
291 joint_values.resize(limits.rows());
292 for (
long i = 0; i < limits.rows(); ++i)
294 std::uniform_real_distribution<double> sample(limits(i, 0), limits(i, 1));
300 void ltrim(std::string& s) { s.erase(0, s.find_first_not_of(
" \n\r\t\f\v")); }
302 void rtrim(std::string& s) { s.erase(s.find_last_not_of(
" \n\r\t\f\v") + 1); }
312 std::ostringstream oss;
313 auto t = std::time(
nullptr);
314 auto tm = *std::localtime(&t);
315 oss << std::put_time(&tm,
"%d-%m-%Y-%H-%M-%S");
319 void reorder(Eigen::Ref<Eigen::VectorXd> v, std::vector<Eigen::Index> order)
321 assert(v.rows() ==
static_cast<Eigen::Index
>(order.size()));
323 for (std::size_t i = 0; i < order.size() - 1; ++i)
325 if (order[i] ==
static_cast<Eigen::Index
>(i))
329 for (j = i + 1; j < order.size(); ++j)
331 if (order[j] ==
static_cast<Eigen::Index
>(i))
334 std::swap(v[
static_cast<Eigen::Index
>(i)], v[order[i]]);
335 std::swap(order[i], order[j]);
341 if (xml_element->Value() ==
nullptr)
342 return tinyxml2::XML_NO_ATTRIBUTE;
344 value = std::string(xml_element->Value());
346 return tinyxml2::XML_SUCCESS;
351 if (xml_element->GetText() ==
nullptr)
352 return tinyxml2::XML_NO_ATTRIBUTE;
354 text = std::string(xml_element->GetText());
356 return tinyxml2::XML_SUCCESS;
361 if (xml_attribute->Value() ==
nullptr)
362 return tinyxml2::XML_WRONG_ATTRIBUTE_TYPE;
364 value = std::string(xml_attribute->Value());
366 return tinyxml2::XML_SUCCESS;
371 const tinyxml2::XMLAttribute* attribute = xml_element->FindAttribute(name);
372 if (attribute ==
nullptr)
373 return tinyxml2::XML_NO_ATTRIBUTE;
378 std::string
StringAttribute(
const tinyxml2::XMLElement* xml_element,
const char* name, std::string default_value)
380 std::string str = std::move(default_value);
389 if (status != tinyxml2::XML_NO_ATTRIBUTE && status != tinyxml2::XML_SUCCESS)
391 CONSOLE_BRIDGE_logError(
"Invalid %s attribute '%s'", xml_element->Name(), name);
393 else if (status == tinyxml2::XML_NO_ATTRIBUTE)
395 CONSOLE_BRIDGE_logError(
"Missing %s required attribute '%s'", xml_element->Name(), name);
397 else if (status == tinyxml2::XML_WRONG_ATTRIBUTE_TYPE)
399 CONSOLE_BRIDGE_logError(
"Invalid %s attribute type '%s'", xml_element->Name(), name);
407 int status = xml_element->QueryDoubleAttribute(name, &value);
409 if (status != tinyxml2::XML_NO_ATTRIBUTE && status != tinyxml2::XML_SUCCESS)
411 CONSOLE_BRIDGE_logError(
"Invalid %s attribute '%s'", xml_element->Name(), name);
413 else if (status == tinyxml2::XML_NO_ATTRIBUTE)
415 CONSOLE_BRIDGE_logError(
"Missing %s required attribute '%s'", xml_element->Name(), name);
417 else if (status == tinyxml2::XML_WRONG_ATTRIBUTE_TYPE)
419 CONSOLE_BRIDGE_logError(
"Invalid %s attribute type '%s'", xml_element->Name(), name);
427 int status = xml_element->QueryIntAttribute(name, &value);
429 if (status != tinyxml2::XML_NO_ATTRIBUTE && status != tinyxml2::XML_SUCCESS)
431 CONSOLE_BRIDGE_logError(
"Invalid %s attribute '%s'", xml_element->Name(), name);
433 else if (status == tinyxml2::XML_NO_ATTRIBUTE)
435 CONSOLE_BRIDGE_logError(
"Missing %s required attribute '%s'", xml_element->Name(), name);
437 else if (status == tinyxml2::XML_WRONG_ATTRIBUTE_TYPE)
439 CONSOLE_BRIDGE_logError(
"Invalid %s attribute type '%s'", xml_element->Name(), name);
447 double diff = std::fabs(a - b);
448 if (diff <= max_diff)
453 double largest = (b > a) ? b : a;
455 return (diff <= largest * max_rel_diff);
459 const Eigen::Ref<const Eigen::VectorXd>& v2,
463 const auto eigen_max_diff = Eigen::VectorXd::Constant(v1.size(), max_diff);
464 const auto eigen_max_rel_diff = Eigen::VectorXd::Constant(v1.size(), max_rel_diff);
470 const Eigen::Ref<const Eigen::VectorXd>& v2,
471 const Eigen::Ref<const Eigen::VectorXd>& max_diff,
472 const Eigen::Ref<const Eigen::VectorXd>& max_rel_diff)
474 if (v1.size() == 0 && v2.size() == 0)
476 if (v1.size() != v2.size() || v1.size() != max_diff.size() || v1.size() != max_rel_diff.size())
479 Eigen::ArrayWrapper<const Eigen::Ref<const Eigen::VectorXd>> a1 = v1.array();
480 Eigen::ArrayWrapper<const Eigen::Ref<const Eigen::VectorXd>> a2 = v2.array();
481 Eigen::ArrayWrapper<const Eigen::Ref<const Eigen::VectorXd>> md = max_diff.array();
482 Eigen::ArrayWrapper<const Eigen::Ref<const Eigen::VectorXd>> mrd = max_rel_diff.array();
484 auto diff_abs = (a1 - a2).abs();
485 double diff = diff_abs.maxCoeff();
486 if ((diff <= md).all())
489 return (diff_abs <= (mrd * a1.abs().max(a2.abs()))).all();
494 bool remove_duplicates)
496 std::vector<std::string> results;
497 results.reserve(acm_entries.size());
499 for (
const auto& entry : acm_entries)
501 const std::string link_1 = entry.first.first;
502 const std::string link_2 = entry.first.second;
505 if (std::find(link_names.begin(), link_names.end(), link_1) != link_names.end())
507 if (!remove_duplicates || (std::find(results.begin(), results.end(), link_2) == results.end()))
508 results.push_back(link_2);
510 if (std::find(link_names.begin(), link_names.end(), link_2) != link_names.end())
511 if (!remove_duplicates || (std::find(results.begin(), results.end(), link_1) == results.end()))
512 results.push_back(link_1);