checkpoint_manager.cpp
Go to the documentation of this file.
00001 #include "checkpoint_manager.h"
00002 #include <move_base_msgs/MoveBaseAction.h>
00003 #include <actionlib/client/simple_action_client.h>
00004 
00005 typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient;
00006 
00007 CheckpointManager::CheckpointManager()
00008 {
00009     srv_checkpoint_ = nh_.advertiseService("add_nav_checkpoint",
00010                                            & CheckpointManager::add_checkpoint_callback, this);
00011 
00012     srv_action_ = nh_.advertiseService("action_checkpoint_nav",
00013                                            & CheckpointManager::action_callback, this);
00014 }
00015 
00016 bool
00017 CheckpointManager::add_checkpoint_callback(iri_checkpoint_nav::Checkpoint::Request  & req,
00018                                            iri_checkpoint_nav::Checkpoint::Response & res)
00019 {
00020     // Autogenerate the ID each time a new checkpoint is recieved
00021     req.id = checkpoints_.size();
00022 
00023     checkpoints_.push_back(req);
00024     marker_.display_new_checkpoint(req);
00025 
00026     return true;
00027 }
00028 
00029 bool
00030 CheckpointManager::action_callback(iri_checkpoint_nav::ActionCheckpointNav::Request  & req,
00031                                    iri_checkpoint_nav::ActionCheckpointNav::Response & res)
00032 {
00033     switch (req.action)
00034     {
00035         case iri_checkpoint_nav::ActionCheckpointNav::Request::START_NAV:
00036             ROS_INFO("Recieved start navigation action");
00037             res.success = start_navigation();
00038             break;
00039         case iri_checkpoint_nav::ActionCheckpointNav::Request::RESET_CHECKPOINTS:
00040             ROS_INFO("Recieved reset action");
00041             reset_checkpoints();
00042             res.success = true;
00043             break;
00044         default:
00045             res.success = false;
00046     }
00047 
00048     return res.success;
00049 }
00050 
00051 void
00052 CheckpointManager::activate_current_checkpoint()
00053 {
00054     marker_.display_active_checkpoint(* current_goal_);
00055 }
00056 
00057 void
00058 CheckpointManager::visited_current_checkpoint()
00059 {
00060     marker_.display_visited_checkpoint(* current_goal_);
00061 }
00062 
00063 void
00064 CheckpointManager::reset_checkpoints()
00065 {
00066     checkpoints_.clear();
00067 }
00068 
00069 geometry_msgs::Quaternion
00070 CheckpointManager::generate_default_orientation()
00071 {
00072     geometry_msgs::Quaternion quat;
00073 
00074     quat.x = 0;
00075     quat.y = 0;
00076     quat.z = 0;
00077     quat.w = 1;
00078 
00079     return quat;
00080 }
00081 
00082 geometry_msgs::Quaternion
00083 CheckpointManager::generate_goal_orientation()
00084 {
00085     // Check if we have only one goal
00086     if ((current_goal_ == --checkpoints_.end()) && (current_goal_ == checkpoints_.begin()))
00087         return generate_default_orientation();
00088 
00089     std::vector<CheckpointRequest>::iterator ref_goal = current_goal_;
00090     CheckpointRequest start;
00091     CheckpointRequest end;
00092 
00093     if (current_goal_ == --checkpoints_.end()) {
00094         // Last checkpoint. Orientation is from previous to current.
00095         ref_goal--;
00096         start = * ref_goal;
00097         end   = * current_goal_;
00098     } else {
00099         // Not in the last checkpoint. Orientation is from current to next.
00100         ref_goal++;
00101         start = * current_goal_;
00102         end   = * ref_goal;
00103     }
00104 
00105     // ArcTan without singularities (atan2) will give the angle in radians
00106     double rotation_angle = atan2(end.position.y - start.position.y,
00107                                   end.position.x - start.position.x);
00108 
00109     return tf::createQuaternionMsgFromYaw(rotation_angle);
00110 }
00111 
00112 bool
00113 CheckpointManager::send_navigation_goal(const CheckpointRequest checkpoint)
00114 {
00115     //tell the action client that we want to spin a thread by default
00116     MoveBaseClient ac("move_base", true);
00117 
00118     //wait for the action server to come up
00119     while (! ac.waitForServer(ros::Duration(5.0))) {
00120         ROS_INFO("Waiting for the move_base action server to come up");
00121     }
00122 
00123     move_base_msgs::MoveBaseGoal goal;
00124 
00125     goal.target_pose.header.frame_id    = checkpoint.ref_frame;
00126     goal.target_pose.header.stamp       = ros::Time::now();
00127     goal.target_pose.pose.position      = checkpoint.position;
00128     goal.target_pose.pose.orientation   = generate_goal_orientation();
00129 
00130     ac.sendGoal(goal);
00131 
00132     ac.waitForResult();
00133 
00134     if (ac.getState() != actionlib::SimpleClientGoalState::SUCCEEDED) {
00135         ROS_WARN("The base failed to move");
00136         return false;
00137     }
00138 
00139     return true;
00140 }
00141 
00142 bool
00143 CheckpointManager::start_navigation()
00144 {
00145     std::vector<CheckpointRequest>::iterator it;
00146 
00147     for (it = checkpoints_.begin(); it < checkpoints_.end(); it++) {
00148         ROS_INFO("Sent navigation goal");
00149         current_goal_ = it;
00150         // Display navigation point in rviz
00151         activate_current_checkpoint();
00152         // Send goal to the navigation stack and wait
00153         if (! send_navigation_goal(* it))
00154             ROS_WARN("Navigation to the goal failed. Send to the next goal");
00155 
00156         visited_current_checkpoint();
00157     }
00158 
00159     return true;
00160 }
00161 
00162 int main(int argc, char** argv)
00163 {
00164     ros::init(argc, argv, "checkpoint_manager");
00165     CheckpointManager server;
00166 
00167     ros::spin();
00168 
00169     return 0;
00170 }


iri_checkpoint_nav
Author(s): Jose Luis Rivero
autogenerated on Fri Dec 6 2013 22:56:28