joint_state_controller.cpp
Go to the documentation of this file.
1 // Copyright (C) 2012, hiDOF INC.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name of hiDOF Inc nor the names of its
12 // contributors may be used to endorse or promote products derived from
13 // this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 // POSSIBILITY OF SUCH DAMAGE.
27 
28 /*
29  * Author: Wim Meeussen
30  */
31 
32 #include <algorithm>
33 #include <cstddef>
34 
36 
37 namespace joint_state_controller
38 {
39 
41  ros::NodeHandle& root_nh,
42  ros::NodeHandle& controller_nh)
43  {
44  // get all joint names from the hardware interface
45  const std::vector<std::string>& joint_names = hw->getNames();
46  num_hw_joints_ = joint_names.size();
47  for (unsigned i=0; i<num_hw_joints_; i++)
48  ROS_DEBUG("Got joint %s", joint_names[i].c_str());
49 
50  // get publishing period
51  if (!controller_nh.getParam("publish_rate", publish_rate_)){
52  ROS_ERROR("Parameter 'publish_rate' not set");
53  return false;
54  }
55 
56  // realtime publisher
58 
59  // get joints and allocate message
60  for (unsigned i=0; i<num_hw_joints_; i++){
61  joint_state_.push_back(hw->getHandle(joint_names[i]));
62  realtime_pub_->msg_.name.push_back(joint_names[i]);
63  realtime_pub_->msg_.position.push_back(0.0);
64  realtime_pub_->msg_.velocity.push_back(0.0);
65  realtime_pub_->msg_.effort.push_back(0.0);
66  }
67  addExtraJoints(controller_nh, realtime_pub_->msg_);
68 
69  return true;
70  }
71 
73  {
74  // initialize time
75  last_publish_time_ = time;
76  }
77 
78  void JointStateController::update(const ros::Time& time, const ros::Duration& /*period*/)
79  {
80  // limit rate of publishing
81  if (publish_rate_ > 0.0 && last_publish_time_ + ros::Duration(1.0/publish_rate_) < time){
82 
83  // try to publish
84  if (realtime_pub_->trylock()){
85  // we're actually publishing, so increment time
87 
88  // populate joint state message:
89  // - fill only joints that are present in the JointStateInterface, i.e. indices [0, num_hw_joints_)
90  // - leave unchanged extra joints, which have static values, i.e. indices from num_hw_joints_ onwards
91  realtime_pub_->msg_.header.stamp = time;
92  for (unsigned i=0; i<num_hw_joints_; i++){
93  realtime_pub_->msg_.position[i] = joint_state_[i].getPosition();
94  realtime_pub_->msg_.velocity[i] = joint_state_[i].getVelocity();
95  realtime_pub_->msg_.effort[i] = joint_state_[i].getEffort();
96  }
97  realtime_pub_->unlockAndPublish();
98  }
99  }
100  }
101 
103  {}
104 
105  void JointStateController::addExtraJoints(const ros::NodeHandle& nh, sensor_msgs::JointState& msg)
106  {
107 
108  // Preconditions
109  XmlRpc::XmlRpcValue list;
110  if (!nh.getParam("extra_joints", list))
111  {
112  ROS_DEBUG("No extra joints specification found.");
113  return;
114  }
115 
117  {
118  ROS_ERROR("Extra joints specification is not an array. Ignoring.");
119  return;
120  }
121 
122  for(std::size_t i = 0; i < list.size(); ++i)
123  {
124  if (list[i].getType() != XmlRpc::XmlRpcValue::TypeStruct)
125  {
126  ROS_ERROR_STREAM("Extra joint specification is not a struct, but rather '" << list[i].getType() <<
127  "'. Ignoring.");
128  continue;
129  }
130 
131  if (!list[i].hasMember("name"))
132  {
133  ROS_ERROR_STREAM("Extra joint does not specify name. Ignoring.");
134  continue;
135  }
136 
137  const std::string name = list[i]["name"];
138  if (std::find(msg.name.begin(), msg.name.end(), name) != msg.name.end())
139  {
140  ROS_WARN_STREAM("Joint state interface already contains specified extra joint '" << name << "'.");
141  continue;
142  }
143 
144  const bool has_pos = list[i].hasMember("position");
145  const bool has_vel = list[i].hasMember("velocity");
146  const bool has_eff = list[i].hasMember("effort");
147 
149  if (has_pos && list[i]["position"].getType() != typeDouble)
150  {
151  ROS_ERROR_STREAM("Extra joint '" << name << "' does not specify a valid default position. Ignoring.");
152  continue;
153  }
154  if (has_vel && list[i]["velocity"].getType() != typeDouble)
155  {
156  ROS_ERROR_STREAM("Extra joint '" << name << "' does not specify a valid default velocity. Ignoring.");
157  continue;
158  }
159  if (has_eff && list[i]["effort"].getType() != typeDouble)
160  {
161  ROS_ERROR_STREAM("Extra joint '" << name << "' does not specify a valid default effort. Ignoring.");
162  continue;
163  }
164 
165  // State of extra joint
166  const double pos = has_pos ? static_cast<double>(list[i]["position"]) : 0.0;
167  const double vel = has_vel ? static_cast<double>(list[i]["velocity"]) : 0.0;
168  const double eff = has_eff ? static_cast<double>(list[i]["effort"]) : 0.0;
169 
170  // Add extra joints to message
171  msg.name.push_back(name);
172  msg.position.push_back(pos);
173  msg.velocity.push_back(vel);
174  msg.effort.push_back(eff);
175  }
176  }
177 
178 }
179 
virtual void update(const ros::Time &time, const ros::Duration &)
int size() const
virtual bool init(hardware_interface::JointStateInterface *hw, ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
Type const & getType() const
virtual void starting(const ros::Time &time)
unsigned int num_hw_joints_
Number of joints present in the JointStateInterface, excluding extra joints.
#define ROS_WARN_STREAM(args)
void addExtraJoints(const ros::NodeHandle &nh, sensor_msgs::JointState &msg)
JointStateHandle getHandle(const std::string &name)
bool hasMember(const std::string &name) const
bool getParam(const std::string &key, std::string &s) const
boost::shared_ptr< realtime_tools::RealtimePublisher< sensor_msgs::JointState > > realtime_pub_
std::vector< std::string > getNames() const
#define ROS_ERROR_STREAM(args)
std::vector< hardware_interface::JointStateHandle > joint_state_
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
#define ROS_ERROR(...)
#define ROS_DEBUG(...)
Controller that publishes the state of all joints in a robot.


joint_state_controller
Author(s): Wim Meeussen
autogenerated on Thu Apr 11 2019 03:08:35