guardian_robot_control.cpp
Go to the documentation of this file.
00001 /*
00002  * guardian_robot_control
00003  * Copyright (c) 2013, Robotnik Automation, SLL
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  *     * Redistributions of source code must retain the above copyright
00010  *       notice, this list of conditions and the following disclaimer.
00011  *     * Redistributions in binary form must reproduce the above copyright
00012  *       notice, this list of conditions and the following disclaimer in the
00013  *       documentation and/or other materials provided with the distribution.
00014  *     * Neither the name of the Robotnik Automation, SLL. nor the names of its
00015  *       contributors may be used to endorse or promote products derived from
00016  *       this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  * \author Robotnik
00031  * \brief Controller for the Guardian robot in skid-steering mode
00032  */
00033 
00034 #include <ros/ros.h>
00035 #include <sensor_msgs/JointState.h>
00036 #include <sensor_msgs/Imu.h>
00037 #include <geometry_msgs/Twist.h>
00038 #include <std_msgs/Float64.h>
00039 #include <tf/transform_broadcaster.h>
00040 #include <nav_msgs/Odometry.h>
00041 #include <robotnik_msgs/set_mode.h>
00042 #include <robotnik_msgs/get_mode.h>
00043 #include <robotnik_msgs/set_odometry.h>
00044 #include <robotnik_msgs/ptz.h>
00045 
00046 
00047 //#include "self_test/self_test.h"
00048 #include "diagnostic_msgs/DiagnosticStatus.h"
00049 #include "diagnostic_updater/diagnostic_updater.h"
00050 #include "diagnostic_updater/update_functions.h"
00051 #include "diagnostic_updater/DiagnosticStatusWrapper.h"
00052 #include "diagnostic_updater/publisher.h"
00053 
00054 
00055 #define PI 3.1415926535
00056 #define GUARDIAN_MIN_COMMAND_REC_FREQ   5.0
00057 #define GUARDIAN_MAX_COMMAND_REC_FREQ   150.0
00058 
00059 #define SKID_STEERING                1
00060 #define MECANUM_STEERING             2
00061 
00062 #define GUARDIAN_WHEEL_DIAMETER 0.25      // Default wheel diameter
00063 #define GUARDIAN_D_TRACKS_M     1.0       // default equivalent W distance (difference is due to slippage of skid steering)
00064 #define GUARDIAN_WHEELBASE         0.446     // default real L distance forward to rear axis
00065 #define GUARDIAN_TRACKWIDTH        0.408     // default real W distance from left wheels to right wheels
00066     
00067 using namespace std;
00068 
00069 class GuardianControllerClass {
00070 
00071 public:
00072 
00073   ros::NodeHandle node_handle_;
00074   ros::NodeHandle private_node_handle_;
00075   double desired_freq_;
00076 
00077   // Diagnostics
00078   diagnostic_updater::Updater diagnostic_;                      // General status diagnostic updater
00079   diagnostic_updater::FrequencyStatus freq_diag_;                        // Component frequency diagnostics
00080   diagnostic_updater::HeaderlessTopicDiagnostic *subs_command_freq; // Topic reception frequency diagnostics
00081   ros::Time last_command_time_;                                 // Last moment when the component received a command
00082   diagnostic_updater::FunctionDiagnosticTask command_freq_;
00083 
00084   // Robot model 
00085   std::string robot_model_;
00086   
00087   // Velocity and position references to low level controllers
00088   ros::Publisher ref_vel_flw_;
00089   ros::Publisher ref_vel_frw_;
00090   ros::Publisher ref_vel_blw_;
00091   ros::Publisher ref_vel_brw_;
00092   ros::Publisher ref_pos_flw_;
00093   ros::Publisher ref_pos_frw_;
00094   ros::Publisher ref_pos_blw_;
00095   ros::Publisher ref_pos_brw_; 
00096   ros::Publisher ref_pos_pan_;
00097   ros::Publisher ref_pos_tilt_;
00098 
00099   // Joint states published by the joint_state_controller of the Controller Manager
00100   ros::Subscriber joint_state_sub_;
00101 
00102   // High level robot command
00103   ros::Subscriber cmd_sub_;
00104         
00105   // High level robot command
00106   ros::Subscriber ptz_sub_;
00107 
00108   //ros::Subscriber gyro_sub_;
00109 
00110   // Services
00111   ros::ServiceServer srv_SetOdometry_;
00112   ros::ServiceServer srv_SetMode_;
00113   ros::ServiceServer srv_GetMode_;
00114   
00115   // Topics - skid - velocity
00116   std::string frw_vel_topic_;
00117   std::string flw_vel_topic_;
00118   std::string brw_vel_topic_;
00119   std::string blw_vel_topic_;
00120   
00121   // Joint names - skid - velocity 
00122   std::string joint_front_right_wheel;
00123   std::string joint_front_left_wheel;
00124   std::string joint_back_left_wheel;
00125   std::string joint_back_right_wheel;
00126 
00127   // Joint names - ptz - position
00128   std::string joint_camera_pan;
00129   std::string joint_camera_tilt;
00130 
00131   // Topics - ptz
00132   std::string pan_pos_topic_;
00133   std::string tilt_pos_topic_;
00134     
00135   // Selected operation mode
00136   int kinematic_modes_;   
00137   int active_kinematic_mode_;
00138 
00139   // Indexes to joint_states
00140   int frw_vel_, flw_vel_, blw_vel_, brw_vel_;
00141   int pan_pos_, tilt_pos_;
00142 
00143   // Robot Speeds
00144   double linearSpeedXMps_;
00145   double linearSpeedYMps_;
00146   double angularSpeedRads_;
00147 
00148   // Robot Positions
00149   double robot_pose_px_;
00150   double robot_pose_py_;
00151   double robot_pose_pa_;
00152   double robot_pose_vx_;
00153   double robot_pose_vy_;
00154   
00155   // Robot Joint States
00156   sensor_msgs::JointState joint_state_;
00157   
00158   // Command reference
00159   geometry_msgs::Twist base_vel_msg_;
00160 
00161   // External speed references
00162   double v_ref_x_;
00163   double v_ref_y_;
00164   double w_ref_;
00165   double v_ref_z_;
00166   double pos_ref_pan_;
00167   double pos_ref_tilt_;
00168   
00169   // Flag to indicate if joint_state has been read
00170   bool read_state_; 
00171   
00172   // Robot configuration parameters 
00173   double guardian_wheel_diameter_; 
00174   double guardian_d_tracks_m_;
00175   double guardian_wheelbase_;
00176   double guardian_trackwidth_;
00177 
00178   // IMU values
00179   double ang_vel_x_;
00180   double ang_vel_y_;
00181   double ang_vel_z_;
00182 
00183   double lin_acc_x_;
00184   double lin_acc_y_;
00185   double lin_acc_z_;
00186 
00187   double orientation_x_;
00188   double orientation_y_;
00189   double orientation_z_;
00190   double orientation_w_;
00191 
00192   // Parameter that defines if odom tf is published or not
00193   bool publish_odom_tf_;
00194 
00195   ros::Subscriber imu_sub_; 
00196   
00197   // Publisher for odom topic
00198   ros::Publisher odom_pub_; 
00199 
00200   // Broadcaster for odom tf  
00201   tf::TransformBroadcaster odom_broadcaster;
00202 
00203 
00207 GuardianControllerClass(ros::NodeHandle h) : diagnostic_(),
00208   node_handle_(h), private_node_handle_("~"), 
00209   desired_freq_(100),
00210   freq_diag_(diagnostic_updater::FrequencyStatusParam(&desired_freq_, &desired_freq_, 0.05)   ),
00211   command_freq_("Command frequency check", boost::bind(&GuardianControllerClass::check_command_subscriber, this, _1))
00212   {
00213 
00214   // /guardian/joint_blw_velocity_controller/joint
00215   ROS_INFO("guardian_robot_control_node - Init ");
00216 
00217   // 4-Axis Skid Steer Rover
00218   // 8-Axis Omni-drive as 4-Axis Mecanum drive
00219   kinematic_modes_ = 1;  
00220   
00221   ros::NodeHandle guardian_robot_control_node_handle(node_handle_, "guardian_robot_control");
00222 
00223   // Get robot model from the parameters
00224   if (!private_node_handle_.getParam("model", robot_model_)) {
00225           ROS_ERROR("Robot model not defined.");
00226           exit(-1);
00227           }
00228   else ROS_INFO("Robot Model : %s", robot_model_.c_str());
00229 
00230   // Skid configuration - topics
00231   private_node_handle_.param<std::string>("frw_vel_topic", frw_vel_topic_, "/guardian/joint_frw_velocity_controller/command");
00232   private_node_handle_.param<std::string>("flw_vel_topic", flw_vel_topic_, "/guardian/joint_flw_velocity_controller/command");
00233   private_node_handle_.param<std::string>("blw_vel_topic", blw_vel_topic_, "/guardian/joint_blw_velocity_controller/command");
00234   private_node_handle_.param<std::string>("brw_vel_topic", brw_vel_topic_, "/guardian/joint_brw_velocity_controller/command");
00235 
00236   // Skid configuration - Joint names 
00237   private_node_handle_.param<std::string>("joint_front_right_wheel", joint_front_right_wheel, "joint_front_right_wheel");
00238   private_node_handle_.param<std::string>("joint_front_left_wheel", joint_front_left_wheel, "joint_front_left_wheel");
00239   private_node_handle_.param<std::string>("joint_back_left_wheel", joint_back_left_wheel, "joint_back_left_wheel");
00240   private_node_handle_.param<std::string>("joint_back_right_wheel", joint_back_right_wheel, "joint_back_right_wheel");
00241 
00242   // PTZ topics
00243   private_node_handle_.param<std::string>("pan_pos_topic", pan_pos_topic_, "/guardian/joint_pan_position_controller/command");
00244   private_node_handle_.param<std::string>("tilt_pos_topic", tilt_pos_topic_, "/guardian/joint_tilt_position_controller/command");
00245   private_node_handle_.param<std::string>("joint_camera_pan", joint_camera_pan, "joint_camera_pan");
00246   private_node_handle_.param<std::string>("joint_camera_tilt", joint_camera_tilt, "joint_camera_tilt");
00247 
00248   // Robot parameters
00249   if (!private_node_handle_.getParam("guardian_wheel_diameter", guardian_wheel_diameter_))
00250     guardian_wheel_diameter_ = GUARDIAN_WHEEL_DIAMETER;
00251   if (!private_node_handle_.getParam("guardian_d_tracks_m", guardian_d_tracks_m_))
00252     guardian_d_tracks_m_ = GUARDIAN_D_TRACKS_M;
00253   ROS_INFO("guardian_wheel_diameter_ = %5.2f", guardian_wheel_diameter_);
00254   ROS_INFO("guardian_d_tracks_m_ = %5.2f", guardian_d_tracks_m_);
00255 
00256   private_node_handle_.param("publish_odom_tf", publish_odom_tf_, true);
00257   if (publish_odom_tf_) ROS_INFO("PUBLISHING odom->base_footprin tf");
00258   else ROS_INFO("NOT PUBLISHING odom->base_footprint tf");
00259   
00260   // Robot Speeds
00261   linearSpeedXMps_   = 0.0;
00262   linearSpeedYMps_   = 0.0;
00263   angularSpeedRads_  = 0.0;
00264 
00265   // Robot Positions
00266   robot_pose_px_ = 0.0;
00267   robot_pose_py_ = 0.0;
00268   robot_pose_pa_ = 0.0;
00269   robot_pose_vx_ = 0.0;
00270   robot_pose_vy_ = 0.0;
00271 
00272   // External speed references
00273   v_ref_x_ = 0.0;
00274   v_ref_y_ = 0.0;
00275   w_ref_ = 0.0;
00276   v_ref_z_ = 0.0;
00277   pos_ref_pan_ = 0.0;
00278   pos_ref_tilt_= 0.0;
00279 
00280   // Imu variables
00281   ang_vel_x_ = 0.0; ang_vel_y_ = 0.0; ang_vel_z_ = 0.0;
00282   lin_acc_x_ = 0.0; lin_acc_y_ = 0.0; lin_acc_z_ = 0.0;
00283   orientation_x_ = 0.0; orientation_y_ = 0.0; orientation_z_ = 0.0; orientation_w_ = 0.0;
00284 
00285   // Active kinematic mode
00286   active_kinematic_mode_ = SKID_STEERING;
00287 
00288   // Advertise services
00289   srv_SetMode_ = guardian_robot_control_node_handle.advertiseService("set_mode", &GuardianControllerClass::srvCallback_SetMode, this);
00290   srv_GetMode_ = guardian_robot_control_node_handle.advertiseService("get_mode", &GuardianControllerClass::srvCallback_GetMode, this);
00291   srv_SetOdometry_ = guardian_robot_control_node_handle.advertiseService("set_odometry",  &GuardianControllerClass::srvCallback_SetOdometry, this);
00292 
00293   // Subscribe to joint states topic
00294   joint_state_sub_ = guardian_robot_control_node_handle.subscribe<sensor_msgs::JointState>("/guardian/joint_states", 1, &GuardianControllerClass::jointStateCallback, this);
00295 
00296   // Subscribe to imu data
00297   imu_sub_ = guardian_robot_control_node_handle.subscribe("/guardian/imu_data", 1, &GuardianControllerClass::imuCallback, this);
00298 
00299   // Adevertise reference topics for the controllers 
00300   ref_vel_frw_ = guardian_robot_control_node_handle.advertise<std_msgs::Float64>( frw_vel_topic_, 50);
00301   ref_vel_flw_ = guardian_robot_control_node_handle.advertise<std_msgs::Float64>( flw_vel_topic_, 50);
00302   ref_vel_blw_ = guardian_robot_control_node_handle.advertise<std_msgs::Float64>( blw_vel_topic_, 50);
00303   ref_vel_brw_ = guardian_robot_control_node_handle.advertise<std_msgs::Float64>( brw_vel_topic_, 50);
00304           
00305   ref_pos_pan_ = guardian_robot_control_node_handle.advertise<std_msgs::Float64>( pan_pos_topic_, 50);
00306   ref_pos_tilt_ = guardian_robot_control_node_handle.advertise<std_msgs::Float64>( tilt_pos_topic_, 50);
00307 
00308   // Subscribe to command topic
00309   cmd_sub_ = guardian_robot_control_node_handle.subscribe<geometry_msgs::Twist>("command", 1, &GuardianControllerClass::commandCallback, this);
00310 
00311   // Subscribe to ptz command topic
00312   ptz_sub_ = guardian_robot_control_node_handle.subscribe<robotnik_msgs::ptz>("command_ptz", 1, &GuardianControllerClass::command_ptzCallback, this);
00313   // /guardian_robot_control/command_ptz
00314   
00315   // TODO odom topic as parameter
00316   // Publish odometry 
00317   odom_pub_ = guardian_robot_control_node_handle.advertise<nav_msgs::Odometry>("/guardian/odom", 1000);
00318 
00319   // Component frequency diagnostics
00320   diagnostic_.setHardwareID("guardian_robot_control - simulation");
00321   diagnostic_.add( freq_diag_ );
00322   diagnostic_.add( command_freq_ );
00323     
00324   // Topics freq control 
00325   // For /guardian_robot_control/command
00326   double min_freq = GUARDIAN_MIN_COMMAND_REC_FREQ; // If you update these values, the
00327   double max_freq = GUARDIAN_MAX_COMMAND_REC_FREQ; // HeaderlessTopicDiagnostic will use the new values.
00328   subs_command_freq = new diagnostic_updater::HeaderlessTopicDiagnostic("/guardian_robot_control/command", diagnostic_,
00329                             diagnostic_updater::FrequencyStatusParam(&min_freq, &max_freq, 0.1, 10));
00330   subs_command_freq->addTask(&command_freq_); // Adding an additional task to the control
00331   
00332   // Flag to indicate joint_state has been read
00333   read_state_ = false;
00334 }
00335 
00337 int starting()
00338 {
00339 
00340   ROS_INFO("GuardianControllerClass::starting");
00341 
00342   //name: ['joint_back_left_wheel', 'joint_back_right_wheel', 'joint_front_left_wheel', 'joint_front_right_wheel']
00343   //position: [-0.04246698357387224, 0.053199274627900195, -0.04246671523622059, 0.03126368464965523]
00344   //velocity: [-0.0006956167983269147, 0.0004581098383479411, -0.0013794952191663358, 0.00045523862784977847]
00345 
00346   // Initialize joint indexes according to joint names 
00347   if (read_state_) {
00348     vector<string> joint_names = joint_state_.name;
00349     frw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_front_right_wheel)) - joint_names.begin();
00350     flw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_front_left_wheel)) - joint_names.begin();
00351     blw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_back_left_wheel)) - joint_names.begin();
00352     brw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_back_right_wheel)) - joint_names.begin();
00353         // For publishing the ptz joint state   
00354         //pan_pos_ = find(joint_names.begin(), joint_names.end(), string(joint_camera_pan)) - joint_names.begin();
00355         //tilt_pos_ = find(joint_names.begin(), joint_names.end(), string(joint_camera_tilt)) - joint_names.begin();
00356     return 0;
00357     }
00358   else return -1;
00359 }
00360 
00361 
00363 void UpdateControl()
00364 {
00365   // Depending on the robot configuration 
00366   if (active_kinematic_mode_ == SKID_STEERING) {
00367 
00368           double v_left_mps, v_right_mps;
00369 
00370           // Calculate its own velocities for realize the motor control 
00371           v_left_mps = ((joint_state_.velocity[blw_vel_] + joint_state_.velocity[flw_vel_]) / 2.0) * (guardian_wheel_diameter_ / 2.0);
00372           v_right_mps = -((joint_state_.velocity[brw_vel_] + joint_state_.velocity[frw_vel_]) / 2.0) * (guardian_wheel_diameter_ / 2.0); 
00373           // sign according to urdf (if wheel model is not symetric, should be inverted)
00374 
00375           linearSpeedXMps_ = (v_right_mps + v_left_mps) / 2.0;                       // m/s
00376           angularSpeedRads_ = (v_right_mps - v_left_mps) / guardian_d_tracks_m_;    // rad/s
00377 
00378           //ROS_INFO("vleft=%5.2f   vright=%5.2f    linearSpeedXMps=%5.2f, linearSpeedYMps=%5.2f, angularSpeedRads=%5.4f", v_left_mps, v_right_mps,
00379                 //      linearSpeedXMps_, linearSpeedYMps_, angularSpeedRads_); 
00380 
00381           // Current controllers close this loop allowing (v,w) references.
00382           double epv=0.0;
00383           double epw=0.0;
00384           static double epvant =0.0;
00385           static double epwant =0.0;
00386 
00387           // Adjusted for soft indoor office soil
00388           //double kpv=2.5; double kdv=0.0;
00389           //double kpw=2.5;  double kdw=0.0;
00390           // In order to use this controller with the move_base stack note that move_base sets the min rotation ref to 0.4 independantly of the yaml configurations!!!
00391           double kpv=2.5; double kdv=0.0;
00392           double kpw=25.0; double kdw=15.0;
00393 
00394           // State feedback error
00395           epv = v_ref_x_ - linearSpeedXMps_;
00396           epw = w_ref_ - angularSpeedRads_;
00397           // ROS_INFO("v_ref_x_=%5.2f, linearSpeedXMps_=%5.2f w_ref_=%5.2f angularSpeedRads_=%5.2f", v_ref_x_, linearSpeedXMps_, w_ref_, angularSpeedRads_);
00398 
00399           // Compute state control actions
00400           double uv= kpv * epv + kdv * (epv - epvant);
00401           double uw= kpw * epw + kdw * (epw - epwant);
00402           epvant = epv;
00403           epwant = epw;
00404 
00405           // Inverse kinematics
00406           double dUl = uv - 0.5 * guardian_d_tracks_m_ * uw;
00407           // sign according to urdf (if wheel model is not symetric, should be inverted)
00408           double dUr = -(uv + 0.5 * guardian_d_tracks_m_ * uw);  
00409 
00410           // Motor control actions
00411           double limit = 100.0;
00412           
00413           //ROS_INFO("epv=%5.2f, epw=%5.2f ***  dUl=%5.2f  dUr=%5.2f", epv, epw, dUl, dUr);
00414 
00415           // 
00416       std_msgs::Float64 frw_ref_msg; 
00417       std_msgs::Float64 flw_ref_msg;
00418       std_msgs::Float64 blw_ref_msg;
00419       std_msgs::Float64 brw_ref_msg;
00420           
00421       double k1 = 0.5; 
00422           
00423           frw_ref_msg.data = saturation( -k1 * dUr, -limit, limit);  
00424           flw_ref_msg.data = saturation( k1 * dUl, -limit, limit);
00425       blw_ref_msg.data = saturation( k1 * dUl, -limit, limit);
00426           brw_ref_msg.data = saturation( -k1 * dUr, -limit, limit);
00427           
00428           ref_vel_frw_.publish( frw_ref_msg );
00429           ref_vel_flw_.publish( flw_ref_msg );
00430           ref_vel_blw_.publish( blw_ref_msg );
00431           ref_vel_brw_.publish( brw_ref_msg );
00432           }
00433           
00434      // PTZ 
00435          std_msgs::Float64 pan_ref_pos_msg, tilt_ref_pos_msg;
00436      pan_ref_pos_msg.data = pos_ref_pan_;            //saturation( pos_ref_pan_, 0.0, 0.5); 
00437      ref_pos_pan_.publish( pan_ref_pos_msg );
00438      tilt_ref_pos_msg.data = pos_ref_tilt_;          //saturation( pos_ref_tilt_, 0.0, 0.5); 
00439      ref_pos_tilt_.publish( tilt_ref_pos_msg );
00440 }
00441 
00442 // Update robot odometry depending on kinematic configuration
00443 void UpdateOdometry()
00444 {
00445   // Depending on the robot configuration 
00446   if (active_kinematic_mode_ == SKID_STEERING) {
00447           
00448       // Compute Velocity (linearSpeedXMps_ computed in control
00449           robot_pose_vx_ = linearSpeedXMps_ *  cos(robot_pose_pa_);
00450       robot_pose_vy_ = linearSpeedXMps_ *  sin(robot_pose_pa_);
00451       }
00452                       
00453       // Compute Position
00454       double fSamplePeriod = 1.0 / desired_freq_;
00455           robot_pose_pa_ += ang_vel_z_ * fSamplePeriod;  // this velocity comes from IMU callback
00456       robot_pose_px_ += robot_pose_vx_ * fSamplePeriod;
00457       robot_pose_py_ += robot_pose_vy_ * fSamplePeriod;
00458       // ROS_INFO("Odom estimated x=%5.2f  y=%5.2f a=%5.2f", robot_pose_px_, robot_pose_py_, robot_pose_pa_);
00459 }
00460 
00461 // Publish robot odometry tf and topic depending 
00462 void PublishOdometry()
00463 {
00464         ros::Time current_time = ros::Time::now();
00465         
00466     //first, we'll publish the transform over tf
00467     geometry_msgs::TransformStamped odom_trans;
00468     odom_trans.header.stamp = current_time;
00469     odom_trans.header.frame_id = "odom";
00470     odom_trans.child_frame_id = "base_footprint";
00471 
00472     odom_trans.transform.translation.x = robot_pose_px_;
00473     odom_trans.transform.translation.y = robot_pose_py_;
00474     odom_trans.transform.translation.z = 0.0;
00475     odom_trans.transform.rotation.x = orientation_x_;
00476         odom_trans.transform.rotation.y = orientation_y_;
00477         odom_trans.transform.rotation.z = orientation_z_;
00478         odom_trans.transform.rotation.w = orientation_w_;
00479         
00480     // send the transform over /tf
00481         // activate / deactivate with param
00482         // this tf in needed when not using robot_pose_ekf
00483     if (publish_odom_tf_) odom_broadcaster.sendTransform(odom_trans);  
00484         
00485     //next, we'll publish the odometry message over ROS
00486     nav_msgs::Odometry odom;
00487     odom.header.stamp = current_time;
00488     odom.header.frame_id = "odom";
00489 
00490     //set the position
00491         // Position
00492     odom.pose.pose.position.x = robot_pose_px_;
00493     odom.pose.pose.position.y = robot_pose_py_;
00494     odom.pose.pose.position.z = 0.0;
00495         // Orientation
00496     odom.pose.pose.orientation.x = orientation_x_;
00497         odom.pose.pose.orientation.y = orientation_y_;
00498         odom.pose.pose.orientation.z = orientation_z_;
00499         odom.pose.pose.orientation.w = orientation_w_;
00500         // Pose covariance
00501     for(int i = 0; i < 6; i++)
00502                 odom.pose.covariance[i*6+i] = 0.1;  // test 0.001
00503 
00504     //set the velocity
00505     odom.child_frame_id = "base_footprint";
00506         // Linear velocities
00507     odom.twist.twist.linear.x = robot_pose_vx_;
00508     odom.twist.twist.linear.y = robot_pose_vy_;
00509         odom.twist.twist.linear.z = 0.0;
00510         // Angular velocities
00511         odom.twist.twist.angular.x = ang_vel_x_;
00512         odom.twist.twist.angular.y = ang_vel_y_;
00513     odom.twist.twist.angular.z = ang_vel_z_;
00514         // Twist covariance
00515         for(int i = 0; i < 6; i++)
00516                 odom.twist.covariance[6*i+i] = 0.1;  // test 0.001
00517 
00518     //publish the message
00519     odom_pub_.publish(odom);
00520 }
00521 
00523 void stopping()
00524 {}
00525 
00526 
00527 /*
00528  *      \brief Checks that the robot is receiving at a correct frequency the command messages. Diagnostics
00529  *
00530  */
00531 void check_command_subscriber(diagnostic_updater::DiagnosticStatusWrapper &stat)
00532 {
00533         ros::Time current_time = ros::Time::now();
00534 
00535         double diff = (current_time - last_command_time_).toSec();
00536 
00537         if(diff > 1.0){
00538                 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Topic is not receiving commands");
00539                 //ROS_INFO("check_command_subscriber: %lf seconds without commands", diff);
00540                 // TODO: Set Speed References to 0
00541         }else{
00542                 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Topic receiving commands");
00543         }
00544 }
00545 
00546 
00547 // Set the base velocity command
00548 void setCommand(const geometry_msgs::Twist &cmd_vel)
00549 {   
00550    v_ref_x_ = saturation(cmd_vel.linear.x, -10.0, 10.0);
00551    v_ref_y_ = saturation(cmd_vel.linear.y, -10.0, 10.0);        
00552    w_ref_ = saturation(cmd_vel.angular.z, -10.0, 10.0); // -10.0 10.0
00553    v_ref_z_ = saturation(cmd_vel.linear.z, -10.0, 10.0);
00554 }
00555 
00556 // CALLBACKS
00557 // Service SetMode
00558 bool srvCallback_SetMode(robotnik_msgs::set_mode::Request& request, robotnik_msgs::set_mode::Response& response)
00559 {
00560   // Only SKID STEERING mode
00561   /*
00562   ROS_INFO("GuardianControllerClass::srvCallback_SetMode request.mode= %d", request.mode);
00563   if (request.mode == 1) {
00564         active_kinematic_mode_ = request.mode;
00565         return true;
00566         }
00567   if (request.mode == 2) {
00568         if (kinematic_modes_ == 2) {
00569                 active_kinematic_mode_ = request.mode;
00570                 return true;    
00571                 }
00572         else return false;
00573         }
00574         */      
00575   return false;
00576 }
00577 
00578 // Service GetMode
00579 bool srvCallback_GetMode(robotnik_msgs::get_mode::Request& request, robotnik_msgs::get_mode::Response& response)
00580 {
00581   response.mode = active_kinematic_mode_;
00582   return true;  
00583 }
00584 
00585 
00586 // Service SetOdometry 
00587 bool srvCallback_SetOdometry(robotnik_msgs::set_odometry::Request &request, robotnik_msgs::set_odometry::Response &response )
00588 {
00589         // ROS_INFO("guardian_odometry::set_odometry: request -> x = %f, y = %f, a = %f", req.x, req.y, req.orientation);
00590         //robot_pose_px_ = req.x;
00591         //robot_pose_py_ = req.y;
00592         //robot_pose_pa_ = req.orientation;
00593 
00594         response.ret = true;
00595         return true;
00596 }
00597 
00598 
00599 // Topic command
00600 void jointStateCallback(const sensor_msgs::JointStateConstPtr& msg)
00601 {       
00602   joint_state_ = *msg;
00603   read_state_ = true;
00604 }
00605 
00606 // Topic command
00607 void commandCallback(const geometry_msgs::TwistConstPtr& msg)
00608 {
00609   // Safety check
00610   last_command_time_ = ros::Time::now();
00611   subs_command_freq->tick();                    // For diagnostics
00612 
00613   base_vel_msg_ = *msg;
00614   this->setCommand(base_vel_msg_);
00615 }
00616 
00617 // Topic ptz command
00618 void command_ptzCallback(const robotnik_msgs::ptzConstPtr& msg)
00619 {
00620   pos_ref_pan_ += msg->pan / 180.0 * PI;
00621   pos_ref_tilt_ += msg->tilt / 180.0 * PI;
00622 }
00623 
00624 // Imu callback
00625 void imuCallback( const sensor_msgs::Imu& imu_msg){
00626 
00627         orientation_x_ = imu_msg.orientation.x;
00628         orientation_y_ = imu_msg.orientation.y;
00629         orientation_z_ = imu_msg.orientation.z;
00630         orientation_w_ = imu_msg.orientation.w;
00631 
00632         ang_vel_x_ = imu_msg.angular_velocity.x;
00633         ang_vel_y_ = imu_msg.angular_velocity.y;
00634         ang_vel_z_ = imu_msg.angular_velocity.z;
00635 
00636         lin_acc_x_ = imu_msg.linear_acceleration.x;
00637         lin_acc_y_ = imu_msg.linear_acceleration.y;
00638         lin_acc_z_ = imu_msg.linear_acceleration.z;
00639 }
00640 
00641 double saturation(double u, double min, double max)
00642 {
00643  if (u>max) u=max;
00644  if (u<min) u=min;
00645  return u; 
00646 }
00647 
00648 double radnorm( double value ) 
00649 {
00650   while (value > PI) value -= PI;
00651   while (value < -PI) value += PI;
00652   return value;
00653 }
00654 
00655 double radnorm2( double value ) 
00656 {
00657   while (value > 2.0*PI) value -= 2.0*PI;
00658   while (value < -2.0*PI) value += 2.0*PI;
00659   return value;
00660 }
00661 
00662 bool spin()
00663 {
00664     ROS_INFO("guardian_robot_control::spin()");
00665     ros::Rate r(desired_freq_);  // 50.0 
00666 
00667     while (!ros::isShuttingDown()) // Using ros::isShuttingDown to avoid restarting the node during a shutdown.
00668     {
00669       if (starting() == 0)
00670       {
00671             while(ros::ok() && node_handle_.ok()) {
00672           UpdateControl();
00673           UpdateOdometry();
00674           PublishOdometry();
00675           diagnostic_.update();
00676           ros::spinOnce();
00677               r.sleep();
00678           }
00679               ROS_INFO("END OF ros::ok() !!!");
00680       } else {
00681        // No need for diagnostic here since a broadcast occurs in start
00682        // when there is an error.
00683        usleep(1000000);
00684        ros::spinOnce();
00685       }
00686    }
00687 
00688    ROS_INFO("guardian_robot_control::spin() - end");
00689    return true;
00690 }
00691 
00692 }; // Class GuardianControllerClass
00693 
00694 int main(int argc, char** argv)
00695 {
00696         ros::init(argc, argv, "guardian_robot_control");
00697 
00698         ros::NodeHandle n;              
00699         GuardianControllerClass sxlrc(n);
00700 
00701         
00702         // ros::ServiceServer service = n.advertiseService("set_odometry", &guardian_node::set_odometry, &sxlc);
00703     sxlrc.spin();
00704 
00705         return (0);
00706 
00707         
00708 }
00709 


guardian_robot_control
Author(s): Roberto Guzmán
autogenerated on Fri Aug 28 2015 10:59:33