00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <unistd.h>
00011
00012 #include <dynamic_reconfigure/server.h>
00013
00014 #include <art/frames.h>
00015
00016 #include <art_msgs/IOadrCommand.h>
00017 #include <art_msgs/IOadrState.h>
00018 #include <art/steering.h>
00019 #include <art_map/ZoneOps.h>
00020
00021 #include <art_msgs/CarCommand.h>
00022 #include <art_nav/NavEstopState.h>
00023 #include <art_nav/NavRoadState.h>
00024
00025
00026 #include "navigator_internal.h"
00027 #include "course.h"
00028
00029
00041 #define CLASS "NavQueueMgr"
00042
00043
00044 class NavQueueMgr
00045 {
00046 public:
00047
00048
00049 NavQueueMgr();
00050 ~NavQueueMgr()
00051 {
00052 delete nav_;
00053 };
00054
00055 bool setup(ros::NodeHandle node);
00056 bool shutdown();
00057 void spin(void);
00058
00059 private:
00060
00061 void processNavCmd(const art_msgs::NavigatorCommand::ConstPtr &cmdIn);
00062 void processOdom(const nav_msgs::Odometry::ConstPtr &odomIn);
00063 void processRoadMap(const art_msgs::ArtLanes::ConstPtr &cmdIn);
00064 void processRelays(const art_msgs::IOadrState::ConstPtr &sigIn);
00065 void PublishState(void);
00066 void reconfig(Config &newconfig, uint32_t level);
00067 void SetRelays(void);
00068 void SetSpeed(pilot_command_t pcmd);
00069
00070
00071 ros::Publisher car_cmd_;
00072 ros::Subscriber nav_cmd_;
00073 ros::Publisher nav_state_;
00074 ros::Subscriber odom_state_;
00075 ros::Subscriber roadmap_;
00076 ros::Publisher signals_cmd_;
00077 ros::Subscriber signals_state_;
00078
00079
00080
00081
00082 bool signal_on_left_;
00083 bool signal_on_right_;
00084 bool flasher_on_;
00085 bool alarm_on_;
00086
00087
00088 nav_msgs::Odometry odom_msg_;
00089
00090
00091 ros::Time cmd_time_;
00092 ros::Time map_time_;
00093
00094
00095 Navigator *nav_;
00096
00097
00098 dynamic_reconfigure::Server<Config> ccb_;
00099 };
00100
00102 NavQueueMgr::NavQueueMgr()
00103 {
00104 signal_on_left_ = signal_on_right_ = false;
00105 flasher_on_ = alarm_on_ = false;
00106
00107
00108 nav_ = new Navigator(&odom_msg_);
00109 ccb_.setCallback(boost::bind(&NavQueueMgr::reconfig, this, _1, _2));
00110 }
00111
00113 void NavQueueMgr::processNavCmd(const
00114 art_msgs::NavigatorCommand::ConstPtr &cmdIn)
00115 {
00116 ROS_DEBUG_STREAM("Navigator order:"
00117 << NavBehavior(cmdIn->order.behavior).Name());
00118 cmd_time_ = cmdIn->header.stamp;
00119 nav_->order = cmdIn->order;
00120 }
00121
00123 void NavQueueMgr::processOdom(const nav_msgs::Odometry::ConstPtr &odomIn)
00124 {
00125 ROS_DEBUG("Odometry pose: (%.3f, %.3f, %.3f), (%.3f, %.3f, %.3f)",
00126 odomIn->pose.pose.position.x,
00127 odomIn->pose.pose.position.y,
00128 odomIn->pose.pose.position.z,
00129 odomIn->twist.twist.linear.x,
00130 odomIn->twist.twist.linear.y,
00131 odomIn->twist.twist.linear.z);
00132
00133 float vel = odomIn->twist.twist.linear.x;
00134 ROS_DEBUG("current velocity = %.3f m/sec, (%02.f mph)", vel, mps2mph(vel));
00135 odom_msg_ = *odomIn;
00136 }
00137
00139 void NavQueueMgr::processRoadMap(const art_msgs::ArtLanes::ConstPtr &mapIn)
00140 {
00141 ROS_DEBUG_STREAM(mapIn->polygons.size() << " lanes polygons received");
00142 map_time_ = mapIn->header.stamp;
00143 nav_->course->lanes_message(*mapIn);
00144 }
00145
00147 void NavQueueMgr::processRelays(const art_msgs::IOadrState::ConstPtr &sigIn)
00148 {
00149 using art_msgs::IOadrState;
00150
00151 bool left_on = (sigIn->relays && IOadrState::TURN_LEFT);
00152 if (left_on != signal_on_left_)
00153 {
00154 ROS_INFO("left turn signal now %s", (left_on? "on": "off"));
00155 signal_on_left_ = left_on;
00156 }
00157
00158 bool right_on = (sigIn->relays && IOadrState::TURN_RIGHT);
00159 if (right_on != signal_on_right_)
00160 {
00161 ROS_INFO("right turn signal now %s", (right_on? "on": "off"));
00162 signal_on_right_ = right_on;
00163 }
00164
00165 bool flasher_on = (sigIn->relays && IOadrState::FLASHER);
00166 if (flasher_on != flasher_on_)
00167 {
00168 ROS_INFO("flasher now %s", (flasher_on? "on": "off"));
00169 flasher_on_ = flasher_on;
00170 }
00171
00172 bool alarm_on = (sigIn->relays && IOadrState::ALARM);
00173 if (alarm_on != alarm_on_)
00174 {
00175 ROS_INFO("alarm now %s", (alarm_on? "on": "off"));
00176 alarm_on_ = alarm_on;
00177 }
00178 }
00179
00180
00190 void NavQueueMgr::reconfig(Config &newconfig, uint32_t level)
00191 {
00192 ROS_INFO("navigator dynamic reconfigure, level 0x%x", level);
00193 nav_->config_ = newconfig;
00194 nav_->configure();
00195 }
00196
00198 bool NavQueueMgr::setup(ros::NodeHandle node)
00199 {
00200
00201 ros::TransportHints noDelay = ros::TransportHints().tcpNoDelay(true);
00202 static uint32_t qDepth = 1;
00203
00204
00205 odom_state_ = node.subscribe("odom", qDepth,
00206 &NavQueueMgr::processOdom, this, noDelay);
00207 nav_cmd_ = node.subscribe("navigator/cmd", qDepth,
00208 &NavQueueMgr::processNavCmd, this, noDelay);
00209 roadmap_ = node.subscribe("roadmap_local", qDepth,
00210 &NavQueueMgr::processRoadMap, this, noDelay);
00211 signals_state_ = node.subscribe("ioadr/state", qDepth,
00212 &NavQueueMgr::processRelays, this, noDelay);
00213
00214
00215 car_cmd_ = node.advertise<art_msgs::CarCommand>("pilot/cmd", qDepth);
00216 nav_state_ =
00217 node.advertise<art_msgs::NavigatorState>("navigator/state", qDepth);
00218 signals_cmd_ = node.advertise<art_msgs::IOadrCommand>("ioadr/cmd", qDepth);
00219
00220 return true;
00221 }
00222
00223
00224 bool NavQueueMgr::shutdown()
00225 {
00226 ROS_INFO("Shutting down navigator node");
00227
00228
00229 pilot_command_t cmd;
00230 cmd.velocity = 0.0;
00231 cmd.yawRate = 0.0;
00232 SetSpeed(cmd);
00233
00234 #if 0
00235 nav_->obstacle->lasers->unsubscribe_lasers();
00236 nav_->odometry->unsubscribe();
00237 #endif
00238
00239 return 0;
00240 }
00241
00249 void NavQueueMgr::SetRelays(void)
00250 {
00251 if (signal_on_left_ != (bool) nav_->navdata.signal_left
00252 || signal_on_right_ != (bool) nav_->navdata.signal_right
00253 || flasher_on_ != (bool) nav_->navdata.flasher
00254 || alarm_on_ != (bool) nav_->navdata.alarm)
00255 {
00256
00257 art_msgs::IOadrCommand sig_cmd;
00258
00259
00260 if (nav_->navdata.signal_left)
00261 sig_cmd.relays_on = art_msgs::IOadrState::TURN_LEFT;
00262 else
00263 sig_cmd.relays_off = art_msgs::IOadrState::TURN_LEFT;
00264
00265
00266 if (nav_->navdata.signal_right)
00267 sig_cmd.relays_on |= art_msgs::IOadrState::TURN_RIGHT;
00268 else
00269 sig_cmd.relays_off |= art_msgs::IOadrState::TURN_RIGHT;
00270
00271
00272 if (nav_->navdata.flasher)
00273 sig_cmd.relays_on |= art_msgs::IOadrState::FLASHER;
00274 else
00275 sig_cmd.relays_off |= art_msgs::IOadrState::FLASHER;
00276
00277
00278 if (nav_->navdata.alarm)
00279 sig_cmd.relays_on |= art_msgs::IOadrState::ALARM;
00280 else
00281 sig_cmd.relays_off |= art_msgs::IOadrState::ALARM;
00282
00283 ROS_DEBUG("setting relays: left turn %s, right turn %s, "
00284 "flasher %s, alarm %s",
00285 (nav_->navdata.signal_left? "on": "off"),
00286 (nav_->navdata.signal_right? "on": "off"),
00287 (nav_->navdata.flasher? "on": "off"),
00288 (nav_->navdata.alarm? "on": "off"));
00289
00290
00291 signals_cmd_.publish(sig_cmd);
00292 }
00293 }
00294
00296 void NavQueueMgr::SetSpeed(pilot_command_t pcmd)
00297 {
00298 if (NavEstopState(nav_->navdata.estop) == NavEstopState::Suspend)
00299 {
00300 ROS_DEBUG_THROTTLE(20,
00301 "Navigator suspended, not sending pilot commands.");
00302 return;
00303 }
00304
00305 art_msgs::CarCommand cmd;
00306 cmd.header.stamp = ros::Time::now();
00307 cmd.header.frame_id = ArtFrames::vehicle;
00308
00309 cmd.control.velocity = pcmd.velocity;
00310 float yawRate = pcmd.yawRate;
00311 if (pcmd.velocity < 0)
00312 yawRate = -yawRate;
00313 cmd.control.angle =
00314 Steering::steering_angle(fabs(pcmd.velocity), yawRate);
00315
00316 ROS_DEBUG("Navigator CMD_CAR (%.3f m/s, %.3f degrees)",
00317 cmd.control.velocity, cmd.control.angle);
00318
00319 car_cmd_.publish(cmd);
00320 }
00321
00323 void NavQueueMgr::PublishState(void)
00324 {
00325 nav_->navdata.header.stamp = ros::Time::now();
00326 nav_->navdata.header.frame_id = ArtFrames::vehicle;
00327
00328 ROS_DEBUG("Publishing Navigator state = %s, %s, last_waypt %s"
00329 ", replan_waypt %s, R%d S%d Z%d, next waypt %s, goal chkpt %s",
00330 NavEstopState(nav_->navdata.estop).Name(),
00331 NavRoadState(nav_->navdata.road).Name(),
00332 ElementID(nav_->navdata.last_waypt).name().str,
00333 ElementID(nav_->navdata.replan_waypt).name().str,
00334 (bool) nav_->navdata.reverse,
00335 (bool) nav_->navdata.stopped,
00336 (bool) nav_->navdata.have_zones,
00337 ElementID(nav_->navdata.last_order.waypt[1].id).name().str,
00338 ElementID(nav_->navdata.last_order.chkpt[0].id).name().str);
00339
00340
00341 nav_state_.publish(nav_->navdata);
00342 }
00343
00345 void NavQueueMgr::spin()
00346 {
00347 ros::Rate cycle(art_msgs::ArtHertz::NAVIGATOR);
00348 while(ros::ok())
00349 {
00350 ros::spinOnce();
00351
00352
00353 SetSpeed(nav_->navigate());
00354
00355 SetRelays();
00356
00357 PublishState();
00358
00359
00360 cycle.sleep();
00361 }
00362 }
00363
00365 int main(int argc, char **argv)
00366 {
00367 ros::init(argc, argv, "navigator");
00368 ros::NodeHandle node;
00369 NavQueueMgr nq;
00370
00371
00372 if (!nq.setup(node))
00373 return 1;
00374
00375
00376 nq.spin();
00377
00378
00379 if (!nq.shutdown())
00380 return 3;
00381
00382 return 0;
00383 }