joint_state_listener.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2008, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 
35 /* Author: Wim Meeussen */
36 
37 #include <ros/ros.h>
38 #include <urdf/model.h>
39 #include <kdl/tree.hpp>
41 
44 
45 using namespace std;
46 using namespace ros;
47 using namespace KDL;
48 using namespace robot_state_publisher;
49 
50 JointStateListener::JointStateListener(const KDL::Tree& tree, const MimicMap& m, const urdf::Model& model)
51  : state_publisher_(tree, model), mimic_(m)
52 {
53  ros::NodeHandle n_tilde("~");
55 
56  // set publish frequency
57  double publish_freq;
58  n_tilde.param("publish_frequency", publish_freq, 50.0);
59  // set whether to use the /tf_static latched static transform broadcaster
60  n_tilde.param("use_tf_static", use_tf_static_, true);
61  // ignore_timestamp_ == true, joins_states messages are accepted, no matter their timestamp
62  n_tilde.param("ignore_timestamp", ignore_timestamp_, false);
63  // get the tf_prefix parameter from the closest namespace
64  std::string tf_prefix_key;
65  n_tilde.searchParam("tf_prefix", tf_prefix_key);
66  n_tilde.param(tf_prefix_key, tf_prefix_, std::string(""));
67  publish_interval_ = ros::Duration(1.0/max(publish_freq, 1.0));
68 
69  // Setting tcpNoNelay tells the subscriber to ask publishers that connect
70  // to set TCP_NODELAY on their side. This prevents some joint_state messages
71  // from being bundled together, increasing the latency of one of the messages.
72  ros::TransportHints transport_hints;
73  transport_hints.tcpNoDelay(true);
74  // subscribe to joint state
75  joint_state_sub_ = n.subscribe("joint_states", 1, &JointStateListener::callbackJointState, this, transport_hints);
76 
77  // trigger to publish fixed joints
78  // if using static transform broadcaster, this will be a oneshot trigger and only run once
80 }
81 
82 
84 {}
85 
86 
88 {
89  (void)e;
91 }
92 
94 {
95  if (state->name.size() != state->position.size()){
96  if (state->position.empty()){
97  const int throttleSeconds = 300;
98  ROS_WARN_THROTTLE(throttleSeconds,
99  "Robot state publisher ignored a JointState message about joint(s) "
100  "\"%s\"(,...) whose position member was empty. This message will "
101  "not reappear for %d seconds.", state->name[0].c_str(),
102  throttleSeconds);
103  } else {
104  ROS_ERROR("Robot state publisher ignored an invalid JointState message");
105  }
106  return;
107  }
108 
109  // check if we moved backwards in time (e.g. when playing a bag file)
110  ros::Time now = ros::Time::now();
111  if (last_callback_time_ > now) {
112  // force re-publish of joint transforms
113  ROS_WARN("Moved backwards in time (probably because ROS clock was reset), re-publishing joint transforms!");
114  last_publish_time_.clear();
115  }
116  ros::Duration warning_threshold(30.0);
117  if ((state->header.stamp + warning_threshold) < now) {
118  ROS_WARN_THROTTLE(10, "Received JointState is %f seconds old.", (now - state->header.stamp).toSec());
119  }
120  last_callback_time_ = now;
121 
122  // determine least recently published joint
123  ros::Time last_published = now;
124  for (unsigned int i=0; i<state->name.size(); i++) {
125  ros::Time t = last_publish_time_[state->name[i]];
126  last_published = (t < last_published) ? t : last_published;
127  }
128  // note: if a joint was seen for the first time,
129  // then last_published is zero.
130 
131  // check if we need to publish
132  if (ignore_timestamp_ || state->header.stamp >= last_published + publish_interval_) {
133  // get joint positions from state message
134  map<string, double> joint_positions;
135  for (unsigned int i=0; i<state->name.size(); i++) {
136  joint_positions.insert(make_pair(state->name[i], state->position[i]));
137  }
138 
139  for (MimicMap::iterator i = mimic_.begin(); i != mimic_.end(); i++) {
140  if(joint_positions.find(i->second->joint_name) != joint_positions.end()) {
141  double pos = joint_positions[i->second->joint_name] * i->second->multiplier + i->second->offset;
142  joint_positions.insert(make_pair(i->first, pos));
143  }
144  }
145 
146  state_publisher_.publishTransforms(joint_positions, state->header.stamp, tf_prefix_);
147 
148  // store publish time in joint map
149  for (unsigned int i = 0; i<state->name.size(); i++) {
150  last_publish_time_[state->name[i]] = state->header.stamp;
151  }
152  }
153 }
154 
155 // ----------------------------------
156 // ----- MAIN -----------------------
157 // ----------------------------------
158 int main(int argc, char** argv)
159 {
160  // Initialize ros
161  ros::init(argc, argv, "robot_state_publisher");
162  NodeHandle node;
163 
165  std::string exe_name = argv[0];
166  std::size_t slash = exe_name.find_last_of("/");
167  if (slash != std::string::npos) {
168  exe_name = exe_name.substr(slash + 1);
169  }
170  if (exe_name == "state_publisher") {
171  ROS_WARN("The 'state_publisher' executable is deprecated. Please use 'robot_state_publisher' instead");
172  }
174 
175  // gets the location of the robot description on the parameter server
176  urdf::Model model;
177  if (!model.initParam("robot_description"))
178  return -1;
179 
180  KDL::Tree tree;
181  if (!kdl_parser::treeFromUrdfModel(model, tree)) {
182  ROS_ERROR("Failed to extract kdl tree from xml robot description");
183  return -1;
184  }
185 
186  MimicMap mimic;
187 
188  for(std::map< std::string, urdf::JointSharedPtr >::iterator i = model.joints_.begin(); i != model.joints_.end(); i++) {
189  if(i->second->mimic) {
190  mimic.insert(make_pair(i->first, i->second->mimic));
191  }
192  }
193 
194  JointStateListener state_publisher(tree, mimic, model);
195  ros::spin();
196 
197  return 0;
198 }
KDL_PARSER_PUBLIC bool treeFromUrdfModel(const urdf::ModelInterface &robot_model, KDL::Tree &tree)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
virtual void publishFixedTransforms(const std::string &tf_prefix, bool use_tf_static=false)
#define ROS_WARN(...)
int main(int argc, char **argv)
virtual void callbackFixedJoint(const ros::TimerEvent &e)
ROSCPP_DECL void spin(Spinner &spinner)
std::map< std::string, ros::Time > last_publish_time_
TransportHints & tcpNoDelay(bool nodelay=true)
virtual void publishTransforms(const std::map< std::string, double > &joint_positions, const ros::Time &time, const std::string &tf_prefix)
#define ROS_WARN_THROTTLE(period,...)
bool searchParam(const std::string &key, std::string &result) const
bool param(const std::string &param_name, T &param_val, const T &default_val) const
robot_state_publisher::RobotStatePublisher state_publisher_
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
URDF_EXPORT bool initParam(const std::string &param)
static Time now()
std::map< std::string, urdf::JointMimicSharedPtr > MimicMap
virtual void callbackJointState(const JointStateConstPtr &state)
double max(double a, double b)
#define ROS_ERROR(...)


robot_state_publisher
Author(s): Ioan Sucan , Jackie Kay , Wim Meeussen
autogenerated on Sun Feb 10 2019 03:51:46