atrvjr_node.cc
Go to the documentation of this file.
00001 #include <string>
00002 #include <ros/ros.h>
00003 #include <tf/transform_broadcaster.h>
00004 #include <rflex/atrvjr_driver.h>
00005 #include <std_msgs/Bool.h>
00006 #include <std_msgs/Float32.h>
00007 #include <sensor_msgs/JointState.h>
00008 #include <geometry_msgs/Twist.h>
00009 #include <sensor_msgs/PointCloud.h>
00010 #include <nav_msgs/Odometry.h>
00011 #include <angles/angles.h>
00012 
00033 class ATRVJRNode {
00034     private:
00035         ATRVJR driver;
00036 
00037         ros::Subscriber subs[4];                        
00038         ros::Publisher base_sonar_pub;          
00039         ros::Publisher body_sonar_pub;          
00040         ros::Publisher voltage_pub;                     
00041         ros::Publisher brake_power_pub;         
00042         ros::Publisher sonar_power_pub;         
00043         ros::Publisher odom_pub;                        
00044         ros::Publisher plugged_pub;                     
00045         ros::Publisher joint_pub; 
00046         ros::Publisher bump_pub; 
00047         tf::TransformBroadcaster broadcaster; 
00048 
00049         bool isSonarOn, isBrakeOn;
00050         float acceleration;
00051         float last_distance, last_bearing;
00052         float x_odo, y_odo, a_odo;
00053         float cmdTranslation, cmdRotation;
00054         bool brake_dirty, sonar_dirty;
00055         bool initialized;
00056         float first_bearing;
00057         int updateTimer;
00058         int prev_bumps;
00059         bool sonar_just_on;
00060 
00061         void publishOdometry();
00062         void publishSonar();
00063         void publishBumps();
00064 
00065     public:
00066         ros::NodeHandle n;
00067         ATRVJRNode();
00068         ~ATRVJRNode();
00069         int initialize(const char* port);
00070         void spinOnce();
00071 
00072         // Message Listeners
00073         void NewCommand      (const geometry_msgs::Twist::ConstPtr& msg);
00074         void SetAcceleration (const std_msgs::Float32   ::ConstPtr& msg);
00075         void ToggleSonarPower(const std_msgs::Bool      ::ConstPtr& msg);
00076         void ToggleBrakePower(const std_msgs::Bool      ::ConstPtr& msg);
00077 };
00078 
00079 ATRVJRNode::ATRVJRNode() : n ("~") {
00080     isSonarOn = isBrakeOn = false;
00081     brake_dirty = sonar_dirty = false;
00082     sonar_just_on = false;
00083     cmdTranslation = cmdRotation = 0.0;
00084     updateTimer = 99;
00085     initialized = false;
00086     prev_bumps = 0;
00087     subs[0] = n.subscribe<geometry_msgs::Twist>("cmd_vel", 1,   &ATRVJRNode::NewCommand, this);
00088     subs[1] = n.subscribe<std_msgs::Float32>("cmd_accel", 1,     &ATRVJRNode::SetAcceleration, this);
00089     subs[2] = n.subscribe<std_msgs::Bool>("cmd_sonar_power", 1, &ATRVJRNode::ToggleSonarPower, this);
00090     subs[3] = n.subscribe<std_msgs::Bool>("cmd_brake_power", 1, &ATRVJRNode::ToggleBrakePower, this);
00091     acceleration = 0.7;
00092 
00093     base_sonar_pub = n.advertise<sensor_msgs::PointCloud>("sonar_cloud_base", 50);
00094     body_sonar_pub = n.advertise<sensor_msgs::PointCloud>("sonar_cloud_body", 50);
00095     sonar_power_pub = n.advertise<std_msgs::Bool>("sonar_power", 1);
00096     brake_power_pub = n.advertise<std_msgs::Bool>("brake_power", 1);
00097     voltage_pub = n.advertise<std_msgs::Float32>("voltage", 1);
00098     odom_pub = n.advertise<nav_msgs::Odometry>("odom", 50);
00099     plugged_pub = n.advertise<std_msgs::Bool>("plugged_in", 1);
00100     joint_pub = n.advertise<sensor_msgs::JointState>("state", 1);
00101     bump_pub = n.advertise<sensor_msgs::PointCloud>("bump", 5);
00102 }
00103 
00104 int ATRVJRNode::initialize(const char* port) {
00105     int ret = driver.initialize(port);
00106     if (ret < 0)
00107         return ret;
00108 
00109     driver.setOdometryPeriod (100000);
00110     driver.setDigitalIoPeriod(100000);
00111     driver.motionSetDefaults();
00112     return 0;
00113 }
00114 
00115 ATRVJRNode::~ATRVJRNode() {
00116     driver.motionSetDefaults();
00117     driver.setOdometryPeriod(0);
00118     driver.setDigitalIoPeriod(0);
00119     driver.setSonarPower(false);
00120     driver.setIrPower(false);
00121 }
00122 
00124 void ATRVJRNode::NewCommand(const geometry_msgs::Twist::ConstPtr& msg) {
00125     cmdTranslation = msg->linear.x;
00126     cmdRotation = msg->angular.z;
00127 }
00128 
00130 void ATRVJRNode::SetAcceleration (const std_msgs::Float32::ConstPtr& msg) {
00131     acceleration = msg->data;
00132 }
00133 
00135 void ATRVJRNode::ToggleSonarPower(const std_msgs::Bool::ConstPtr& msg) {
00136     isSonarOn=msg->data;
00137     sonar_dirty = true;
00138 }
00139 
00141 void ATRVJRNode::ToggleBrakePower(const std_msgs::Bool::ConstPtr& msg) {
00142     isBrakeOn = msg->data;
00143     brake_dirty = true;
00144 }
00145 
00146 void ATRVJRNode::spinOnce() {
00147     // Sending the status command too often overwhelms the driver
00148     if (updateTimer>=100) {
00149         driver.sendSystemStatusCommand();
00150         updateTimer = 0;
00151     }
00152     updateTimer++;
00153 
00154     if (cmdTranslation != 0 || cmdRotation != 0)
00155         driver.setMovement(cmdTranslation, cmdRotation, acceleration);
00156 
00157     if (sonar_dirty) {
00158         driver.setSonarPower(isSonarOn);
00159         sonar_dirty = false;
00160         driver.sendSystemStatusCommand();
00161     }
00162     if (brake_dirty) {
00163         driver.setBrakePower(isBrakeOn);
00164         brake_dirty = false;
00165         updateTimer = 99;
00166     }
00167 
00168     std_msgs::Bool bmsg;
00169     bmsg.data = isSonarOn;
00170     sonar_power_pub.publish(bmsg);
00171     bmsg.data = driver.getBrakePower();
00172     brake_power_pub.publish(bmsg);
00173     bmsg.data = driver.isPluggedIn();
00174     plugged_pub.publish(bmsg);
00175     std_msgs::Float32 vmsg;
00176     vmsg.data = driver.getVoltage();
00177     voltage_pub.publish(vmsg);
00178 
00179     publishOdometry();
00180     publishSonar();
00181     publishBumps();
00182 }
00183 
00186 void ATRVJRNode::publishOdometry() {
00187     if (!driver.isOdomReady()) {
00188         return;
00189     }
00190 
00191     float distance = driver.getDistance();
00192     float true_bearing = angles::normalize_angle(driver.getBearing());
00193 
00194     if (!initialized) {
00195         initialized = true;
00196         first_bearing = true_bearing;
00197         x_odo = 0;
00198         y_odo = 0;
00199         a_odo = 0*true_bearing;
00200     } else {
00201         float bearing = true_bearing - first_bearing;
00202         float d_dist = distance-last_distance;
00203         float d_bearing = bearing - last_bearing;
00204 
00205         if (d_dist > 50 || d_dist < -50)
00206             return;
00207 
00208         a_odo += d_bearing;
00209         a_odo = angles::normalize_angle(a_odo);
00210 
00211         //integrate latest motion into odometry
00212         x_odo += d_dist * cos(a_odo);
00213         y_odo += d_dist * sin(a_odo);
00214     }
00215     last_distance = distance;
00216     last_bearing = true_bearing - first_bearing;
00217 
00218     //since all odometry is 6DOF we'll need a quaternion created from yaw
00219     geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(last_bearing);
00220 
00221     //first, we'll publish the transform over tf
00222     geometry_msgs::TransformStamped odom_trans;
00223     odom_trans.header.stamp = ros::Time::now();
00224     odom_trans.header.frame_id = "odom";
00225     odom_trans.child_frame_id = "base_link";
00226 
00227     odom_trans.transform.translation.x = x_odo;
00228     odom_trans.transform.translation.y = y_odo;
00229     odom_trans.transform.rotation = odom_quat;
00230 
00231     //send the transform
00232     broadcaster.sendTransform(odom_trans);
00233 
00234     //next, we'll publish the odometry message over ROS
00235     nav_msgs::Odometry odom;
00236     odom.header.stamp = ros::Time::now();
00237     odom.header.frame_id = "odom";
00238 
00239     //set the position
00240     odom.pose.pose.position.x = x_odo;
00241     odom.pose.pose.position.y = y_odo;
00242     odom.pose.pose.orientation = odom_quat;
00243 
00244     //set the velocity
00245     odom.child_frame_id = "base_link";
00246     float tvel = driver.getTranslationalVelocity();
00247     odom.twist.twist.linear.x = tvel*cos(a_odo);
00248     odom.twist.twist.linear.y = tvel*sin(a_odo);
00249     odom.twist.twist.angular.z = driver.getRotationalVelocity();
00250 
00251     //publish the message
00252     odom_pub.publish(odom);
00253 
00254     // finally, publish the joint state
00255     sensor_msgs::JointState joint_state;
00256     joint_state.header.stamp = ros::Time::now();
00257     joint_state.name.resize(1);
00258     joint_state.position.resize(1);
00259     joint_state.name[0] = "lewis_twist";
00260     joint_state.position[0] = true_bearing;
00261 
00262     joint_pub.publish(joint_state);
00263 
00264 }
00265 
00266 void ATRVJRNode::publishSonar() {
00267     sensor_msgs::PointCloud cloud;
00268     cloud.header.stamp = ros::Time::now();
00269     cloud.header.frame_id = "base_link";
00270 
00271     if (isSonarOn) {
00272         driver.getBaseSonarPoints(&cloud);
00273         base_sonar_pub.publish(cloud);
00274 
00275         driver.getBodySonarPoints(&cloud);
00276         cloud.header.frame_id = "body";
00277         body_sonar_pub.publish(cloud);
00278 
00279     } else if (sonar_just_on) {
00280         base_sonar_pub.publish(cloud);
00281         cloud.header.frame_id = "body";
00282         body_sonar_pub.publish(cloud);
00283     }
00284 }
00285 
00286 void ATRVJRNode::publishBumps() {
00287     sensor_msgs::PointCloud cloud1, cloud2;
00288     cloud1.header.stamp = ros::Time::now();
00289     cloud2.header.stamp = ros::Time::now();
00290     cloud1.header.frame_id = "base_link";
00291     cloud2.header.frame_id = "body";
00292     int bumps = driver.getBaseBumps(&cloud1) +
00293                 driver.getBodyBumps(&cloud2);
00294 
00295     if (bumps>0 || prev_bumps>0) {
00296         bump_pub.publish(cloud1);
00297         bump_pub.publish(cloud2);
00298     }
00299     prev_bumps = bumps;
00300 }
00301 
00302 int main(int argc, char** argv) {
00303     ros::init(argc, argv, "atrvjr");
00304     ATRVJRNode node;
00305     std::string port;
00306     node.n.param<std::string>("port", port, "/dev/ttyUSB0");
00307     ROS_INFO("Attempting to connect to %s", port.c_str());
00308     if (node.initialize(port.c_str())<0) {
00309         ROS_ERROR("Could not initialize RFLEX driver!\n");
00310         return 0;
00311     }
00312     ROS_INFO("Connected!");
00313 
00314 
00315     int hz;
00316     node.n.param("rate", hz, 10);
00317     ros::Rate loop_rate(hz);
00318 
00319     while (ros::ok()) {
00320         node.spinOnce();
00321         // Process a round of subscription messages
00322         ros::spinOnce();
00323         // This will adjust as needed per iteration
00324         loop_rate.sleep();
00325     }
00326 
00327     return 0;
00328 }


rflex
Author(s): David V. Lu!!, Mikhail Medvedev
autogenerated on Fri Aug 28 2015 12:58:58