3 #include <boost/property_tree/ptree.hpp> 4 #include <boost/property_tree/xml_parser.hpp> 9 #include <unordered_set> 24 std::string exec(
const char *cmd)
26 std::shared_ptr<FILE> pipe(popen(cmd,
"r"), pclose);
30 std::string result =
"";
31 while (!feof(pipe.get()))
33 if (fgets(buffer, 128, pipe.get()) != NULL)
56 for (
auto joint_position :
joints_)
58 if (joint_position.joint_name_ == joint)
60 return joint_position.position_;
64 return std::numeric_limits<double>::quiet_NaN();
69 for (
unsigned int i =
joints_.size(); i > 0; --i)
73 if (!used_joints.at(
joints_[i - 1].joint_name_))
78 catch (std::out_of_range &e)
87 const std::vector<std::string> &names)
const 92 for (
auto joint_name : names)
107 if (std::find(names.begin(), names.end(), joint.joint_name_) != names.end())
109 pm.
joints_.push_back(joint.joint_name_);
122 Motion::Motion(
const std::string &robot_description,
const std::string &robot_description_semantic,
123 const std::vector<std::string> &extra_joints)
127 if (robot_description !=
"" && robot_description_semantic !=
"")
135 if (group.second.size() >=
size)
138 size = group.second.size();
145 for (
const auto &joint : extra_joints)
148 if (std::find(existing_joints.begin(), existing_joints.end(), joint) ==
149 existing_joints.end())
155 const std::string &robot_description_semantic,
156 const std::vector<std::string> &extra_joints)
157 :
Motion(robot_description, robot_description_semantic, extra_joints)
163 std::vector<std::string> names;
164 for (
int i = 0; i < param[
"joints"].
size(); ++i)
166 names.push_back(static_cast<std::string>(param[
"joints"][i]));
173 joint.second = std::find(names.begin(), names.end(), joint.first) != names.end();
177 std::string group_used =
"";
182 if (group.second.size() <= names.size() && group.second.size() >
size)
185 bool all_used =
true;
186 for (
const std::string &joint : group.second)
188 if (std::find(names.begin(), names.end(), joint) == names.end())
190 ROS_INFO_STREAM(
"Joint " << joint <<
" from group " << group.first <<
" not in use");
199 size = group.second.size();
200 group_used = group.first;
206 ROS_INFO_STREAM(
"Group " << group.first <<
" discarded (" << group.second.size()
207 <<
"<=" << names.size() <<
" && " << group.second.size()
208 <<
">" << size <<
")");
216 float last_time = 0.0f;
217 for (
int i = 0; i < param[
"points"].
size(); ++i)
221 for (
int j = 0; j < param[
"points"][i][
"positions"].
size(); ++j)
233 const std::string &robot_description_semantic)
236 boost::property_tree::ptree tree_robot;
237 std::stringstream ss_robot(robot_description);
238 boost::property_tree::read_xml(ss_robot, tree_robot);
241 std::unordered_set<std::string> actuable_joints;
242 for (boost::property_tree::ptree::value_type &joint : tree_robot.get_child(
"robot"))
244 if (joint.first !=
"joint")
248 std::string joint_name;
249 bool is_actuable =
true;
250 for (boost::property_tree::ptree::value_type &joint_child : joint.second)
252 if (joint_child.first ==
"<xmlattr>")
254 for (boost::property_tree::ptree::value_type &joint_att : joint_child.second)
256 if (joint_att.first ==
"name")
258 joint_name = joint_att.second.data();
260 else if (joint_att.first ==
"type" && joint_att.second.data() ==
"fixed")
268 actuable_joints.insert(joint_name);
274 boost::property_tree::ptree tree_semantic;
275 std::stringstream ss_semantic(robot_description_semantic);
276 boost::property_tree::read_xml(ss_semantic, tree_semantic);
279 std::vector<std::pair<std::string, std::string>> pending_groups_;
280 for (boost::property_tree::ptree::value_type &group : tree_semantic.get_child(
"robot"))
282 if (group.first !=
"group")
286 std::string group_name =
"";
287 for (boost::property_tree::ptree::value_type &group_child : group.second)
289 if (group_child.first ==
"<xmlattr>")
291 for (boost::property_tree::ptree::value_type &group_att : group_child.second)
293 if (group_att.first ==
"name")
295 group_name = group_att.second.data();
300 else if (group_child.first ==
"joint")
302 for (boost::property_tree::ptree::value_type &joint_att :
303 group_child.second.get_child(
"<xmlattr>"))
306 if (joint_att.first ==
"name" &&
307 actuable_joints.find(joint_att.second.data()) != actuable_joints.end())
310 ROS_DEBUG_STREAM(
"Add joint " << joint_att.second.data() <<
" to " << group_name);
314 else if (group_child.first ==
"group")
316 for (boost::property_tree::ptree::value_type &subgroup_att :
317 group_child.second.get_child(
"<xmlattr>"))
319 if (subgroup_att.first ==
"name")
323 pending_groups_.push_back(std::make_pair(group_name, subgroup_att.second.data()));
324 ROS_DEBUG_STREAM(
"Wait for group" << subgroup_att.second.data() <<
" to be loaded");
326 ROS_DEBUG_STREAM(
"Add group " << subgroup_att.second.data() <<
" to " << group_name);
333 for (
const auto &pair : pending_groups_)
343 std::string random =
"";
344 static const char num[] =
"0123456789";
345 for (
int i = 0; i < 5; ++i)
347 random.append(std::to_string(num[rand() % (
sizeof(num) - 1)]));
362 for (
unsigned int i = 0; i < msg->name.size(); ++i)
376 it !=
keyframes_[frame].getJoints().end(); ++it)
378 for (
unsigned int i = 0; i < msg->name.size(); ++i)
380 if (msg->name[i] == it->joint_name_)
382 it->position_ = msg->position[i];
396 if ((
unsigned long)frame >=
keyframes_.size())
399 throw ros::Exception(
"Keyframe " + std::to_string(frame) +
" doesn't exist");
407 if ((
unsigned long)frame >=
keyframes_.size())
410 throw ros::Exception(
"Keyframe " + std::to_string(frame) +
" doesn't exist");
414 it !=
keyframes_[frame].getJoints().end(); ++it)
416 if (it->joint_name_ == joint_name)
420 it->position_ = position;
423 return it->position_;
445 if (new_frame_pos < 0)
460 << YAML::Key <<
"play_motion" 461 << YAML::Value << YAML::BeginMap
462 << YAML::Key <<
"motions" 463 << YAML::Value << YAML::BeginMap
481 << YAML::Key <<
"play_motion" 482 << YAML::Value << YAML::BeginMap
483 << YAML::Key <<
"motions" 484 << YAML::Value << YAML::BeginMap
486 << YAML::Value <<
print(downshift)
499 for (
unsigned int i = 0; i < msg->name.size(); ++i)
505 if (std::isnan(it->getJointPosition(msg->name[i])))
507 it->addPosition(msg->name[i], msg->position[i]);
543 return print(
"",
"",
"", downshift);
552 const std::string &description,
double downshift)
const 557 double basetime = 0.0;
560 pm.
points_.push_back(frame.print(basetime, downshift, pm.
joints_));
561 basetime = pm.
points_.back().time_from_start_;
564 if (name !=
"" || usage !=
"" || description !=
"")
579 void loadParams(
const YAML::Emitter ¶m,
const std::string &name)
582 exec((
"rosparam delete /play_motion/motions/" + name).c_str());
585 std::ofstream ofile(
"/tmp/" + name +
".yaml");
586 ofile << param.c_str();
591 exec((
"rosparam load /tmp/" + name +
".yaml").c_str());
598 return name.substr(0, name.size() - 6);
603 return name +
"_joint";
608 double val = std::numeric_limits<double>::quiet_NaN();
611 val =
static_cast<double>(value);
615 val =
static_cast<int>(value);
630 out.SetFloatPrecision(5);
631 out.SetDoublePrecision(5);
635 out << YAML::BeginMap
637 << YAML::Value << YAML::Flow << m.
joints_ 649 out.SetFloatPrecision(5);
650 out.SetDoublePrecision(5);
653 out << YAML::BeginMap
672 << YAML::Value << m.
name_ 674 << YAML::Value << YAML::Flow << m.
usage_
Motion(const std::string &robot_description, const std::string &robot_description_semantic, const std::vector< std::string > &extra_joints)
static const std::string POINTS_KEY
void addPosition(const std::string &name, double position)
static const std::string TIME_KEY
std::vector< std::string > joints_
void updateKeyFrame(const sensor_msgs::JointStateConstPtr &msg, int frame)
std::string rosifyName(const std::string &name)
bool addGroupToGroup(const std::string &group, const std::string &subgroup)
void copyFrame(int frame, int new_frame_pos=-1)
Emitter & operator<<(YAML::Emitter &out, const pal::PrintMotion &m)
std::vector< KeyFrame > keyframes_
std::vector< std::string > getAvailableJoints()
double toDouble(XmlRpc::XmlRpcValue &value)
std::vector< std::string > getJoints() const
void addJointModel(const std::string &joint_name, const JointModel &joint_model)
std::unordered_map< std::string, std::vector< std::string > > joint_groups_
bool isJointUsed(const std::string &joint_name) const
std::string cleanName(const std::string &name)
static const std::string POSITIONS_KEY
Type const & getType() const
std::vector< JointPosition > joints_
void addJointToGroup(const std::string &group, const std::string &joint)
std::vector< double > positions_
void loadYAML(double downshift) const
const std::string & getParamName() const
double changeJoint(int frame, const std::string &joint_name, double position)
std::unordered_map< std::string, JointModel > joint_models_
void changeTime(int frame, float time_increment)
PrintPoint print(double basetime, double downshift, const std::vector< std::string > &names) const
void loadFrame(int frame) const
std::unordered_map< std::string, bool > extra_joints_
#define ROS_DEBUG_STREAM(args)
void addKeyFrame(const sensor_msgs::JointStateConstPtr &msg, float time_increment=DEFAULT_TIME)
void cleanUnused(const std::map< std::string, bool > &used_joints)
double getJointPosition(const std::string &joint) const
void extendFrames(const sensor_msgs::JointStateConstPtr &msg)
void removeKeyFrame(int frame)
static const float DEFAULT_TIME
std::vector< PrintPoint > points_
#define ROS_INFO_STREAM(args)
void loadParams(const YAML::Emitter ¶m, const std::string &filename)
void setMotionGroups(const std::string &robot_description, const std::string &robot_description_semantic)
#define ROS_ERROR_STREAM(args)
PrintMotion print(double downshift=1.0) const
void setTime(float time_increment)
static const std::string JOINTS_KEY
KeyFrame(float time_increment)
void removeAllKeyFrames()