rbcar_robot_control.cpp
Go to the documentation of this file.
1 /*
2  * rbcar_robot_control
3  * Copyright (c) 2015, Robotnik Automation, SLL
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * * Neither the name of the Robotnik Automation, SLL. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * \author Robotnik
31  * \brief Controller for the RBCAR robot in ackermann-steering (single)
32  Control steering (2 direction axes) and traction axes (4W) of the RBCAR single Ackerman drive kinematics
33  transforms the commands received from the joystick (or other high level controller) in motor position / velocity commands
34  */
35 
36 #include <ros/ros.h>
37 #include <sensor_msgs/JointState.h>
38 #include <sensor_msgs/Imu.h>
39 #include <std_msgs/Float64.h>
41 #include <nav_msgs/Odometry.h>
42 #include <robotnik_msgs/set_mode.h>
43 #include <robotnik_msgs/get_mode.h>
44 #include <robotnik_msgs/set_odometry.h>
45 #include <robotnik_msgs/ptz.h>
46 
47 #include "ackermann_msgs/AckermannDriveStamped.h"
48 
49 //#include "self_test/self_test.h"
50 #include "diagnostic_msgs/DiagnosticStatus.h"
55 
56 
57 #define PI 3.1415926535
58 #define RBCAR_MIN_COMMAND_REC_FREQ 5.0
59 #define RBCAR_MAX_COMMAND_REC_FREQ 150.0
60 
61 #define RBCAR_D_WHEELS_M 2.5 // distance from front to back axis, car-like kinematics
62 #define RBCAR_WHEEL_DIAMETER 0.470 // wheel avg diameter - may need calibration according to tyre pressure
63 #define RBCAR_JOINT_STATES_TIME_WINDOW 1.0 // accepted time deviation to process joint_sttate
64 
65 using namespace std;
66 
68 
69 public:
70 
73  double desired_freq_;
74 
75  // Diagnostics
76  diagnostic_updater::Updater diagnostic_; // General status diagnostic updater
77  diagnostic_updater::FrequencyStatus freq_diag_; // Component frequency diagnostics
78  diagnostic_updater::HeaderlessTopicDiagnostic *subs_command_freq; // Topic reception frequency diagnostics
79  ros::Time last_command_time_; // Last moment when the component received a command
81 
82  // Robot model
83  std::string robot_model_;
84 
85  // Velocity and position references to low level controllers
92 
93  // Joint states published by the joint_state_controller of the Controller Manager
95 
96  // High level robot command
98 
99  //ros::Subscriber gyro_sub_;
100 
101  // Services
103 
104  // Ackermann Topics - control action - traction - velocity
105  std::string frw_vel_topic_;
106  std::string flw_vel_topic_;
107  std::string brw_vel_topic_;
108  std::string blw_vel_topic_;
109 
110  // Ackerman Topics - control action - steering - position
111  std::string frw_pos_topic_;
112  std::string flw_pos_topic_;
113 
114  // Joint names - traction - velocity
119 
120  // Joint names - steering - position
123 
124  // Indexes to joint_states
125  int frw_vel_, flw_vel_, blw_vel_, brw_vel_;
126  int frw_pos_, flw_pos_;
127 
128  // Robot Speeds
132 
133  // Robot Positions
139 
140  // Robot Joint States
141  sensor_msgs::JointState joint_state_;
142 
143  // Command reference
144  ackermann_msgs::AckermannDriveStamped base_vel_msg_;
145 
146  // External speed references
147  double v_ref_;
148  double alfa_ref_;
149  double pos_ref_pan_;
151 
152  // Flag to indicate if joint_state has been read
153  bool read_state_;
154 
155  // Robot configuration parameters
158 
159  // IMU values
160  double ang_vel_x_;
161  double ang_vel_y_;
162  double ang_vel_z_;
163 
164  double lin_acc_x_;
165  double lin_acc_y_;
166  double lin_acc_z_;
167 
172 
173  // Parameter that defines if odom tf is published or not
175 
177 
178  // Publisher for odom topic
180 
181  // Broadcaster for odom tf
183 
184 
189  node_handle_(h), private_node_handle_("~"),
190  desired_freq_(100),
191  freq_diag_(diagnostic_updater::FrequencyStatusParam(&desired_freq_, &desired_freq_, 0.05) ),
192  command_freq_("Command frequency check", boost::bind(&RbcarControllerClass::check_command_subscriber, this, _1))
193  {
194 
195  ROS_INFO("rbcar_robot_control_node - Init ");
196 
197  ros::NodeHandle rbcar_robot_control_node_handle(node_handle_, "rbcar_robot_control");
198 
199  // Get robot model from the parameters
200  if (!private_node_handle_.getParam("model", robot_model_)) {
201  ROS_ERROR("Robot model not defined.");
202  exit(-1);
203  }
204  else ROS_INFO("Robot Model : %s", robot_model_.c_str());
205 
206  // Ackermann configuration - traction - topics
207 
208 
209  private_node_handle_.param<std::string>("frw_vel_topic", frw_vel_topic_, "rbcar/right_front_axle_controller/command");
210  private_node_handle_.param<std::string>("flw_vel_topic", flw_vel_topic_, "rbcar/left_front_axle_controller/command");
211  private_node_handle_.param<std::string>("blw_vel_topic", blw_vel_topic_, "rbcar/left_rear_axle_controller/command");
212  private_node_handle_.param<std::string>("brw_vel_topic", brw_vel_topic_, "rbcar/right_rear_axle_controller/command");
213 
214  // Ackermann configuration - traction - joint names
215  private_node_handle_.param<std::string>("joint_front_right_wheel", joint_front_right_wheel, "right_front_axle");
216  private_node_handle_.param<std::string>("joint_front_left_wheel", joint_front_left_wheel, "left_front_axle");
217  private_node_handle_.param<std::string>("joint_back_left_wheel", joint_back_left_wheel, "left_rear_axle");
218  private_node_handle_.param<std::string>("joint_back_right_wheel", joint_back_right_wheel, "right_rear_axle");
219 
220  // Ackermann configuration - direction - topics
221  private_node_handle_.param<std::string>("frw_pos_topic", frw_pos_topic_, "rbcar/right_steering_joint_controller/command");
222  private_node_handle_.param<std::string>("flw_pos_topic", flw_pos_topic_, "rbcar/left_steering_joint_controller/command");
223 
224  private_node_handle_.param<std::string>("joint_front_right_steer", joint_front_right_steer, "right_steering_joint");
225  private_node_handle_.param<std::string>("joint_front_left_steer", joint_front_left_steer, "left_steering_joint");
226 
227  // Robot parameters
228  if (!private_node_handle_.getParam("rbcar_d_wheels", rbcar_d_wheels_))
229  rbcar_d_wheels_ = RBCAR_D_WHEELS_M;
230  if (!private_node_handle_.getParam("rbcar_wheel_diameter", rbcar_wheel_diameter_))
231  rbcar_wheel_diameter_ = RBCAR_WHEEL_DIAMETER;
232  ROS_INFO("rbcar_d_wheels_ = %5.2f", rbcar_d_wheels_);
233  ROS_INFO("rbcar_wheel_diameter_ = %5.2f", rbcar_wheel_diameter_);
234 
235  private_node_handle_.param("publish_odom_tf", publish_odom_tf_, true);
236  if (publish_odom_tf_) ROS_INFO("PUBLISHING odom->base_footprint tf");
237  else ROS_INFO("NOT PUBLISHING odom->base_footprint tf");
238 
239  // Robot Speeds
240  linearSpeedXMps_ = 0.0;
241  linearSpeedYMps_ = 0.0;
242  angularSpeedRads_ = 0.0;
243 
244  // Robot Positions
245  robot_pose_px_ = 0.0;
246  robot_pose_py_ = 0.0;
247  robot_pose_pa_ = 0.0;
248  robot_pose_vx_ = 0.0;
249  robot_pose_vy_ = 0.0;
250 
251  // Robot state space control references
252  v_ref_ = 0.0;
253  alfa_ref_ = 0.0;
254  pos_ref_pan_ = 0.0;
255 
256  // Imu variables
257  ang_vel_x_ = 0.0; ang_vel_y_ = 0.0; ang_vel_z_ = 0.0;
258  lin_acc_x_ = 0.0; lin_acc_y_ = 0.0; lin_acc_z_ = 0.0;
259  orientation_x_ = 0.0; orientation_y_ = 0.0; orientation_z_ = 0.0; orientation_w_ = 1.0;
260 
261  // Advertise controller services
262  srv_SetOdometry_ = rbcar_robot_control_node_handle.advertiseService("set_odometry", &RbcarControllerClass::srvCallback_SetOdometry, this);
263 
264  // Subscribe to joint states topic
265  joint_state_sub_ = node_handle_.subscribe<sensor_msgs::JointState>("joint_states", 1, &RbcarControllerClass::jointStateCallback, this);
266 
267  // Subscribe to imu data
268  imu_sub_ = node_handle_.subscribe("imu/data", 1, &RbcarControllerClass::imuCallback, this);
269 
270  // Adevertise reference topics for the controllers
271  ref_vel_frw_ = node_handle_.advertise<std_msgs::Float64>( frw_vel_topic_, 50);
272  ref_vel_flw_ = node_handle_.advertise<std_msgs::Float64>( flw_vel_topic_, 50);
273  ref_vel_blw_ = node_handle_.advertise<std_msgs::Float64>( blw_vel_topic_, 50);
274  ref_vel_brw_ = node_handle_.advertise<std_msgs::Float64>( brw_vel_topic_, 50);
275  ref_pos_frw_ = node_handle_.advertise<std_msgs::Float64>( frw_pos_topic_, 50);
276  ref_pos_flw_ = node_handle_.advertise<std_msgs::Float64>( flw_pos_topic_, 50);
277 
278  // Subscribe to command topic
279  cmd_sub_ = rbcar_robot_control_node_handle.subscribe<ackermann_msgs::AckermannDriveStamped>("command", 1, &RbcarControllerClass::commandCallback, this);
280 
281  // Publish odometry
282  odom_pub_ = private_node_handle_.advertise<nav_msgs::Odometry>("odom", 1000);
283 
284  // Component frequency diagnostics
285  diagnostic_.setHardwareID("rbcar_robot_control - simulation");
286  diagnostic_.add( freq_diag_ );
287  diagnostic_.add( command_freq_ );
288 
289  // Topics freq control
290  // For /rbcar_robot_control/command
291  double min_freq = RBCAR_MIN_COMMAND_REC_FREQ; // If you update these values, the
292  double max_freq = RBCAR_MAX_COMMAND_REC_FREQ; // HeaderlessTopicDiagnostic will use the new values.
293 
294  subs_command_freq = new diagnostic_updater::HeaderlessTopicDiagnostic("~command", diagnostic_,
295  diagnostic_updater::FrequencyStatusParam(&min_freq, &max_freq, 0.1, 10));
296  subs_command_freq->addTask(&command_freq_); // Adding an additional task to the control
297 
298  // Flag to indicate joint_state has been read
299  read_state_ = false;
300 }
301 
303 int starting()
304 {
305  // Initialize joint indexes according to joint names
306  if (read_state_) {
307  vector<string> joint_names = joint_state_.name;
308  frw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_front_right_wheel)) - joint_names.begin();
309  flw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_front_left_wheel)) - joint_names.begin();
310  blw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_back_left_wheel)) - joint_names.begin();
311  brw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_back_right_wheel)) - joint_names.begin();
312  frw_pos_ = find (joint_names.begin(),joint_names.end(), string(joint_front_right_steer)) - joint_names.begin();
313  flw_pos_ = find (joint_names.begin(),joint_names.end(), string(joint_front_left_steer)) - joint_names.begin();
314  return 0;
315  }else{
316  ROS_WARN("RbcarControllerClass::starting: joint_states are not being received");
317  return -1;
318  }
319 }
320 
323 {
324  // Compute state control actions
325  // State feedback error 4 position loops / 4 velocity loops
326  // Single steering
327  double d1 =0.0;
328  double d = RBCAR_D_WHEELS_M; // divide by 2 for dual Ackermann steering
329  double alfa_ref_left = 0.0;
330  double alfa_ref_right = 0.0;
331  if (alfa_ref_!=0.0) { // div/0
332  d1 = d / tan (alfa_ref_);
333  alfa_ref_left = atan2( d, d1 - 0.105);
334  alfa_ref_right = atan2( d, d1 + 0.105);
335  if (alfa_ref_<0.0) {
336  alfa_ref_left = alfa_ref_left - PI;
337  alfa_ref_right = alfa_ref_right - PI;
338  }
339  }
340  else {
341  alfa_ref_left = 0.0;
342  alfa_ref_right = 0.0;
343  }
344 
345  // Angular position ref publish
346  std_msgs::Float64 frw_ref_pos_msg;
347  std_msgs::Float64 flw_ref_pos_msg;
348  std_msgs::Float64 brw_ref_pos_msg;
349  std_msgs::Float64 blw_ref_pos_msg;
350 
351  flw_ref_pos_msg.data = alfa_ref_left;
352  frw_ref_pos_msg.data = alfa_ref_right;
353 
354  // Linear speed ref publish (could be improved by setting correct speed to each wheel according to turning state
355  // w = v_mps / (PI * D); w_rad = w * 2.0 * PI
356  double ref_speed_joint = 2.0 * v_ref_ / RBCAR_WHEEL_DIAMETER;
357 
358  std_msgs::Float64 frw_ref_vel_msg;
359  std_msgs::Float64 flw_ref_vel_msg;
360  std_msgs::Float64 brw_ref_vel_msg;
361  std_msgs::Float64 blw_ref_vel_msg;
362  frw_ref_vel_msg.data = -ref_speed_joint;
363  flw_ref_vel_msg.data = -ref_speed_joint;
364  brw_ref_vel_msg.data = -ref_speed_joint;
365  blw_ref_vel_msg.data = -ref_speed_joint;
366 
367  // Publish msgs traction and direction
368  ref_vel_frw_.publish( frw_ref_vel_msg );
369  ref_vel_flw_.publish( flw_ref_vel_msg );
370  ref_vel_blw_.publish( blw_ref_vel_msg );
371  ref_vel_brw_.publish( brw_ref_vel_msg );
372  ref_pos_frw_.publish( frw_ref_pos_msg );
373  ref_pos_flw_.publish( flw_ref_pos_msg );
374 }
375 
376 // Update robot odometry depending on kinematic configuration
378 {
379  // Get angles
380  double a1, a2;
381 
382  if( (ros::Time::now() - joint_state_.header.stamp).toSec() > RBCAR_JOINT_STATES_TIME_WINDOW){
383  ROS_WARN_THROTTLE(2, "RbcarControllerClass::UpdateOdometry: joint_states are not being received");
384  return;
385  }
386 
387  // joint_state_.position[frw_pos_], joint_state_.position[flw_pos_])
388  a1 = radnorm2( joint_state_.position[frw_pos_] );
389  a2 = radnorm2( joint_state_.position[flw_pos_] );
390 
391  // Linear speed of each wheel [mps]
392  double v3, v4;
393  // filtering noise from the Velocity controller when the speed is 0.0 (by using an open loop with desired speed)
394  if( v_ref_ == 0.0){
395  v3 = 0.0;
396  v4 = 0.0;
397  }else{
398  v3 = joint_state_.velocity[blw_vel_] * (rbcar_wheel_diameter_ / 2.0);
399  v4 = joint_state_.velocity[brw_vel_] * (rbcar_wheel_diameter_ / 2.0);
400  }
401  // Turning angle front
402  double fBetaRads = (a1 + a2) / 2.0;
403 
404  // Linear speed
405  double fSamplePeriod = 1.0 / desired_freq_; // Default sample period
406  double v_mps = -(v3 + v4) / 2.0;
407 
408  // Compute orientation just integrating imu gyro (not so reliable with the simulated imu)
409  // robot_pose_pa_ += ang_vel_z_ * fSamplePeriod;
410 
411  // Compute orientation converting imu orientation estimation
412  tf::Quaternion q(orientation_x_, orientation_y_, orientation_z_, orientation_w_);
413  // ROS_INFO("ox=%5.2f oy=%5.2f oz=%5.2f ow=%5.2f", orientation_x_, orientation_y_, orientation_z_, orientation_w_);
414  tf::Matrix3x3 m(q);
415  double roll, pitch, yaw;
416  m.getRPY(roll, pitch, yaw);
417  robot_pose_pa_ = yaw;
418 
419  // Normalize
420  while (robot_pose_pa_ >= PI)
421  robot_pose_pa_ -= 2.0 * PI;
422  while (robot_pose_pa_ <= (-PI))
423  robot_pose_pa_ += 2.0 * PI;
424 
425  double vx = v_mps * cos(fBetaRads) * cos(robot_pose_pa_);
426  double vy = v_mps * cos(fBetaRads) * sin(robot_pose_pa_);
427 
428  // Positions
429  robot_pose_px_ += vx * fSamplePeriod;
430  robot_pose_py_ += vy * fSamplePeriod;
431 
432  // Compute Velocity (linearSpeedXMps_ computed in control
433  robot_pose_vx_ = vx;
434  robot_pose_vy_ = vy;
435 
436  // ROS_INFO("Odom estimated x=%5.2f y=%5.2f a=%5.2f", robot_pose_px_, robot_pose_py_, robot_pose_pa_);
437 }
438 
439 // Publish robot odometry tf and topic depending
441 {
442  ros::Time current_time = ros::Time::now();
443 
444  //first, we'll publish the transform over tf
445  // TODO change to tf_prefix
446  geometry_msgs::TransformStamped odom_trans;
447  odom_trans.header.stamp = current_time;
448  odom_trans.header.frame_id = "odom";
449  odom_trans.child_frame_id = "base_footprint";
450 
451  odom_trans.transform.translation.x = robot_pose_px_;
452  odom_trans.transform.translation.y = robot_pose_py_;
453  odom_trans.transform.translation.z = 0.0;
454  odom_trans.transform.rotation.x = orientation_x_;
455  odom_trans.transform.rotation.y = orientation_y_;
456  odom_trans.transform.rotation.z = orientation_z_;
457  odom_trans.transform.rotation.w = orientation_w_;
458 
459  // send the transform over /tf
460  // activate / deactivate with param
461  // this tf in needed when not using robot_pose_ekf
462  if (publish_odom_tf_) odom_broadcaster.sendTransform(odom_trans);
463 
464  //next, we'll publish the odometry message over ROS
465  nav_msgs::Odometry odom;
466  odom.header.stamp = current_time;
467  odom.header.frame_id = "odom";
468 
469  //set the position
470  // Position
471  odom.pose.pose.position.x = robot_pose_px_;
472  odom.pose.pose.position.y = robot_pose_py_;
473  odom.pose.pose.position.z = 0.0;
474  // Orientation
475  odom.pose.pose.orientation.x = orientation_x_;
476  odom.pose.pose.orientation.y = orientation_y_;
477  odom.pose.pose.orientation.z = orientation_z_;
478  odom.pose.pose.orientation.w = orientation_w_;
479  // Pose covariance
480  for(int i = 0; i < 6; i++)
481  odom.pose.covariance[i*6+i] = 0.1; // test 0.001
482 
483  //set the velocity
484  odom.child_frame_id = "base_footprint";
485  // Linear velocities
486  odom.twist.twist.linear.x = robot_pose_vx_;
487  odom.twist.twist.linear.y = robot_pose_vy_;
488  odom.twist.twist.linear.z = 0.0;
489  // Angular velocities
490  odom.twist.twist.angular.x = ang_vel_x_;
491  odom.twist.twist.angular.y = ang_vel_y_;
492  odom.twist.twist.angular.z = ang_vel_z_;
493  // Twist covariance
494  for(int i = 0; i < 6; i++)
495  odom.twist.covariance[6*i+i] = 0.1; // test 0.001
496 
497  //publish the message
498  odom_pub_.publish(odom);
499 }
500 
502 void stopping()
503 {}
504 
505 
506 /*
507  * \brief Checks that the robot is receiving at a correct frequency the command messages. Diagnostics
508  *
509  */
511 {
512  ros::Time current_time = ros::Time::now();
513 
514  double diff = (current_time - last_command_time_).toSec();
515 
516  if(diff > 1.0){
517  stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Topic is not receiving commands");
518  //ROS_INFO("check_command_subscriber: %lf seconds without commands", diff);
519  // If no command is received, set Speed References to 0
520  // Turning angle can stay in the previous position.
521  v_ref_ = 0.0;
522  }else{
523  stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Topic receiving commands");
524  }
525 }
526 
527 
528 // Set the base velocity command
529 // void setCommand(const geometry_msgs::Twist &cmd_vel)
530 void setCommand(const ackermann_msgs::AckermannDriveStamped &msg)
531 {
532  // Mapping - linear = v_ref_, angular = alfa_ref_
533  double speed_limit = 10.0; // m/s
534  double angle_limit = PI/4.0; // there should be also urdf limits
535  v_ref_ = saturation(msg.drive.speed, -speed_limit, speed_limit);
536  alfa_ref_ = saturation(msg.drive.steering_angle, -angle_limit, angle_limit);
537 }
538 
539 // Service SetOdometry
540 bool srvCallback_SetOdometry(robotnik_msgs::set_odometry::Request &request, robotnik_msgs::set_odometry::Response &response )
541 {
542  // ROS_INFO("rbcar_odometry::set_odometry: request -> x = %f, y = %f, a = %f", req.x, req.y, req.orientation);
543  robot_pose_px_ = request.x;
544  robot_pose_py_ = request.y;
545  robot_pose_pa_ = request.orientation;
546 
547  response.ret = true;
548  return true;
549 }
550 
551 // Topic command
552 void jointStateCallback(const sensor_msgs::JointStateConstPtr& msg)
553 {
554  joint_state_ = *msg;
555  read_state_ = true;
556 }
557 
558 // Topic command
559 // void commandCallback(const geometry_msgs::TwistConstPtr& msg)
560 // void commandCallback(const ackermann_msgs::AckermannDriveStamped& msg)
561 void commandCallback(const ackermann_msgs::AckermannDriveStamped::ConstPtr& msg)
562 {
563  // Safety check
564  last_command_time_ = ros::Time::now();
565  subs_command_freq->tick(); // For diagnostics
566 
567  base_vel_msg_ = *msg;
568  this->setCommand(base_vel_msg_);
569 }
570 
571 // Imu callback
572 void imuCallback( const sensor_msgs::Imu& imu_msg){
573 
574  orientation_x_ = imu_msg.orientation.x;
575  orientation_y_ = imu_msg.orientation.y;
576  orientation_z_ = imu_msg.orientation.z;
577  orientation_w_ = imu_msg.orientation.w;
578 
579  ang_vel_x_ = imu_msg.angular_velocity.x;
580  ang_vel_y_ = imu_msg.angular_velocity.y;
581  ang_vel_z_ = imu_msg.angular_velocity.z;
582 
583  lin_acc_x_ = imu_msg.linear_acceleration.x;
584  lin_acc_y_ = imu_msg.linear_acceleration.y;
585  lin_acc_z_ = imu_msg.linear_acceleration.z;
586 }
587 
588 double saturation(double u, double min, double max)
589 {
590  if (u>max) u=max;
591  if (u<min) u=min;
592  return u;
593 }
594 
595 double radnorm( double value )
596 {
597  while (value > PI) value -= PI;
598  while (value < -PI) value += PI;
599  return value;
600 }
601 
602 double radnorm2( double value )
603 {
604  while (value > 2.0*PI) value -= 2.0*PI;
605  while (value < -2.0*PI) value += 2.0*PI;
606  return value;
607 }
608 
609 bool spin()
610 {
611  ROS_INFO("rbcar_robot_control::spin()");
612  ros::Rate r(desired_freq_); // 50.0
613 
614  while (!ros::isShuttingDown()) // Using ros::isShuttingDown to avoid restarting the node during a shutdown.
615  {
616  if (starting() == 0)
617  {
618  while(ros::ok() && node_handle_.ok()) {
619  UpdateControl();
620  UpdateOdometry();
621  PublishOdometry();
622  diagnostic_.update();
623  ros::spinOnce();
624  r.sleep();
625  }
626  ROS_INFO("END OF ros::ok() !!!");
627  } else {
628  // No need for diagnostic here since a broadcast occurs in start
629  // when there is an error.
630  usleep(1000000);
631  ros::spinOnce();
632  }
633  }
634 
635  return true;
636 }
637 
638 }; // Class RbcarControllerClass
639 
640 int main(int argc, char** argv)
641 {
642  ros::init(argc, argv, "rbcar_robot_control");
643 
644  ros::NodeHandle n;
645  RbcarControllerClass scc(n);
646 
647  // ros::ServiceServer service = n.advertiseService("set_odometry", &rbcar_node::set_odometry, &scc);
648  scc.spin();
649 
650  return (0);
651 }
652 
void imuCallback(const sensor_msgs::Imu &imu_msg)
d
ros::NodeHandle node_handle_
#define RBCAR_JOINT_STATES_TIME_WINDOW
double radnorm(double value)
diagnostic_updater::HeaderlessTopicDiagnostic * subs_command_freq
#define ROS_WARN_THROTTLE(rate,...)
void publish(const boost::shared_ptr< M > &message) const
void summary(unsigned char lvl, const std::string s)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
sensor_msgs::JointState joint_state_
ros::Subscriber joint_state_sub_
void setHardwareID(const std::string &hwid)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void add(const std::string &name, TaskFunction f)
void setCommand(const ackermann_msgs::AckermannDriveStamped &msg)
#define RBCAR_MIN_COMMAND_REC_FREQ
void check_command_subscriber(diagnostic_updater::DiagnosticStatusWrapper &stat)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
tf::TransformBroadcaster odom_broadcaster
#define ROS_WARN(...)
ros::ServiceServer srv_SetOdometry_
void stopping()
Controller stopping.
ackermann_msgs::AckermannDriveStamped base_vel_msg_
bool srvCallback_SetOdometry(robotnik_msgs::set_odometry::Request &request, robotnik_msgs::set_odometry::Response &response)
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ROSCPP_DECL bool ok()
void sendTransform(const StampedTransform &transform)
ROSCPP_DECL bool isShuttingDown()
diagnostic_updater::FrequencyStatus freq_diag_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define RBCAR_WHEEL_DIAMETER
bool sleep()
diagnostic_updater::Updater diagnostic_
int starting()
Controller startup in realtime.
RbcarControllerClass(ros::NodeHandle h)
Public constructor.
void UpdateControl()
Controller update loop.
double radnorm2(double value)
#define RBCAR_D_WHEELS_M
bool getParam(const std::string &key, std::string &s) const
void jointStateCallback(const sensor_msgs::JointStateConstPtr &msg)
diagnostic_updater::FunctionDiagnosticTask command_freq_
void commandCallback(const ackermann_msgs::AckermannDriveStamped::ConstPtr &msg)
static Time now()
ros::NodeHandle private_node_handle_
bool ok() const
ROSCPP_DECL void spinOnce()
#define ROS_ERROR(...)
int main(int argc, char **argv)
#define PI
double saturation(double u, double min, double max)
#define RBCAR_MAX_COMMAND_REC_FREQ


rbcar_robot_control
Author(s): Roberto Guzman
autogenerated on Mon Jun 10 2019 14:38:48