scout_node.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2010, ISR University of Coimbra.
00006 *  All rights reserved.
00007 *
00008 *  Redistribution and use in source and binary forms, with or without
00009 *  modification, are permitted provided that the following conditions
00010 *  are met:
00011 *
00012 *   * Redistributions of source code must retain the above copyright
00013 *     notice, this list of conditions and the following disclaimer.
00014 *   * Redistributions in binary form must reproduce the above
00015 *     copyright notice, this list of conditions and the following
00016 *     disclaimer in the documentation and/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of the ISR University of Coimbra nor the names of its
00019 *     contributors may be used to endorse or promote products derived
00020 *     from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 *  POSSIBILITY OF SUCH DAMAGE.
00034 *
00035 * Author: Gonçalo Cabrita and Pedro Sousa on 21/10/2010
00036 *********************************************************************/
00037 #define NODE_VERSION 0.02
00038 
00039 #include <ros/ros.h>
00040 #include <tf/transform_broadcaster.h>
00041 #include <nav_msgs/Odometry.h>                  // odom
00042 #include <geometry_msgs/Twist.h>                // cmd_vel
00043 #include <lse_sensor_msgs/Range.h>              // sonar
00044 
00045 #include "Nclient.h"
00046 
00047 #define INCH_TO_METER           0.0254
00048 #define DEGREE_TO_RADIAN        0.0174532925
00049 
00050 #define SCOUT_BAUD_RATE         38400
00051 #define BRIDGE_BAUD_RATE        19200
00052 
00053 #define BATTERY_LOW     0
00054 #define BATTERY_MED     1
00055 #define BATTERY_HIGH    2
00056 
00057 long State[NUM_STATE];
00058 
00059 void cmdVelReceived(const geometry_msgs::Twist::ConstPtr& cmd_vel)
00060 {
00061         scout_vm((int)(cmd_vel->linear.x/(INCH_TO_METER)*10), (int)(cmd_vel->angular.z/(DEGREE_TO_RADIAN)*10));
00062 }
00063 
00064 
00065 int main(int argc, char** argv)
00066 {
00067         ros::init(argc, argv, "scout_node");
00068 
00069         ROS_INFO("Scout for ROS %.2f", NODE_VERSION);
00070 
00071         ros::NodeHandle n("~");
00072         
00073         tf::TransformBroadcaster odom_broadcaster;
00074         
00075         ros::Publisher odom_pub = n.advertise<nav_msgs::Odometry>("/odom", 50);
00076         ros::Publisher sonar_pub = n.advertise<lse_sensor_msgs::Range>("/sonar", 50);
00077         
00078         ros::Subscriber cmd_vel_sub = n.subscribe<geometry_msgs::Twist>("/cmd_vel", 1, cmdVelReceived);
00079 
00080         std::string port;
00081         n.param<std::string>("port", port, "/dev/ttyUSB0");
00082         
00083         std::string model;
00084         n.param<std::string>("model", model, "Scout2");
00085         
00086         int robot_model;
00087         if(model.compare("N200")==0) robot_model = MODEL_N200;
00088         else if(model.compare("N150")==0) robot_model = MODEL_N150;
00089         else if(model.compare("Scout")==0) robot_model = MODEL_SCOUT;
00090         else if(model.compare("Scout2")==0) robot_model = MODEL_SCOUT2;
00091         else
00092         {
00093                 ROS_FATAL("Scout -- Unknown robot model: %s! Options are N200, N150, Scout and Scout2", model.c_str());
00094                 ROS_BREAK();
00095         }
00096 
00097         // Connect to the Scout
00098         connect_robot(1, robot_model, port.c_str(), SCOUT_BAUD_RATE);
00099         // Reset
00100         dp(0,0);
00101         da(0,0);
00102         zr();
00103         // Set command timeout
00104         //conf_tm(1000);
00105 
00106         // Configure sonars
00107         int sn_order[16] = {0, 2, 15, 1, 14, 3, 13, 4, 12, 5, 11, 6, 10, 7, 9, 8};
00108         conf_sn(15, sn_order);
00109         
00110         ros::Time current_time;
00111         
00112         ros::Rate r(10.0);
00113         while(n.ok())
00114         {
00115                 // Update the Scout readings
00116                 gs();
00117                 
00118                 current_time = ros::Time::now();
00119 
00120                 //ROS_INFO("Error: %d", State[STATE_ERROR]);
00121                 
00122         float odom_x = State[STATE_CONF_X]*INCH_TO_METER/10.0;
00123         float odom_y = State[STATE_CONF_Y]*INCH_TO_METER/10.0;
00124         float odom_yaw = State[STATE_CONF_STEER]*DEGREE_TO_RADIAN/10.0;
00125                 
00126                 //since all odometry is 6DOF we'll need a quaternion created from yaw
00127                 geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(odom_yaw);
00128                 
00129                 //first, we'll publish the transform over tf
00130                 geometry_msgs::TransformStamped odom_trans;
00131                 odom_trans.header.stamp = current_time;
00132                 odom_trans.header.frame_id = "/odom";
00133                 odom_trans.child_frame_id = "/base_link";
00134                 
00135                 odom_trans.transform.translation.x = odom_x;
00136                 odom_trans.transform.translation.y = odom_y;
00137                 odom_trans.transform.translation.z = 0.0;
00138                 odom_trans.transform.rotation = odom_quat;
00139                 
00140                 //send the transform
00141                 odom_broadcaster.sendTransform(odom_trans);
00142                 
00143                 //next, we'll publish the odometry message over ROS
00144                 nav_msgs::Odometry odom;
00145                 odom.header.stamp = current_time;
00146                 odom.header.frame_id = "/odom";
00147                 
00148                 //set the position
00149                 odom.pose.pose.position.x = odom_x;
00150                 odom.pose.pose.position.y = odom_y;
00151                 odom.pose.pose.position.z = 0.0;
00152                 odom.pose.pose.orientation = odom_quat;
00153                 
00154                 //set the velocity
00155                 odom.child_frame_id = "/base_link";
00156                 odom.twist.twist.linear.x = State[STATE_VEL_TRANS]*INCH_TO_METER/10;
00157                 odom.twist.twist.linear.y = 0.0;
00158                 odom.twist.twist.angular.z = State[STATE_VEL_STEER]*DEGREE_TO_RADIAN/10;
00159                 
00160                 //publish the message
00161                 odom_pub.publish(odom);
00162                 
00163                 //now on to the sonar array!
00164                 for(int STATE_SONAR_i=STATE_SONAR_0 ; STATE_SONAR_i<=STATE_SONAR_15 ; STATE_SONAR_i++)
00165                 {
00166                         lse_sensor_msgs::Range sonar;
00167                         sonar.header.stamp = current_time;
00168                         char frame_id[32];
00169                         sprintf(frame_id, "/base_sonar_%d", STATE_SONAR_i-STATE_SONAR_0);
00170                         sonar.header.frame_id = frame_id;
00171                         sonar.field_of_view = 0.34906585;       // 20 degress
00172                         sonar.min_range = 0.50;
00173                         sonar.max_range = 5.00;
00174                         sonar.range = (float)(State[STATE_SONAR_i]*INCH_TO_METER);
00175                         sonar_pub.publish(sonar);
00176                 }
00177                 
00178                 char status = State[STATE_MOTOR_STATUS];
00179                 
00180                 bool left_wheel_moving = status & 0x01;
00181                 bool right_wheel_moving = (status>>1) & 0x01;
00182                 
00183                 int battery_state;
00184                 bool b0 = (status>>2) & 0x01;
00185                 bool b1 = (status>>3) & 0x01;
00186                 if(!b0 && !b1) battery_state = BATTERY_LOW;
00187                 else if(b0 && !b1) battery_state = BATTERY_MED;
00188                 else if(!b0 && b1) battery_state = BATTERY_HIGH;
00189                 
00190                 bool is_plugged = (status>>4) & 0x01;
00191                 bool is_charging = (status>>5) & 0x01;
00192                 bool emergency_stop = (status>>6) & 0x01;
00193 
00194                 ros::spinOnce();
00195                 r.sleep();
00196         }
00197         
00198         // Turn sonars off
00199         int sn_off[1] = {255};
00200         conf_sn(15, sn_off);
00201         // Stop the robot
00202         st();
00203         // Disconnect the Scout
00204         disconnect_robot(1);
00205 }
00206 
00207 // EOF


scout_ndirect
Author(s): Gonçalo Cabrita and Pedro Sousa
autogenerated on Mon Jan 6 2014 11:25:23