00001 #include <stdio.h>
00002 #include <math.h>
00003 #include <Aria.h>
00004
00005 #include "ros/ros.h"
00006 #include "geometry_msgs/Twist.h"
00007 #include "geometry_msgs/Pose.h"
00008 #include "geometry_msgs/PoseStamped.h"
00009 #include <sensor_msgs/PointCloud.h>
00010 #include "nav_msgs/Odometry.h"
00011 #include "ROSARIA/BumperState.h"
00012 #include "tf/tf.h"
00013 #include "tf/transform_listener.h"
00014 #include <tf/transform_broadcaster.h>
00015 #include "tf/transform_datatypes.h"
00016
00017 #include <sstream>
00018
00019 class ActionPause : public ArAction
00020 {
00021 public:
00022
00023 ActionPause(double time);
00024
00025 virtual ~ActionPause(void) {};
00026
00027 virtual ArActionDesired *fire(ArActionDesired currentDesired);
00028 protected:
00029 double pauseTime;
00030 ArActionDesired myDesired;
00031 };
00032
00033 ActionPause::ActionPause(double time) :
00034 ArAction("Pause")
00035 {
00036 pauseTime = time;
00037 myDesired.reset();
00038 }
00039
00040 ArActionDesired *ActionPause::fire(ArActionDesired currentDesired)
00041 {
00042 ros::Duration(pauseTime).sleep();
00043 return &myDesired;
00044 }
00045
00046
00047 class RosAriaNode
00048 {
00049 public:
00050 RosAriaNode(ros::NodeHandle n);
00051 virtual ~RosAriaNode();
00052
00053 public:
00054 int Setup();
00055 void cmdvel_cb( const geometry_msgs::TwistConstPtr &);
00056 void spin();
00057 void publish();
00058 void sonarConnectCb();
00059
00060 protected:
00061 ros::NodeHandle n;
00062 ros::Publisher pose_pub;
00063 ros::Publisher bumpers_pub;
00064 ros::Publisher sonar_pub;
00065 ros::Subscriber cmdvel_sub;
00066
00067 ros::Time veltime;
00068
00069 std::string serial_port;
00070
00071 ArSimpleConnector *conn;
00072 ArRobot *robot;
00073 ActionPause *pause;
00074 nav_msgs::Odometry position;
00075 ROSARIA::BumperState bumpers;
00076 ArPose pos;
00077 ArFunctorC<RosAriaNode> myPublishCB;
00078
00079
00080 tf::TransformBroadcaster odom_broadcaster;
00081 geometry_msgs::TransformStamped odom_trans;
00082
00083 std::string tf_prefix;
00084 std::string frame_id_odom;
00085 std::string frame_id_base_link;
00086 std::string frame_id_bumper;
00087 std::string frame_id_sonar;
00088
00089
00090 bool use_sonar;
00091 };
00092
00093 void RosAriaNode::sonarConnectCb()
00094 {
00095 if (sonar_pub.getNumSubscribers() == 0)
00096 {
00097 robot->disableSonar();
00098 use_sonar = false;
00099 }
00100 else
00101 {
00102 robot->enableSonar();
00103 use_sonar = true;
00104 }
00105 }
00106
00107 RosAriaNode::RosAriaNode(ros::NodeHandle nh) :
00108 myPublishCB(this, &RosAriaNode::publish), use_sonar(false)
00109 {
00110
00111 n = nh;
00112
00113
00114 n.param( "port", serial_port, std::string("/dev/ttyUSB0") );
00115 ROS_INFO( "using port: [%s]", serial_port.c_str() );
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 tf_prefix = tf::getPrefixParam(n);
00128 frame_id_odom = tf::resolve(tf_prefix, "odom");
00129 frame_id_base_link = tf::resolve(tf_prefix, "base_link");
00130 frame_id_bumper = tf::resolve(tf_prefix, "bumpers_frame");
00131 frame_id_sonar = tf::resolve(tf_prefix, "sonar_frame");
00132
00133
00134 pose_pub = n.advertise<nav_msgs::Odometry>("pose",1000);
00135 bumpers_pub = n.advertise<ROSARIA::BumperState>("bumper_state",1000);
00136 sonar_pub = n.advertise<sensor_msgs::PointCloud>("sonar", 50, boost::bind(&RosAriaNode::sonarConnectCb, this),
00137 boost::bind(&RosAriaNode::sonarConnectCb, this));
00138
00139
00140 cmdvel_sub = n.subscribe( "cmd_vel", 1, (boost::function < void(const geometry_msgs::TwistConstPtr&)>) boost::bind( &RosAriaNode::cmdvel_cb, this, _1 ));
00141
00142 veltime = ros::Time::now();
00143 }
00144
00145 RosAriaNode::~RosAriaNode()
00146 {
00147
00148 robot->disableMotors();
00149 robot->disableSonar();
00150
00151 robot->stopRunning();
00152 robot->waitForRunExit();
00153 Aria::shutdown();
00154 }
00155
00156 int RosAriaNode::Setup()
00157 {
00158 ArArgumentBuilder *args;
00159 args = new ArArgumentBuilder();
00160
00161 size_t colon_pos = serial_port.find(":");
00162 if (colon_pos != std::string::npos)
00163 {
00164 args->add("-rh");
00165 args->add(serial_port.substr(0, colon_pos).c_str());
00166 args->add("-rrtp");
00167 args->add(serial_port.substr(colon_pos+1).c_str());
00168 }
00169 else
00170 {
00171 args->add("-rp");
00172 args->add(serial_port.c_str());
00173 }
00174
00175 args->add("-rlpr");
00176 args->add("-rlps");
00177 args->add("-rlvr");
00178 conn = new ArSimpleConnector(args);
00179
00180 robot = new ArRobot();
00181 pause = new ActionPause(4e-3);
00182
00183 ArLog::init(ArLog::File, ArLog::Verbose, "aria.log", true);
00184
00185
00186 if (!conn->connectRobot(robot)) {
00187 ArLog::log(ArLog::Terse, "rotate: Could not connect to robot! Exiting.");
00188 return 1;
00189 }
00190
00191
00192 robot->enableMotors();
00193
00194
00195 robot->disableSonar();
00196
00197 robot->addSensorInterpTask("PublishingTask", 100, &myPublishCB);
00198
00199 robot->runAsync(true);
00200
00201
00202 bumpers.front_bumpers.resize(robot->getNumFrontBumpers());
00203 bumpers.rear_bumpers.resize(robot->getNumRearBumpers());
00204
00205 return 0;
00206 }
00207
00208 void RosAriaNode::spin()
00209 {
00210 ros::spin();
00211 }
00212
00213 void RosAriaNode::publish()
00214 {
00215
00216 pos = robot->getPose();
00217
00218 tf::poseTFToMsg(tf::Transform(tf::createQuaternionFromYaw(pos.getTh()*M_PI/180), tf::Vector3(pos.getX()/1000, pos.getY()/1000, 0)), position.pose.pose);
00219 position.twist.twist.linear.x = robot->getVel()/1000;
00220 position.twist.twist.angular.z = robot->getRotVel()*M_PI/180;
00221
00222 position.header.frame_id = frame_id_odom;
00223 position.child_frame_id = frame_id_base_link;
00224 position.header.stamp = ros::Time::now();
00225 pose_pub.publish(position);
00226 ROS_INFO("rcv: %f %f %f", position.header.stamp.toSec(), (double) position.twist.twist.linear.x, (double) position.twist.twist.angular.z);
00227
00228
00229 odom_trans.header.stamp = ros::Time::now();
00230 odom_trans.header.frame_id = frame_id_odom;
00231 odom_trans.child_frame_id = frame_id_base_link;
00232
00233 odom_trans.transform.translation.x = pos.getX()/1000;
00234 odom_trans.transform.translation.y = pos.getY()/1000;
00235 odom_trans.transform.translation.z = 0.0;
00236 odom_trans.transform.rotation = tf::createQuaternionMsgFromYaw(pos.getTh()*M_PI/180);
00237
00238 odom_broadcaster.sendTransform(odom_trans);
00239
00240
00241 int stall = robot->getStallValue();
00242 unsigned char front_bumpers = (unsigned char)(stall >> 8);
00243 unsigned char rear_bumpers = (unsigned char)(stall);
00244
00245 bumpers.header.frame_id = frame_id_bumper;
00246 bumpers.header.stamp = ros::Time::now();
00247
00248 std::stringstream bumper_info(std::stringstream::out);
00249
00250 for (unsigned int i=0; i<robot->getNumFrontBumpers(); i++)
00251 {
00252 bumpers.front_bumpers[i] = (front_bumpers & (1 << (i+1))) == 0 ? 0 : 1;
00253 bumper_info << " " << (front_bumpers & (1 << (i+1)));
00254 }
00255 ROS_INFO("Front bumpers:%s", bumper_info.str().c_str());
00256
00257 bumper_info.str("");
00258
00259 unsigned int numRearBumpers = robot->getNumRearBumpers();
00260 for (unsigned int i=0; i<numRearBumpers; i++)
00261 {
00262 bumpers.rear_bumpers[i] = (rear_bumpers & (1 << (numRearBumpers-i))) == 0 ? 0 : 1;
00263 bumper_info << " " << (rear_bumpers & (1 << (numRearBumpers-i)));
00264 }
00265 ROS_INFO("Rear bumpers:%s", bumper_info.str().c_str());
00266
00267 bumpers_pub.publish(bumpers);
00268
00269
00270
00271
00272 if (use_sonar) {
00273 sensor_msgs::PointCloud cloud;
00274 cloud.header.stamp = position.header.stamp;
00275
00276 cloud.header.frame_id = frame_id_sonar;
00277
00278 std::stringstream sonar_debug_info;
00279 sonar_debug_info << "Sonar readings: ";
00280 for (int i = 0; i < robot->getNumSonar(); i++) {
00281 ArSensorReading* reading = NULL;
00282 reading = robot->getSonarReading(i);
00283 if(!reading) {
00284 ROS_WARN("Did not receive a sonar reading.");
00285 continue;
00286 }
00287
00288
00289 sonar_debug_info << reading->getRange() << " ";
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 geometry_msgs::Point32 p;
00305 p.x = reading->getLocalX() / 1000.0;
00306 p.y = reading->getLocalY() / 1000.0;
00307 p.z = 0.0;
00308 cloud.points.push_back(p);
00309 }
00310 ROS_DEBUG_STREAM(sonar_debug_info.str());
00311
00312 sonar_pub.publish(cloud);
00313 }
00314
00315 ros::Duration(1e-3).sleep();
00316 }
00317
00318 void
00319 RosAriaNode::cmdvel_cb( const geometry_msgs::TwistConstPtr &msg)
00320 {
00321 veltime = ros::Time::now();
00322 ROS_INFO( "new speed: [%0.2f,%0.2f](%0.3f)", msg->linear.x*1e3, msg->angular.z, veltime.toSec() );
00323
00324
00325 robot->setVel(msg->linear.x*1e3);
00326 robot->setRotVel(msg->angular.z*180/M_PI);
00327
00328 ROS_INFO("snd: %f %f %f", veltime.toSec(), (double) msg->linear.x, (double) msg->angular.z);
00329 }
00330
00331
00332 int main( int argc, char** argv )
00333 {
00334 ros::init(argc,argv, "RosAria");
00335 ros::NodeHandle n(std::string("~"));
00336 Aria::init();
00337
00338 RosAriaNode *node = new RosAriaNode(n);
00339
00340 if( node->Setup() != 0 )
00341 {
00342 printf( "setup failed... \n" );
00343 return -1;
00344 }
00345
00346 node->spin();
00347
00348 delete node;
00349
00350 printf( "\nQuitting... \n" );
00351 return 0;
00352
00353 }