50     for (
unsigned int i = 0; i < entry1->first.size(); ++i)
 
   51       dist += entry1->first[i].distance(entry2->first[i]);
 
   63                               const unsigned int num_joints, 
const Options& opts)
 
   74   std::lock_guard<std::mutex> slock(
lock_);
 
   76   std::filesystem::path prefix(!cached_ik_path.empty() ? std::filesystem::path(cached_ik_path) :
 
   77                                                          std::filesystem::current_path());
 
   79   std::filesystem::create_directories(prefix);
 
   91     std::ifstream cache_file(
cache_file_name_, std::ios_base::binary | std::ios_base::in);
 
   93     unsigned int num_dofs;
 
   94     cache_file.read((
char*)&num_dofs, 
sizeof(
unsigned int));
 
   95     unsigned int num_tips;
 
   96     cache_file.read((
char*)&num_tips, 
sizeof(
unsigned int));
 
   98     RCLCPP_INFO(LOGGER, 
"Found %d IK solutions for a %d-dof system with %d end effectors in %s", 
last_saved_cache_size_,
 
  101     unsigned int position_size = 3 * 
sizeof(tf2Scalar);
 
  102     unsigned int orientation_size = 4 * 
sizeof(tf2Scalar);
 
  103     unsigned int pose_size = position_size + orientation_size;
 
  104     unsigned int config_size = num_dofs * 
sizeof(double);
 
  105     unsigned int offset_conf = pose_size * num_tips;
 
  106     unsigned int bufsize = offset_conf + config_size;
 
  107     char* buffer = 
new char[bufsize];
 
  109     entry.first.resize(num_tips);
 
  110     entry.second.resize(num_dofs);
 
  116       cache_file.read(buffer, bufsize);
 
  117       for (
auto& pose : entry.first)
 
  119         memcpy(&pose.position[0], buffer + j * pose_size, position_size);
 
  120         memcpy(&pose.orientation[0], buffer + j * pose_size + position_size, orientation_size);
 
  123       memcpy(&entry.second[0], buffer + offset_conf, config_size);
 
  126     RCLCPP_INFO(LOGGER, 
"freeing buffer");
 
  128     RCLCPP_INFO(LOGGER, 
"freed buffer");
 
  137   RCLCPP_INFO(LOGGER, 
"cache file %s initialized!", 
cache_file_name_.string().c_str());
 
  142   double dist = 0., diff;
 
  143   for (
unsigned int i = 0; i < config1.size(); ++i)
 
  145     diff = config1[i] - config2[i];
 
  155     static IKEntry dummy = std::make_pair(std::vector<Pose>(1, pose), std::vector<double>(
num_joints_, 0.));
 
  158   IKEntry query = std::make_pair(std::vector<Pose>(1, pose), std::vector<double>());
 
  169   IKEntry query = std::make_pair(poses, std::vector<double>());
 
  178     std::lock_guard<std::mutex> slock(
lock_);
 
  179     ik_cache_.emplace_back(std::vector<Pose>(1u, pose), config);
 
  187                           const std::vector<double>& config)
 const 
  195       for (
unsigned int i = 0; i < poses.size(); ++i)
 
  197         dist += nearest.first[i].distance(poses[i]);
 
  207       std::lock_guard<std::mutex> slock(
lock_);
 
  219     RCLCPP_ERROR(LOGGER, 
"can't save cache before initialization");
 
  223   std::ofstream cache_file(
cache_file_name_, std::ios_base::binary | std::ios_base::out);
 
  224   unsigned int position_size = 3 * 
sizeof(tf2Scalar);
 
  225   unsigned int orientation_size = 4 * 
sizeof(tf2Scalar);
 
  226   unsigned int pose_size = position_size + orientation_size;
 
  227   unsigned int num_tips = 
ik_cache_[0].first.size();
 
  228   unsigned int config_size = 
ik_cache_[0].second.size() * 
sizeof(double);
 
  229   unsigned int offset_conf = num_tips * pose_size;
 
  230   unsigned int bufsize = offset_conf + config_size;
 
  231   char* buffer = 
new char[bufsize];
 
  236   unsigned int sz = 
