rbcar_pad.cpp
Go to the documentation of this file.
00001 /*
00002  * rbcar_pad
00003  * Copyright (c) 2015, 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 Automation, SLL
00031  * \brief Allows to use a pad with the robot controller, sending the messages received from the joystick device
00032  */
00033 
00034 #include <ros/ros.h>
00035 #include <sensor_msgs/Joy.h>
00036 #include <geometry_msgs/Twist.h>
00037 #include <std_msgs/Int32.h>
00038 #include <unistd.h>
00039 #include <vector>
00040 #include <robotnik_msgs/enable_disable.h>
00041 #include <robotnik_msgs/set_digital_output.h>
00042 #include "diagnostic_msgs/DiagnosticStatus.h"
00043 #include "diagnostic_updater/diagnostic_updater.h"
00044 #include "diagnostic_updater/update_functions.h"
00045 #include "diagnostic_updater/DiagnosticStatusWrapper.h"
00046 #include "diagnostic_updater/publisher.h"
00047 #include "ackermann_msgs/AckermannDriveStamped.h"
00048 #include <std_srvs/Empty.h>
00049 #include "robotnik_msgs/set_mode.h"
00050 #include "robotnik_msgs/get_mode.h"
00051 
00052 #define DEFAULT_MAX_LINEAR_SPEED            3.0 //m/s
00053 #define DEFAULT_MAX_ANGULAR_POSITION    0.5 // rads/s
00054 
00055 #define MAX_NUM_OF_BUTTONS                      16
00056 #define MAX_NUM_OF_AXES                         8
00057 #define MAX_NUM_OF_BUTTONS_PS3          19
00058 #define MAX_NUM_OF_AXES_PS3                     20
00059 
00060 #define DEFAULT_NUM_OF_BUTTONS          16
00061 #define DEFAULT_NUM_OF_AXES                     8
00062 
00063 #define DEFAULT_AXIS_LINEAR_X           1
00064 #define DEFAULT_AXIS_ANGULAR            2
00065 #define DEFAULT_SCALE_LINEAR            1.0
00066 #define DEFAULT_SCALE_ANGULAR           1.0
00067 
00068 #define DEFAULT_JOY                     "/joy"
00069 #define DEFAULT_HZ                      50.0
00070 
00071 
00073 class Button{
00074         int iPressed;
00075         bool bReleased;
00076         
00077         public:
00078         
00079         Button(){
00080                 iPressed = 0;
00081                 bReleased = false;
00082         }
00084         void Press(int value){          
00085                 if(iPressed and !value){
00086                         bReleased = true;
00087                         
00088                 }else if(bReleased and value)
00089                         bReleased = false;
00090                         
00091                 iPressed = value;
00092                         
00093         }
00094         
00095         int IsPressed(){
00096                 return iPressed;
00097         }
00098         
00099         bool IsReleased(){
00100                 bool b = bReleased;
00101                 bReleased = false;
00102                 return b;
00103         }
00104 };
00105 
00106 class RbcarPad
00107 {
00108 public:
00109   RbcarPad();
00110 
00111         void ControlLoop();
00112         int SetStateMode(int state, int arm_mode, int platform_mode);
00113         
00114 private:
00115         
00116         void joyCallback(const sensor_msgs::Joy::ConstPtr& joy);
00117         
00118         char * StateToString(int state);
00119         int SwitchToState(int new_state);
00120         
00121         void PublishState();
00123         bool EnableDisable(robotnik_msgs::enable_disable::Request &req, robotnik_msgs::enable_disable::Response &res );
00124         void Update();
00125 
00126 
00127 private:
00128         ros::NodeHandle nh_, pnh_;
00129         
00130         int axis_linear_speed_, axis_angular_position_;
00131         double l_scale_, a_scale_;
00132         double current_speed_lvl;
00134         double max_linear_speed_, max_angular_position_;
00136         double desired_freq_;
00137 
00138         // TOPICS
00140         ros::Publisher vel_pub_;        
00142         ros::Subscriber joy_sub_;
00144         std::string  joy_topic_;        
00146         std::string cmd_topic_vel;
00148         std::string cmd_service_io_;
00150         std::string topic_state_;
00152         ros::Publisher state_pub_;
00153 
00154         // SERVICES
00156         ros::ServiceServer enable_disable_srv_; 
00157         ros::ServiceClient set_digital_outputs_client_;  
00158 
00159         // JOYSTICK
00161         int num_of_buttons_;
00162         int num_of_axes_;
00163 
00165         std::vector<float> fAxes;
00167         std::vector<Button> vButtons;
00169         int button_dead_man_;
00171         int button_speed_up_, button_speed_down_;
00172         int output_1_, output_2_;
00173         bool bOutput1, bOutput2;
00175         int ptz_tilt_up_, ptz_tilt_down_, ptz_pan_right_, ptz_pan_left_;
00177         std::string cmd_service_ptz_;
00179         int button_kinematic_mode_;
00181         int kinematic_mode_;
00183         ros::ServiceClient setKinematicMode;  
00185         std::string cmd_set_mode_;
00186                 
00187         // DIAGNOSTICS
00189         diagnostic_updater::HeaderlessTopicDiagnostic *pub_command_freq; 
00191         diagnostic_updater::HeaderlessTopicDiagnostic *sus_joy_freq; 
00193         diagnostic_updater::Updater updater_pad;        
00195         double min_freq_command, min_freq_joy; 
00197         double max_freq_command, max_freq_joy;  
00199         bool bEnable;   
00200 };
00201 
00202 RbcarPad::RbcarPad():
00203   axis_linear_speed_(1),
00204   axis_angular_position_(2),
00205   pnh_("~")
00206 {
00207         current_speed_lvl = 0.1;
00208         // 
00209         pnh_.param("num_of_buttons", num_of_buttons_, DEFAULT_NUM_OF_BUTTONS);
00210         pnh_.param("num_of_axes", num_of_axes_, DEFAULT_NUM_OF_AXES);
00211         pnh_.param("desired_freq", desired_freq_, DEFAULT_HZ);
00212 
00213         if(num_of_axes_ > MAX_NUM_OF_AXES){
00214                 num_of_axes_ = MAX_NUM_OF_AXES;
00215                 ROS_INFO("RbcarPad::RbcarPad: Limiting the max number of axes to %d", MAX_NUM_OF_AXES);
00216                 }
00217         if(num_of_buttons_ > MAX_NUM_OF_BUTTONS){
00218                 num_of_buttons_ = MAX_NUM_OF_BUTTONS;
00219                 ROS_INFO("RbcarPad::RbcarPad: Limiting the max number of buttons to %d", MAX_NUM_OF_BUTTONS);
00220                 }
00221 
00222         pnh_.param("topic_joy", joy_topic_, std::string(DEFAULT_JOY));  
00223 
00224 
00225         // MOTION CONF
00226         pnh_.param("cmd_topic_vel", cmd_topic_vel, std::string("/rbcar_robot_control/command"));
00227         
00228         pnh_.param("button_dead_man", button_dead_man_, button_dead_man_);
00229         pnh_.param("button_speed_up", button_speed_up_, button_speed_up_);
00230         pnh_.param("button_speed_down", button_speed_down_, button_speed_down_); 
00231         pnh_.param("max_angular_position", max_angular_position_, DEFAULT_MAX_ANGULAR_POSITION); 
00232         pnh_.param("max_linear_speed_", max_linear_speed_, DEFAULT_MAX_LINEAR_SPEED); 
00233         pnh_.param("axis_linear_speed", axis_linear_speed_, DEFAULT_AXIS_LINEAR_X); 
00234         pnh_.param("axis_angular_position", axis_angular_position_, DEFAULT_AXIS_ANGULAR); 
00235         ROS_INFO("axis_linear_speed_ = %d, axis_angular = %d", axis_linear_speed_, axis_angular_position_);
00236         ROS_INFO("max_linear_speed = %lf, max_angular_speed = %lf", max_linear_speed_, max_angular_position_);
00237 
00238         // DIGITAL OUTPUTS CONF
00239         pnh_.param("cmd_service_io", cmd_service_io_, cmd_service_io_);
00240         pnh_.param("output_1", output_1_, output_1_);
00241         pnh_.param("output_2", output_2_, output_2_);
00242         pnh_.param("topic_state", topic_state_, std::string("/rbcar_pad/state"));
00243 
00244         // PANTILT CONF
00245         pnh_.param("cmd_service_ptz", cmd_service_ptz_, cmd_service_ptz_);
00246         pnh_.param("button_ptz_tilt_up", ptz_tilt_up_, ptz_tilt_up_);
00247         pnh_.param("button_ptz_tilt_down", ptz_tilt_down_, ptz_tilt_down_);
00248         pnh_.param("button_ptz_pan_right", ptz_pan_right_, ptz_pan_right_);
00249         pnh_.param("button_ptz_pan_left", ptz_pan_left_, ptz_pan_left_);
00250 
00251                 
00252         ROS_INFO("RbcarPad num_of_buttons_ = %d, axes = %d, topic controller: %s, hz = %.2lf", num_of_buttons_, num_of_axes_, cmd_topic_vel.c_str(), desired_freq_);    
00253         
00254         for(int i = 0; i < MAX_NUM_OF_BUTTONS_PS3; i++){
00255                 Button b;
00256                 vButtons.push_back(b);
00257         }
00258         
00259         for(int i = 0; i < MAX_NUM_OF_AXES_PS3; i++){
00260                 fAxes.push_back(0.0);
00261         }
00262         
00263         
00264         this->vel_pub_ = nh_.advertise<ackermann_msgs::AckermannDriveStamped>(this->cmd_topic_vel, 1);
00265                 
00266         // Listen through the node handle sensor_msgs::Joy messages from joystick 
00267         joy_sub_ = nh_.subscribe<sensor_msgs::Joy>(joy_topic_, 1, &RbcarPad::joyCallback, this);
00268         
00269         // Request service to activate / deactivate digital I/O
00270         set_digital_outputs_client_ = nh_.serviceClient<robotnik_msgs::set_digital_output>(cmd_service_io_);
00271                 
00272         bOutput1 = bOutput2 = false;
00273 
00274         // Diagnostics
00275         updater_pad.setHardwareID("RbcarPad");
00276         // Topics freq control 
00277         min_freq_command = min_freq_joy = 5.0;
00278         max_freq_command = max_freq_joy = 50.0;
00279         sus_joy_freq = new diagnostic_updater::HeaderlessTopicDiagnostic("/joy", updater_pad,
00280                             diagnostic_updater::FrequencyStatusParam(&min_freq_joy, &max_freq_joy, 0.1, 10));
00281 
00282         pub_command_freq = new diagnostic_updater::HeaderlessTopicDiagnostic(cmd_topic_vel.c_str(), updater_pad,
00283                             diagnostic_updater::FrequencyStatusParam(&min_freq_command, &max_freq_command, 0.1, 10));
00284 
00285         // Advertises new service to enable/disable the pad
00286         enable_disable_srv_ = pnh_.advertiseService("enable_disable",  &RbcarPad::EnableDisable, this);
00287         //
00288         bEnable = true; // Communication flag enabled by default
00289         
00290     // Info message
00291     // ROS_INFO("A segfault after this line is usually caused either by bad definition of the pad yaml file or by incrorrect setting of the jsX device in the launch file");
00292 }
00293 
00294 /*
00295  *      \brief Updates the diagnostic component. Diagnostics
00296  *                 Publishes the state
00297  *
00298  */
00299 void RbcarPad::Update(){
00300         PublishState();
00301 }
00302 
00304 void RbcarPad::PublishState(){
00305         /*RbcarPad::rescuer_pad_state pad_state;
00306         
00307         pad_state.state = StateToString(iState);
00308         pad_state.arm_mode = ModeToString(iArmMode);
00309         pad_state.platform_mode = ModeToString(iPlatformMode);
00310         pad_state.speed_level = current_speed_lvl;
00311         pad_state.deadman_active = (bool) vButtons[button_dead_man_].IsPressed();
00312         
00313         state_pub_.publish(pad_state);*/        
00314 }
00315 
00316 /*
00317  *      \brief Enables/Disables the pad
00318  */
00319 bool RbcarPad::EnableDisable(robotnik_msgs::enable_disable::Request &req, robotnik_msgs::enable_disable::Response &res )
00320 {
00321         bEnable = req.value;
00322 
00323         ROS_INFO("RbcarPad::EnablaDisable: Setting to %d", req.value);
00324         res.ret = true;
00325         return true;
00326 }
00327 
00328 void RbcarPad::joyCallback(const sensor_msgs::Joy::ConstPtr& joy)
00329 {
00330         
00331         // First joystick being saved
00332         for(int i = 0; i < joy->axes.size(); i++){
00333                 this->fAxes[i] = joy->axes[i];
00334         }
00335         for(int i = 0; i < joy->buttons.size(); i++){
00336                 this->vButtons[i].Press(joy->buttons[i]);
00337         }
00338         
00339         //ROS_INFO("RbcarPad::joyCallback: num_of_axes = %d, buttons = %d", (int)(joy->axes.size()), (int)(joy->buttons.size()));
00340 }
00341 
00343 void RbcarPad::ControlLoop(){
00344         
00345         double desired_linear_speed = 0.0, desired_angular_position = 0.0;
00346         ackermann_msgs::AckermannDriveStamped ref_msg;
00347         
00348         ros::Rate r(desired_freq_);   
00349 
00350     while(ros::ok()) {
00351                 
00352                 Update();
00353                         
00354                 if(bEnable){
00355                                                 
00356                         if(vButtons[button_dead_man_].IsPressed()){
00357                                 ref_msg.header.stamp = ros::Time::now();
00358                                 ref_msg.drive.jerk = 0.0; 
00359                                 ref_msg.drive.acceleration = 0.0; 
00360                                 ref_msg.drive.steering_angle_velocity = 0.0;
00361                         
00362                                 desired_linear_speed = max_linear_speed_ * current_speed_lvl * fAxes[axis_linear_speed_];
00363                                 desired_angular_position = max_angular_position_ * fAxes[axis_angular_position_];
00364                                 
00365                                 // ROS_INFO("axis_angular_position_ %d   desired_angular_position=%5.2f", axis_angular_position_, desired_angular_position);
00366                                 
00367                                 ref_msg.drive.steering_angle = desired_angular_position;
00368                                 ref_msg.drive.speed = desired_linear_speed;
00369                                 
00370                                 // Publish into command_vel topic
00371                                 vel_pub_.publish(ref_msg);
00372                         
00373                                 if(vButtons[button_speed_up_].IsReleased()){
00374                                         current_speed_lvl += 0.1;
00375                                         if(current_speed_lvl > 1.0)
00376                                                 current_speed_lvl = 1.0;
00377                                 }
00378                                 if(vButtons[button_speed_down_].IsReleased()){
00379                                         current_speed_lvl -= 0.1;
00380                                         if(current_speed_lvl < 0.0)
00381                                                 current_speed_lvl = 0.0;
00382                                 }                               
00383                                                         
00384                         }else if(vButtons[button_dead_man_].IsReleased()){
00385                                 ref_msg.header.stamp = ros::Time::now();
00386                                 ref_msg.drive.jerk = 0.0; 
00387                                 ref_msg.drive.acceleration = 0.0; 
00388                                 ref_msg.drive.steering_angle_velocity = 0.0;
00389                                 
00390                                 ref_msg.drive.steering_angle = 0.0;
00391                                 ref_msg.drive.speed = 0.0;
00392                                 //ROS_INFO("RbcarPad::ControlLoop: Deadman released!");
00393                                 vel_pub_.publish(ref_msg);// Publish into command_vel topic
00394                         }
00395                 }
00396                 
00397                 ros::spinOnce();
00398                 r.sleep();
00399         }       
00400 }
00401 
00403 int main(int argc, char** argv)
00404 {
00405         ros::init(argc, argv, "rbcar_pad");
00406         RbcarPad joy;
00407         
00408         joy.ControlLoop();
00409         
00410 }
00411 
00412 


rbcar_pad
Author(s): Román Navarro
autogenerated on Thu Jun 6 2019 21:37:47