00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdr_robot/stdr_robot.h>
00023 #include <nodelet/NodeletUnload.h>
00024 #include <pluginlib/class_list_macros.h>
00025
00026 PLUGINLIB_EXPORT_CLASS(stdr_robot::Robot, nodelet::Nodelet)
00027
00028 namespace stdr_robot
00029 {
00034 Robot::Robot(void)
00035 {
00036
00037 }
00038
00043 void Robot::onInit()
00044 {
00045 ros::NodeHandle n = getMTNodeHandle();
00046
00047 _odomPublisher = n.advertise<nav_msgs::Odometry>(getName() + "/odom", 10);
00048
00049 _registerClientPtr.reset(
00050 new RegisterRobotClient(n, "stdr_server/register_robot", true) );
00051
00052 _registerClientPtr->waitForServer();
00053
00054 stdr_msgs::RegisterRobotGoal goal;
00055 goal.name = getName();
00056 _registerClientPtr->sendGoal(goal,
00057 boost::bind(&Robot::initializeRobot, this, _1, _2));
00058
00059 _mapSubscriber = n.subscribe("map", 1, &Robot::mapCallback, this);
00060 _moveRobotService = n.advertiseService(
00061 getName() + "/replace", &Robot::moveRobotCallback, this);
00062
00063
00064 _tfTimer = n.createTimer(
00065 ros::Duration(0.1), &Robot::publishTransforms, this, false, false);
00066 }
00067
00074 void Robot::initializeRobot(
00075 const actionlib::SimpleClientGoalState& state,
00076 const stdr_msgs::RegisterRobotResultConstPtr result)
00077 {
00078
00079 if (state == state.ABORTED) {
00080 NODELET_ERROR("Something really bad happened...");
00081 return;
00082 }
00083
00084 NODELET_INFO("Loaded new robot, %s", getName().c_str());
00085 ros::NodeHandle n = getMTNodeHandle();
00086
00087 _currentPose = result->description.initialPose;
00088
00089 _previousPose = _currentPose;
00090
00091 for ( unsigned int laserIter = 0;
00092 laserIter < result->description.laserSensors.size(); laserIter++ )
00093 {
00094 _sensors.push_back( SensorPtr(
00095 new Laser( _map,
00096 result->description.laserSensors[laserIter], getName(), n ) ) );
00097 }
00098 for ( unsigned int sonarIter = 0;
00099 sonarIter < result->description.sonarSensors.size(); sonarIter++ )
00100 {
00101 _sensors.push_back( SensorPtr(
00102 new Sonar( _map,
00103 result->description.sonarSensors[sonarIter], getName(), n ) ) );
00104 }
00105 for ( unsigned int rfidReaderIter = 0;
00106 rfidReaderIter < result->description.rfidSensors.size();
00107 rfidReaderIter++ )
00108 {
00109 _sensors.push_back( SensorPtr(
00110 new RfidReader( _map,
00111 result->description.rfidSensors[rfidReaderIter], getName(), n ) ) );
00112 }
00113 for ( unsigned int co2SensorIter = 0;
00114 co2SensorIter < result->description.co2Sensors.size();
00115 co2SensorIter++ )
00116 {
00117 _sensors.push_back( SensorPtr(
00118 new CO2Sensor( _map,
00119 result->description.co2Sensors[co2SensorIter], getName(), n ) ) );
00120 }
00121 for ( unsigned int thermalSensorIter = 0;
00122 thermalSensorIter < result->description.thermalSensors.size();
00123 thermalSensorIter++ )
00124 {
00125 _sensors.push_back( SensorPtr(
00126 new ThermalSensor( _map,
00127 result->description.thermalSensors[thermalSensorIter], getName(), n ) ) );
00128 }
00129 for ( unsigned int soundSensorIter = 0;
00130 soundSensorIter < result->description.soundSensors.size();
00131 soundSensorIter++ )
00132 {
00133 _sensors.push_back( SensorPtr(
00134 new SoundSensor( _map,
00135 result->description.soundSensors[soundSensorIter], getName(), n ) ) );
00136 }
00137
00138 if( result->description.footprint.points.size() == 0 ) {
00139 float radius = result->description.footprint.radius;
00140 for(unsigned int i = 0 ; i < 360 ; i++)
00141 {
00142 float x = cos(i * 3.14159265359 / 180.0) * radius;
00143 float y = sin(i * 3.14159265359 / 180.0) * radius;
00144 _footprint.push_back( std::pair<float,float>(x,y));
00145 }
00146 } else {
00147 for( unsigned int i = 0 ;
00148 i < result->description.footprint.points.size() ;
00149 i++ ) {
00150 geometry_msgs::Point p = result->description.footprint.points[i];
00151 _footprint.push_back( std::pair<float,float>(p.x, p.y));
00152 }
00153 }
00154
00155 _motionControllerPtr.reset(
00156 new IdealMotionController(_currentPose, _tfBroadcaster, n, getName()));
00157
00158 _tfTimer.start();
00159 }
00160
00166 void Robot::mapCallback(const nav_msgs::OccupancyGridConstPtr& msg)
00167 {
00168 _map = *msg;
00169 }
00170
00177 bool Robot::moveRobotCallback(stdr_msgs::MoveRobot::Request& req,
00178 stdr_msgs::MoveRobot::Response& res)
00179 {
00180 if( collisionExistsNoPath(req.newPose) ||
00181 checkUnknownOccupancy(req.newPose) )
00182 {
00183 return false;
00184 }
00185
00186 _currentPose = req.newPose;
00187
00188 _previousPose = _currentPose;
00189
00190 _motionControllerPtr->setPose(_previousPose);
00191 return true;
00192 }
00193
00198 bool Robot::collisionExistsNoPath(
00199 const geometry_msgs::Pose2D& newPose)
00200 {
00201 if(_map.info.width == 0 || _map.info.height == 0)
00202 {
00203 return false;
00204 }
00205
00206 int xMap = newPose.x / _map.info.resolution;
00207 int yMap = newPose.y / _map.info.resolution;
00208
00209 for(unsigned int i = 0 ; i < _footprint.size() ; i++)
00210 {
00211 double x = _footprint[i].first * cos(newPose.theta) -
00212 _footprint[i].second * sin(newPose.theta);
00213 double y = _footprint[i].first * sin(newPose.theta) +
00214 _footprint[i].second * cos(newPose.theta);
00215
00216 int xx = xMap + (int)(x / _map.info.resolution);
00217 int yy = yMap + (int)(y / _map.info.resolution);
00218
00219 if(_map.data[ yy * _map.info.width + xx ] > 70)
00220 {
00221 return true;
00222 }
00223 }
00224 return false;
00225 }
00226
00232 bool Robot::checkUnknownOccupancy(
00233 const geometry_msgs::Pose2D& newPose)
00234 {
00235 if(_map.info.width == 0 || _map.info.height == 0)
00236 {
00237 return false;
00238 }
00239
00240 int xMap = newPose.x / _map.info.resolution;
00241 int yMap = newPose.y / _map.info.resolution;
00242
00243 if( _map.data[ yMap * _map.info.width + xMap ] == -1 )
00244 {
00245 return true;
00246 }
00247
00248 return false;
00249 }
00250
00259 std::vector<std::pair<int,int> > Robot::getPointsBetween(
00260 int x1, int y1, int x2, int y2)
00261 {
00262 std::vector<std::pair<int,int> > points;
00263
00264 float angle = atan2(y2 - y1, x2 - x1);
00265 float dist = sqrt( pow(x2 - x1, 2) + pow(y2 - y1, 2));
00266
00267 int d = 0;
00268
00269 while(d < dist)
00270 {
00271 int x = x1 + d * cos(angle);
00272 int y = y1 + d * sin(angle);
00273 points.push_back(std::pair<int,int>(x,y));
00274 d++;
00275 }
00276
00277 return points;
00278 }
00279
00284 bool Robot::collisionExists(
00285 const geometry_msgs::Pose2D& newPose,
00286 const geometry_msgs::Pose2D& previousPose)
00287 {
00288 if(_map.info.width == 0 || _map.info.height == 0)
00289 return false;
00290
00291 int xMapPrev, xMap, yMapPrev, yMap;
00292 bool movingForward, movingUpward;
00293
00294
00295 movingForward = _previousMovementXAxis? false: true;
00296 if ( fabs(previousPose.x - newPose.x) > 0.001)
00297 {
00298 movingForward = (previousPose.x > newPose.x)? false: true;
00299 _previousMovementXAxis = movingForward;
00300 }
00301 movingUpward = _previousMovementYAxis? false: true;
00302 if ( fabs(previousPose.y - newPose.y) > 0.001)
00303 {
00304 movingUpward = (previousPose.y > newPose.y)? false: true;
00305 _previousMovementYAxis = movingUpward;
00306 }
00307
00308 xMapPrev = movingForward? (int)( previousPose.x / _map.info.resolution ):
00309 ceil( previousPose.x / _map.info.resolution );
00310 xMap = movingForward? ceil( newPose.x / _map.info.resolution ):
00311 (int)( newPose.x / _map.info.resolution );
00312
00313 yMapPrev = movingUpward? (int)( previousPose.y / _map.info.resolution ):
00314 ceil( previousPose.y / _map.info.resolution );
00315 yMap = movingUpward? ceil( newPose.y / _map.info.resolution ):
00316 (int)( newPose.y / _map.info.resolution );
00317
00318 float angle = atan2(yMap - yMapPrev, xMap - xMapPrev);
00319 int x = xMapPrev;
00320 int y = yMapPrev;
00321 int d = 2;
00322
00323 while(pow(xMap - x,2) + pow(yMap - y,2) > 1)
00324 {
00325 x = xMapPrev +
00326 ( movingForward? ceil( cos(angle) * d ): (int)( cos(angle) * d ) );
00327 y = yMapPrev +
00328 ( movingUpward? ceil( sin(angle) * d ): (int)( sin(angle) * d ) );
00329
00330 for(unsigned int i = 0 ; i < _footprint.size() ; i++)
00331 {
00332 int index_1 = i;
00333 int index_2 = (i + 1) % _footprint.size();
00334
00335
00336 double footprint_x_1 = _footprint[index_1].first * cos(newPose.theta) -
00337 _footprint[index_1].second * sin(newPose.theta);
00338 double footprint_y_1 = _footprint[index_1].first * sin(newPose.theta) +
00339 _footprint[index_1].second * cos(newPose.theta);
00340
00341 int xx1 = x + footprint_x_1 / _map.info.resolution;
00342 int yy1 = y + footprint_y_1 / _map.info.resolution;
00343
00344 double footprint_x_2 = _footprint[index_2].first * cos(newPose.theta) -
00345 _footprint[index_2].second * sin(newPose.theta);
00346 double footprint_y_2 = _footprint[index_2].first * sin(newPose.theta) +
00347 _footprint[index_2].second * cos(newPose.theta);
00348
00349 int xx2 = x + footprint_x_2 / _map.info.resolution;
00350 int yy2 = y + footprint_y_2 / _map.info.resolution;
00351
00352
00353 std::vector<std::pair<int,int> > pts =
00354 getPointsBetween(xx1,yy1,xx2,yy2);
00355
00356 for(unsigned int j = 0 ; j < pts.size() ; j++)
00357 {
00358 static int OF = 1;
00359 if(
00360 _map.data[ (pts[j].second - OF) *
00361 _map.info.width + pts[j].first - OF ] > 70 ||
00362 _map.data[ (pts[j].second - OF) *
00363 _map.info.width + pts[j].first ] > 70 ||
00364 _map.data[ (pts[j].second - OF) *
00365 _map.info.width + pts[j].first + OF ] > 70 ||
00366 _map.data[ (pts[j].second) *
00367 _map.info.width + pts[j].first - OF ] > 70 ||
00368 _map.data[ (pts[j].second) *
00369 _map.info.width + pts[j].first + OF ] > 70 ||
00370 _map.data[ (pts[j].second + OF) *
00371 _map.info.width + pts[j].first - OF ] > 70 ||
00372 _map.data[ (pts[j].second + OF) *
00373 _map.info.width + pts[j].first ] > 70 ||
00374 _map.data[ (pts[j].second + OF) *
00375 _map.info.width + pts[j].first + OF ] > 70
00376 )
00377 {
00378 return true;
00379 }
00380 }
00381 }
00382 if ( (movingForward && xMap < x) || (movingUpward && yMap < y) ||
00383 (!movingForward && xMap > x) || (!movingUpward && yMap > y) )
00384 {
00385 break;
00386 }
00387 d++;
00388 }
00389 return false;
00390 }
00391
00396 void Robot::publishTransforms(const ros::TimerEvent&)
00397 {
00398 geometry_msgs::Pose2D pose = _motionControllerPtr->getPose();
00399 if( ! collisionExists(pose, _previousPose) )
00400 {
00401 _previousPose = pose;
00402 }
00403 else
00404 {
00405 _motionControllerPtr->setPose(_previousPose);
00406 }
00408 tf::Vector3 translation(_previousPose.x, _previousPose.y, 0);
00409 tf::Quaternion rotation;
00410 rotation.setRPY(0, 0, _previousPose.theta);
00411
00412 tf::Transform mapToRobot(rotation, translation);
00413
00414 _tfBroadcaster.sendTransform(tf::StampedTransform(
00415 mapToRobot, ros::Time::now(), "map_static", getName()));
00416
00418 nav_msgs::Odometry odom;
00419 odom.header.stamp = ros::Time::now();
00420 odom.header.frame_id = "map_static";
00421 odom.child_frame_id = getName();
00422 odom.pose.pose.position.x = _previousPose.x;
00423 odom.pose.pose.position.y = _previousPose.y;
00424 odom.pose.pose.orientation = tf::createQuaternionMsgFromYaw(
00425 _previousPose.theta);
00426 odom.twist.twist = _motionControllerPtr->getVelocity();
00427
00428 _odomPublisher.publish(odom);
00429
00431 for (int i = 0; i < _sensors.size(); i++) {
00432 geometry_msgs::Pose2D sensorPose = _sensors[i]->getSensorPose();
00433
00434 tf::Vector3 trans(sensorPose.x, sensorPose.y, 0);
00435 tf::Quaternion rot;
00436 rot.setRPY(0, 0, sensorPose.theta);
00437
00438 tf::Transform robotToSensor(rot, trans);
00439
00440 _tfBroadcaster.sendTransform(
00441 tf::StampedTransform(
00442 robotToSensor,
00443 ros::Time::now(),
00444 getName(),
00445 _sensors[i]->getFrameId()));
00446 }
00447 }
00448
00453 Robot::~Robot()
00454 {
00456 }
00457
00458 }