ik_cache_[0].second.size();
 
  237   cache_file.write((
char*)&sz, 
sizeof(
unsigned int));
 
  238   cache_file.write((
char*)&num_tips, 
sizeof(
unsigned int));
 
  241     for (
unsigned int i = 0; i < num_tips; ++i)
 
  243       memcpy(buffer + i * pose_size, &entry.first[i].position[0], position_size);
 
  244       memcpy(buffer + i * pose_size + position_size, &entry.first[i].orientation[0], orientation_size);
 
  246     memcpy(buffer + offset_conf, &entry.second[0], config_size);
 
  247     cache_file.write(buffer, bufsize);
 
  254   const std::vector<std::string>& tip_names(fk.
getTipFrames());
 
  255   std::vector<geometry_msgs::msg::Pose> poses(tip_names.size());
 
  256   double error, max_error = 0.;
 
  262     for (
unsigned int i = 0; i < poses.size(); ++i)
 
  263       error += entry.first[i].distance(poses[i]);
 
  265       error /= (double)poses.size();
 
  266     if (error > max_error)
 
  269       RCLCPP_ERROR(LOGGER, 
"Cache entry is invalid, error = %g", error);
 
  271   RCLCPP_INFO(LOGGER, 
"Max. error in cache entries is %g", max_error);
 
  279   orientation = tf2::Quaternion(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w);
 
  284   return (position - pose.
position).length() + (orientation.angleShortestPath(pose.
orientation));
 
  288   : robot_description_(robot_description), group_name_(group_name), 
num_joints_(num_joints)
 
  294   for (
auto& cache : *
this)
 
  299                                                                  const std::vector<std::string>& active,
 
  300                                                                  const std::vector<Pose>& poses)
 const 
  302   auto key(
getKey(fixed, active));
 
  305     return it->second->getBestApproximateIKSolution(poses);
 
  314                              const std::vector<std::string>& active, 
const std::vector<Pose>& poses,
 
  315                              const std::vector<double>& config)
 
  317   auto key(
getKey(fixed, active));
 
  320     it->second->updateCache(nearest, poses, config);
 
  323     value_type val = std::make_pair(key, 
nullptr);
 
  324     auto it = insert(val).first;
 
  330 std::string 
IKCacheMap::getKey(
const std::vector<std::string>& fixed, 
const std::vector<std::string>& active)
 const 
  333   std::accumulate(fixed.begin(), fixed.end(), key);
 
  335   std::accumulate(active.begin(), active.end(), key);
 
const IKEntry & getBestApproximateIKSolution(const std::vector< std::string > &fixed, const std::vector< std::string > &active, const std::vector< Pose > &poses) const
 
std::string getKey(const std::vector< std::string > &fixed, const std::vector< std::string > &active) const
 
std::string robot_description_
 
void updateCache(const IKEntry &nearest, const std::vector< std::string > &fixed, const std::vector< std::string > &active, const std::vector< Pose > &poses, const std::vector< double > &config)
 
IKCacheMap(const std::string &robot_description, const std::string &group_name, unsigned int num_joints)
 
A cache of inverse kinematic solutions.
 
double min_pose_distance_
 
unsigned int max_cache_size_
 
const IKEntry & getBestApproximateIKSolution(const Pose &pose) const
 
std::pair< std::vector< Pose >, std::vector< double > > IKEntry
 
unsigned int last_saved_cache_size_
 
void verifyCache(kdl_kinematics_plugin::KDLKinematicsPlugin &fk) const
 
NearestNeighborsGNAT< IKEntry * > ik_nn_
 
double configDistance2(const std::vector< double > &config1, const std::vector< double > &config2) const
 
std::filesystem::path cache_file_name_
 
void initializeCache(const std::string &robot_id, const std::string &group_name, const std::string &cache_name, const unsigned int num_joints, const Options &opts=Options())
 
double min_config_distance2_
 
void updateCache(const IKEntry &nearest, const Pose &pose, const std::vector< double > &config) const
 
std::vector< IKEntry > ik_cache_
 
void setDistanceFunction(const typename NearestNeighbors< _T >::DistanceFunction &distFun) override
 
void add(const _T &data) override
Add an element to the datastructure.
 
void clear() override
Clear the datastructure.
 
_T nearest(const _T &data) const override
Get the nearest neighbor of a point.
 
Specific implementation of kinematics using KDL. This version supports any kinematic chain,...
 
bool getPositionFK(const std::vector< std::string > &link_names, const std::vector< double > &joint_angles, std::vector< geometry_msgs::msg::Pose > &poses) const override
Given a set of joint angles and a set of links, compute their pose.
 
virtual const std::vector< std::string > & getTipFrames() const
Return the names of the tip frames of the kinematic tree on which the solver is operating....
 
double min_joint_config_distance
 
std::string cached_ik_path
 
unsigned int max_cache_size
 
class to represent end effector pose
 
double distance(const Pose &pose) const
 
tf2::Quaternion orientation