jog_joint_node.cpp
Go to the documentation of this file.
2 
3 namespace jog_joint {
4 
6 {
7  ros::NodeHandle gnh;
8 
9  // Get controller information from move_group/controller_list
10  if (!gnh.hasParam("move_group/controller_list"))
11  {
12  ROS_ERROR_STREAM("move_group/controller_list is not specified.");
13  return -1;
14  }
15  XmlRpc::XmlRpcValue controller_list;
16  gnh.getParam("move_group/controller_list", controller_list);
17  for (int i = 0; i < controller_list.size(); i++)
18  {
19  if (!controller_list[i].hasMember("name"))
20  {
21  ROS_ERROR("name must be specifed for each controller.");
22  return -1;
23  }
24  if (!controller_list[i].hasMember("joints"))
25  {
26  ROS_ERROR("joints must be specifed for each controller.");
27  return -1;
28  }
29  try
30  {
31  // get name member
32  std::string name = std::string(controller_list[i]["name"]);
33  // get action_ns member if exists
34  std::string action_ns = std::string("");
35  if (controller_list[i].hasMember("action_ns"))
36  {
37  action_ns = std::string(controller_list[i]["action_ns"]);
38  }
39  // get joints member
40  if (controller_list[i]["joints"].getType() != XmlRpc::XmlRpcValue::TypeArray)
41  {
42  ROS_ERROR_STREAM("joints for controller " << name << " is not specified as an array");
43  return -1;
44  }
45  auto joints = controller_list[i]["joints"];
46  // Get type member
47  std::string type = std::string("FollowJointTrajectory");
48  if (!controller_list[i].hasMember("type"))
49  {
50  ROS_WARN_STREAM("type is not specifed for controller " << name << ", using default FollowJointTrajectory");
51  }
52  type = std::string(controller_list[i]["type"]);
53  if (type != "FollowJointTrajectory")
54  {
55  ROS_ERROR_STREAM("controller type " << type << " is not supported");
56  return -1;
57  }
58  // Create controller map
59  cinfo_map_[name].action_ns = action_ns;
60  cinfo_map_[name].joints.resize(joints.size());
61  for (int j = 0; j < cinfo_map_[name].joints.size(); ++j)
62  {
63  cinfo_map_[name].joints[j] = std::string(joints[j]);
64  }
65  }
66  catch (...)
67  {
68  ROS_ERROR_STREAM("Caught unknown exception while parsing controller information");
69  return -1;
70  }
71  }
72  return 0;
73 }
74 
76 {
77  ros::NodeHandle gnh, pnh("~");
78 
79  pnh.param<double>("time_from_start", time_from_start_, 0.2);
80  pnh.param<bool>("use_action", use_action_, false);
81  pnh.param<bool>("intermittent", intermittent_, false);
82 
83  if (not use_action_ && intermittent_)
84  {
85  ROS_WARN("'intermittent' param should be true with 'use_action'. Assuming to use action'");
86  use_action_ = true;
87  }
88  if (get_controller_list() < 0)
89  {
90  ROS_ERROR("get_controller_list faild. Aborted.");
91  ros::shutdown();
92  return;
93  }
94  ROS_INFO_STREAM("controller_list:");
95  for (auto it=cinfo_map_.begin(); it!=cinfo_map_.end(); it++)
96  {
97  auto cinfo = it->second;
98  ROS_INFO_STREAM("- " << it->first);
99  for (int i=0; i<cinfo.joints.size(); i++)
100  {
101  ROS_INFO_STREAM(" - " << cinfo.joints[i]);
102  }
103  }
104 
105  // Create subscribers
106  joint_state_sub_ = gnh.subscribe("joint_states", 20, &JogJointNode::joint_state_cb, this);
107  jog_joint_sub_ = gnh.subscribe("jog_joint", 20, &JogJointNode::jog_joint_cb, this);
108 
109  // Reference joint_state publisher
110  joint_state_pub_ = pnh.advertise<sensor_msgs::JointState>("reference_joint_states", 10);
111 
112  if (use_action_)
113  {
114  // Create action client for each controller
115  for (auto it=cinfo_map_.begin(); it!=cinfo_map_.end(); it++)
116  {
117  auto controller_name = it->first;
118  auto controller_info = it->second;
119  auto action_name = controller_name + "/" + controller_info.action_ns;
120 
121  traj_clients_[controller_name] = new TrajClient(action_name, true);
122  }
123  for (auto it=cinfo_map_.begin(); it!=cinfo_map_.end(); it++)
124  {
125  auto controller_name = it->first;
126  auto controller_info = it->second;
127  auto action_name = controller_name + "/" + controller_info.action_ns;
128 
129  for(;;)
130  {
131  if (traj_clients_[controller_name]->waitForServer(ros::Duration(1)))
132  {
133  ROS_INFO_STREAM(action_name << " is ready.");
134  break;
135  }
136  ROS_WARN_STREAM("Waiting for " << action_name << "server...");
137  }
138  }
139  }
140  else
141  {
142  // Create publisher for each controller
143  for (auto it=cinfo_map_.begin(); it!=cinfo_map_.end(); it++)
144  {
145  auto controller_name = it->first;
146  traj_pubs_[controller_name] = gnh.advertise<trajectory_msgs::JointTrajectory>(controller_name + "/command", 1);
147  }
148  }
149 }
150 
155 void JogJointNode::jog_joint_cb(jog_msgs::JogJointConstPtr msg)
156 {
157  // Validate the message
158  if (msg->joint_names.size() != msg->deltas.size())
159  {
160  ROS_ERROR("Size mismatch of joint_names and deltas");
161  return;
162  }
163  // In intermittent mode, confirm to all of the action is completed
164  if (intermittent_)
165  {
166  for (auto it=cinfo_map_.begin(); it!=cinfo_map_.end(); it++)
167  {
168  auto controller_name = it->first;
169  actionlib::SimpleClientGoalState state = traj_clients_[controller_name]->getState();
171  {
172  return;
173  }
174  }
175  }
176 
177  // Update only if the stamp is older than last_stamp_ + time_from_start
178  if (msg->header.stamp > last_stamp_ + ros::Duration(time_from_start_))
179  {
180  ROS_INFO("start joint state updated");
181  // Update reference joint_state
182  joint_state_.name.clear();
183  joint_state_.position.clear();
184  joint_state_.velocity.clear();
185  joint_state_.effort.clear();
186  for (auto it=joint_map_.begin(); it!=joint_map_.end(); it++)
187  {
188  joint_state_.name.push_back(it->first);
189  joint_state_.position.push_back(it->second);
190  joint_state_.velocity.push_back(0.0);
191  joint_state_.effort.push_back(0.0);
192  }
193  // Publish reference joint state for debug
195  }
196  // Update timestamp of the last jog command
197  last_stamp_ = msg->header.stamp;
198 
199  // Publish trajectory message for each controller
200  for (auto it=cinfo_map_.begin(); it!=cinfo_map_.end(); it++)
201  {
202  auto controller_name = it->first;
203  auto joint_names = it->second.joints;
204 
205  trajectory_msgs::JointTrajectory traj;
206  trajectory_msgs::JointTrajectoryPoint point;
207  point.time_from_start = ros::Duration(time_from_start_);
208 
209  for (int i=0; i<joint_names.size(); i++)
210  {
211  size_t jog_index = std::distance(msg->joint_names.begin(),
212  std::find(msg->joint_names.begin(),
213  msg->joint_names.end(), joint_names[i]));
214  if (jog_index == msg->joint_names.size())
215  {
216  ROS_INFO_STREAM("Cannot find joint in jog_joint: " << joint_names[i]);
217  continue;
218  }
219  size_t state_index = std::distance(joint_state_.name.begin(),
220  std::find(joint_state_.name.begin(),
221  joint_state_.name.end(), joint_names[i]));
222  if (state_index == joint_state_.name.size())
223  {
224  ROS_ERROR_STREAM("Cannot find joint " << joint_names[i] << " in joint_states_");
225  continue;
226  }
227  // Update start joint position
228  joint_state_.position[state_index] += msg->deltas[jog_index];
229  // Fill joint trajectory joint_names and positions
230  traj.joint_names.push_back(joint_names[i]);
231  point.positions.push_back(joint_state_.position[state_index]);
232  point.velocities.push_back(0.0);
233  point.accelerations.push_back(0.0);
234  }
235  // Fill joint trajectory members
236  traj.header.stamp = ros::Time::now();
237  traj.header.frame_id = "base_link";
238  traj.points.push_back(point);
239  if (use_action_)
240  {
241  control_msgs::FollowJointTrajectoryGoal goal;
242  goal.trajectory = traj;
243  traj_clients_[controller_name]->sendGoal(goal);
244  }
245  else
246  {
247  traj_pubs_[controller_name].publish(traj);
248  }
249  }
250  // Publish start joint state for debug
252 }
253 
258 void JogJointNode::joint_state_cb(sensor_msgs::JointStateConstPtr msg)
259 {
260  // Check that the msg contains joints
261  if (msg->name.empty() || msg->name.size() != msg->position.size())
262  {
263  ROS_WARN("Invalid JointState message");
264  return;
265  }
266  for (int i=0; i<msg->name.size(); i++)
267  {
268  joint_map_[msg->name[i]] = msg->position[i];
269  }
270 }
271 
272 } // namespace jog_arm
273 
277 int main(int argc, char **argv)
278 {
279  ros::init(argc, argv, "jog_joint_node");
281 
282  ros::Rate loop_rate(100);
283  while ( ros::ok() )
284  {
285  ros::spinOnce();
286  loop_rate.sleep();
287  }
288  return 0;
289 }
290 
actionlib::SimpleActionClient< control_msgs::FollowJointTrajectoryAction > TrajClient
void publish(const boost::shared_ptr< M > &message) const
ros::Subscriber jog_joint_sub_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
int size() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
#define ROS_WARN(...)
std::map< std::string, ros::Publisher > traj_pubs_
void jog_joint_cb(jog_msgs::JogJointConstPtr msg)
Callback function for the topic jog_joint.
ros::Publisher joint_state_pub_
int main(int argc, char **argv)
Main function of the node.
std::map< std::string, TrajClient * > traj_clients_
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ROSCPP_DECL bool ok()
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
std::map< std::string, double > joint_map_
#define ROS_WARN_STREAM(args)
bool sleep()
void joint_state_cb(sensor_msgs::JointStateConstPtr msg)
Callback function for the topic joint_state.
#define ROS_INFO_STREAM(args)
bool getParam(const std::string &key, std::string &s) const
static Time now()
std::map< std::string, Controller > cinfo_map_
ROSCPP_DECL void shutdown()
bool hasParam(const std::string &key) const
ros::Subscriber joint_state_sub_
#define ROS_ERROR_STREAM(args)
ROSCPP_DECL void spinOnce()
sensor_msgs::JointState joint_state_
#define ROS_ERROR(...)


jog_controller
Author(s): Ryosuke Tajima
autogenerated on Sun May 17 2020 03:25:01