converters/joint_state.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2015 Aldebaran
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
18 /*
19 * LOCAL includes
20 */
21 #include "joint_state.hpp"
22 #include "nao_footprint.hpp"
23 
24 /*
25 * BOOST includes
26 */
27 #include <boost/foreach.hpp>
28 #define for_each BOOST_FOREACH
29 
30 /*
31 * ROS includes
32 */
33 #include <urdf/model.h>
36 
37 namespace naoqi
38 {
39 
40 namespace converter
41 {
42 
43 JointStateConverter::JointStateConverter( const std::string& name, const float& frequency, const BufferPtr& tf2_buffer, const qi::SessionPtr& session ):
44  BaseConverter( name, frequency, session ),
45  p_motion_( session->service("ALMotion") ),
46  p_memory_( session->service("ALMemory") ),
47  tf2_buffer_(tf2_buffer)
48 {
50 }
51 
53 {
54  // clear all sessions
55 }
56 
58 {
59  if ( robot_desc_.empty() )
60  {
61  std::cout << "error in loading robot description" << std::endl;
62  return;
63  }
64  urdf::Model model;
65  model.initString( robot_desc_ );
66  KDL::Tree tree;
67  kdl_parser::treeFromUrdfModel( model, tree );
68 
69  addChildren( tree.getRootSegment() );
70 
71  // set mimic joint list
72  mimic_.clear();
73  for(std::map< std::string, urdf::JointSharedPtr >::iterator i = model.joints_.begin(); i != model.joints_.end(); i++){
74  if(i->second->mimic){
75  mimic_.insert(make_pair(i->first, i->second->mimic));
76  }
77  }
78  // pre-fill joint states message
79  msg_joint_states_.name = p_motion_.call<std::vector<std::string> >("getBodyNames", "Body" );
80 }
81 
83 {
84  callbacks_[action] = cb;
85 }
86 
87 void JointStateConverter::callAll( const std::vector<message_actions::MessageAction>& actions )
88 {
89  // get joint state values
90  std::vector<double> al_joint_angles = p_motion_.call<std::vector<double> >("getAngles", "Body", true );
91  std::vector<double> al_joint_velocities;
92  std::vector<double> al_joint_torques;
93 
94  const ros::Time& stamp = ros::Time::now();
95 
99  msg_joint_states_.header.stamp = stamp;
100 
101  // STUPID CONVERTION FROM FLOAT TO DOUBLE ARRAY --> OPTIMIZE THAT!
102  msg_joint_states_.position = std::vector<double>( al_joint_angles.begin(), al_joint_angles.end() );
103 
107  // put joint states in tf broadcaster
108  std::map< std::string, double > joint_state_map;
109  // stupid version --> change this with std::transform c++11 ??!
110 // std::transform( msg_joint_states_.name.begin(), msg_joint_states_.name.end(), msg_joint_states_.position.begin(),
111 // std::inserter( joint_state_map, joint_state_map.end() ),
112 // std::make_pair);
113  std::vector<double>::const_iterator itPos = msg_joint_states_.position.begin();
114  for(std::vector<std::string>::const_iterator itName = msg_joint_states_.name.begin();
115  itName != msg_joint_states_.name.end();
116  ++itName, ++itPos)
117  {
118  joint_state_map[*itName] = *itPos;
119 
120  try {
121  al_joint_velocities.push_back(p_memory_.call<double>(
122  "getData",
123  "Motion/Velocity/Sensor/" + (*itName)));
124 
125  al_joint_torques.push_back(p_memory_.call<double>(
126  "getData",
127  "Motion/Torque/Sensor/" + (*itName)));
128 
129  } catch (qi::FutureUserException e) {
130  // Sets the velocity and torques field to nan if no info is provided
131  al_joint_velocities.push_back(std::numeric_limits<double>::quiet_NaN());
132  al_joint_torques.push_back(std::numeric_limits<double>::quiet_NaN());
133  }
134  }
135 
136  msg_joint_states_.velocity = al_joint_velocities;
137  msg_joint_states_.effort = al_joint_torques;
138 
139  // for mimic map
140  for(MimicMap::iterator i = mimic_.begin(); i != mimic_.end(); i++){
141  if(joint_state_map.find(i->second->joint_name) != joint_state_map.end()){
142  double pos = joint_state_map[i->second->joint_name] * i->second->multiplier + i->second->offset;
143  joint_state_map[i->first] = pos;
144  }
145  }
146 
147  // reset the transforms we want to use at this time
148  tf_transforms_.clear();
149  static const std::string& jt_tf_prefix = "";
150  setTransforms(joint_state_map, stamp, jt_tf_prefix);
151  setFixedTransforms(jt_tf_prefix, stamp);
152 
157  /*
158  * can be called via getRobotPosture
159  * but this would require a proper URDF
160  * with a base_link and base_footprint in the base
161  */
162  std::vector<float> al_odometry_data = p_motion_.call<std::vector<float> >( "getPosition", "Torso", 1, true );
163  const ros::Time& odom_stamp = ros::Time::now();
164  const float& odomX = al_odometry_data[0];
165  const float& odomY = al_odometry_data[1];
166  const float& odomZ = al_odometry_data[2];
167  const float& odomWX = al_odometry_data[3];
168  const float& odomWY = al_odometry_data[4];
169  const float& odomWZ = al_odometry_data[5];
170  //since all odometry is 6DOF we'll need a quaternion created from yaw
171  tf2::Quaternion tf_quat;
172  tf_quat.setRPY( odomWX, odomWY, odomWZ );
173  geometry_msgs::Quaternion odom_quat = tf2::toMsg( tf_quat );
174 
175  static geometry_msgs::TransformStamped msg_tf_odom;
176  msg_tf_odom.header.frame_id = "odom";
177  msg_tf_odom.child_frame_id = "base_link";
178  msg_tf_odom.header.stamp = odom_stamp;
179 
180  msg_tf_odom.transform.translation.x = odomX;
181  msg_tf_odom.transform.translation.y = odomY;
182  msg_tf_odom.transform.translation.z = odomZ;
183  msg_tf_odom.transform.rotation = odom_quat;
184 
185  tf_transforms_.push_back( msg_tf_odom );
186  tf2_buffer_->setTransform( msg_tf_odom, "naoqiconverter", false);
187 
188  if (robot_ == robot::NAO )
189  {
191  }
192 
193  // If nobody uses that buffer, do not fill it next time
194  if (( tf2_buffer_ ) && ( tf2_buffer_.use_count() == 1 ))
195  {
196  tf2_buffer_.reset();
197  }
198 
200  {
202  }
203 }
204 
205 
206 // Copied from robot state publisher
207 void JointStateConverter::setTransforms(const std::map<std::string, double>& joint_positions, const ros::Time& time, const std::string& tf_prefix)
208 {
209  geometry_msgs::TransformStamped tf_transform;
210  tf_transform.header.stamp = time;
211 
212  // loop over all joints
213  for (std::map<std::string, double>::const_iterator jnt=joint_positions.begin(); jnt != joint_positions.end(); jnt++){
214  std::map<std::string, robot_state_publisher::SegmentPair>::const_iterator seg = segments_.find(jnt->first);
215  if (seg != segments_.end()){
216  seg->second.segment.pose(jnt->second).M.GetQuaternion(tf_transform.transform.rotation.x,
217  tf_transform.transform.rotation.y,
218  tf_transform.transform.rotation.z,
219  tf_transform.transform.rotation.w);
220  tf_transform.transform.translation.x = seg->second.segment.pose(jnt->second).p.x();
221  tf_transform.transform.translation.y = seg->second.segment.pose(jnt->second).p.y();
222  tf_transform.transform.translation.z = seg->second.segment.pose(jnt->second).p.z();
223 
224  //tf_transform.header.frame_id = tf::resolve(tf_prefix, seg->second.root);
225  //tf_transform.child_frame_id = tf::resolve(tf_prefix, seg->second.tip);
226  tf_transform.header.frame_id = seg->second.root; // tf2 does not suppport tf_prefixing
227  tf_transform.child_frame_id = seg->second.tip;
228 
229  tf_transforms_.push_back(tf_transform);
230 
231  if (tf2_buffer_)
232  tf2_buffer_->setTransform(tf_transform, "naoqiconverter", false);
233  }
234  }
235  //tf_broadcaster_.sendTransform(tf_transforms);
236 }
237 
238 // Copied from robot state publisher
239 void JointStateConverter::setFixedTransforms(const std::string& tf_prefix, const ros::Time& time)
240 {
241  geometry_msgs::TransformStamped tf_transform;
242  tf_transform.header.stamp = time/*+ros::Duration(0.5)*/; // future publish by 0.5 seconds
243 
244  // loop over all fixed segments
245  for (std::map<std::string, robot_state_publisher::SegmentPair>::const_iterator seg=segments_fixed_.begin(); seg != segments_fixed_.end(); seg++){
246  seg->second.segment.pose(0).M.GetQuaternion(tf_transform.transform.rotation.x,
247  tf_transform.transform.rotation.y,
248  tf_transform.transform.rotation.z,
249  tf_transform.transform.rotation.w);
250  tf_transform.transform.translation.x = seg->second.segment.pose(0).p.x();
251  tf_transform.transform.translation.y = seg->second.segment.pose(0).p.y();
252  tf_transform.transform.translation.z = seg->second.segment.pose(0).p.z();
253 
254  //tf_transform.header.frame_id = tf::resolve(tf_prefix, seg->second.root);
255  //tf_transform.child_frame_id = tf::resolve(tf_prefix, seg->second.tip);
256  tf_transform.header.frame_id = seg->second.root;
257  tf_transform.child_frame_id = seg->second.tip;
258 
259  tf_transforms_.push_back(tf_transform);
260 
261  if (tf2_buffer_)
262  tf2_buffer_->setTransform(tf_transform, "naoqiconverter", true);
263  }
264  //tf_broadcaster_.sendTransform(tf_transforms);
265 }
266 
267 void JointStateConverter::addChildren(const KDL::SegmentMap::const_iterator segment)
268 {
269  const std::string& root = GetTreeElementSegment(segment->second).getName();
270 
271  const std::vector<KDL::SegmentMap::const_iterator>& children = GetTreeElementChildren(segment->second);
272  for (unsigned int i=0; i<children.size(); i++){
273  const KDL::Segment& child = GetTreeElementSegment(children[i]->second);
274  robot_state_publisher::SegmentPair s(GetTreeElementSegment(children[i]->second), root, child.getName());
275  if (child.getJoint().getType() == KDL::Joint::None){
276  segments_fixed_.insert(std::make_pair(child.getJoint().getName(), s));
277  ROS_DEBUG("Adding fixed segment from %s to %s", root.c_str(), child.getName().c_str());
278  }
279  else{
280  segments_.insert(std::make_pair(child.getJoint().getName(), s));
281  ROS_DEBUG("Adding moving segment from %s to %s", root.c_str(), child.getName().c_str());
282  }
283  addChildren(children[i]);
284  }
285 }
286 
287 } //publisher
288 } // naoqi
#define GetTreeElementSegment(tree_element)
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
void registerCallback(const message_actions::MessageAction action, Callback_t cb)
URDF_EXPORT bool initString(const std::string &xmlstring)
KDL_PARSER_PUBLIC bool treeFromUrdfModel(const urdf::ModelInterface &robot_model, KDL::Tree &tree)
XmlRpcServer s
void addBaseFootprint(boost::shared_ptr< tf2_ros::Buffer > tf2_buffer, std::vector< geometry_msgs::TransformStamped > &tf_transforms, const ros::Time &time)
boost::function< void(sensor_msgs::JointState &, std::vector< geometry_msgs::TransformStamped > &) > Callback_t
#define for_each
#define GetTreeElementChildren(tree_element)
const std::string & getName() const
const std::string & getName() const
std::map< message_actions::MessageAction, Callback_t > callbacks_
const Joint & getJoint() const
void setFixedTransforms(const std::string &tf_prefix, const ros::Time &time)
std::map< std::string, robot_state_publisher::SegmentPair > segments_
action
void addChildren(const KDL::SegmentMap::const_iterator segment)
B toMsg(const A &a)
SegmentMap::const_iterator getRootSegment() const
void callAll(const std::vector< message_actions::MessageAction > &actions)
static Time now()
std::map< std::string, robot_state_publisher::SegmentPair > segments_fixed_
void setTransforms(const std::map< std::string, double > &joint_positions, const ros::Time &time, const std::string &tf_prefix)
std::vector< geometry_msgs::TransformStamped > tf_transforms_
std::string getRobotDescription(const robot::Robot &robot)
const JointType & getType() const
JointStateConverter(const std::string &name, const float &frequency, const BufferPtr &tf2_buffer, const qi::SessionPtr &session)
#define ROS_DEBUG(...)


naoqi_driver
Author(s): Karsten Knese
autogenerated on Sat Feb 15 2020 03:24:26