controller.cpp
Go to the documentation of this file.
00001 #include <ros/ros.h>
00002 #include <riskrrt/PoseTwistStamped.h>
00003 #include <riskrrt/Trajectory.h>//ros only have path msg, no trajectory
00004 #include <geometry_msgs/Point.h>
00005 #include <geometry_msgs/Pose.h>
00006 #include <geometry_msgs/PoseStamped.h>
00007 #include <geometry_msgs/Twist.h>
00008 #include <geometry_msgs/PoseWithCovarianceStamped.h>
00009 #include <nav_msgs/Odometry.h>
00010 #include <tf/tf.h>
00011 #include <vector>
00012 
00013 using namespace std;
00014 
00015 geometry_msgs::Pose robot_pose;
00016 riskrrt::Trajectory trajectory;
00017 
00018 //kanayama control law
00019 //returns a corrected control from the robot theoretical, estimated pose and current speed
00020 geometry_msgs::Twist kanayama(geometry_msgs::Pose theoretical_pose, geometry_msgs::Pose estimated_pose, geometry_msgs::Twist control){
00021 
00022   double delta_x, delta_y, delta_theta;
00023   double error_x, error_y, error_theta;
00024   double k_x, k_y, k_theta;
00025   geometry_msgs::Twist corrected_control;
00026 
00027   //difference between theoretical pose (from the kinematic model) and estimated pose (from localization)
00028         delta_x = theoretical_pose.position.x - estimated_pose.position.x;
00029         delta_y = theoretical_pose.position.y - estimated_pose.position.y;
00030         delta_theta = tf::getYaw(theoretical_pose.orientation) - tf::getYaw(estimated_pose.orientation);
00031   
00032   //error
00033         error_x = delta_x * cos(tf::getYaw(estimated_pose.orientation)) + delta_y * sin(tf::getYaw(estimated_pose.orientation));
00034         error_y = -delta_x * sin(tf::getYaw(estimated_pose.orientation)) + delta_y * cos(tf::getYaw(estimated_pose.orientation));
00035         error_theta = delta_theta;
00036 
00037   //some coefficient
00038         k_x = 0.15;
00039         k_y = 0.15;
00040         k_theta = 2 * sqrt(k_y);
00041         
00042   //corrected control
00043   corrected_control.linear.x = control.linear.x * cos(error_theta) + k_x * error_x;
00044   corrected_control.angular.z = control.angular.z + control.linear.x * (k_y * error_y + k_theta * sin(error_theta));
00045         
00046         return corrected_control;
00047 }
00048 
00049 //returns a control that stops the robot (stops the robot from executing the end of a deprecated trajectory if it cannot find a new one)
00050 geometry_msgs::Twist brake(){
00051   
00052   geometry_msgs::Twist corrected_control;
00053   
00054   corrected_control.linear.x = 0.0;
00055   corrected_control.angular.z = 0.0;
00056     
00057         return corrected_control;
00058 };
00059 
00060 //returns a pose given a starting pose, velocity and duration
00061 //differential drive kinematic
00062 geometry_msgs::Pose robotKinematic(geometry_msgs::Pose pose, geometry_msgs::Twist velocity, double duration){
00063   geometry_msgs::Pose new_pose;
00064   double rotation_radius;
00065   double delta_theta, delta_x, delta_y;
00066   
00067   if(velocity.linear.x == 0.0){
00068     delta_theta = velocity.angular.z * duration;
00069     delta_x = 0.0;
00070     delta_y = 0.0;
00071         }
00072         else if(velocity.angular.z == 0.0){
00073     delta_theta = 0.0;
00074     delta_x = velocity.linear.x * duration;
00075     delta_y = 0.0;
00076   }
00077   else{
00078     rotation_radius = velocity.linear.x / velocity.angular.z;
00079     delta_theta = velocity.angular.z * duration;
00080     delta_x = rotation_radius * sin(delta_theta);
00081     delta_y = rotation_radius * (1.0 - cos(delta_theta));
00082   }
00083   new_pose.position.x = pose.position.x + (delta_x * cos(tf::getYaw(pose.orientation)) - delta_y * sin(tf::getYaw(pose.orientation)));
00084   new_pose.position.y = pose.position.y + (delta_x * sin(tf::getYaw(pose.orientation)) + delta_y * cos(tf::getYaw(pose.orientation)));
00085   new_pose.orientation = tf::createQuaternionMsgFromYaw(tf::getYaw(pose.orientation) + delta_theta);
00086   
00087   return new_pose;
00088 }
00089 
00090 //returns the index of the last visited node in the trajectory
00091 int interpolation(riskrrt::Trajectory trajectory, double timeStep){
00092   
00093   int index;
00094   ros::Time present;
00095   
00096   present = ros::Time::now();
00097   
00098   //there is only root in the trajectory, wait for an actual trajectory
00099         if(trajectory.poses.size() <= 1){
00100     index = -1;
00101         }
00102   //trajectory hasn't started yet (root time is in the future)
00103         else if(trajectory.poses.front().time > present){
00104     index = -1;
00105         }
00106   //trajectory has already ended (last node of trajectory is in the past)
00107         else if(trajectory.poses.back().time < present){
00108                 index = -1;
00109         }
00110   else{
00111     index = floor((present - trajectory.poses.front().time).toSec() / timeStep);
00112   }
00113     
00114         return index;
00115 }
00116 
00117 void trajectoryCallback(const riskrrt::Trajectory::ConstPtr& msg){
00118   trajectory = *msg;
00119 }
00120 
00121 void poseCallback(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg){
00122   robot_pose = msg->pose.pose;
00123 }
00124 
00125 int main(int argc, char** argv){
00126   
00127   ros::init(argc, argv, "riskrrt_controller");
00128   
00129   ros::NodeHandle n;
00130   
00131   geometry_msgs::Pose theoretical_pose;
00132   geometry_msgs::Twist raw_control;
00133   int index;
00134   double duration;
00135   double timeStep;
00136   geometry_msgs::Twist corrected_control;
00137   std_msgs::Bool controller_feedback;
00138   
00139   n.param("timeStep", timeStep, 0.5);
00140   
00141   ros::Publisher controlPublisher = n.advertise<geometry_msgs::Twist>("/cmd_vel", 100);
00142   //publish a msg to tell the rrt if the robot is too far from the trajectory
00143   ros::Publisher controllerFeedbackPublisher = n.advertise<std_msgs::Bool>("controller_feedback",1);
00144   
00145   ros::Subscriber trajectorySubscriber = n.subscribe("/traj", 1, trajectoryCallback);
00146   ros::Subscriber poseSubscriber = n.subscribe("/amcl_pose", 1, poseCallback);
00147   
00148   ros::Rate loop_rate(20.0);
00149   trajectory.exists.data = false;
00150   
00151   while(ros::ok()){
00152     
00153     ros::spinOnce();
00154     
00155     if(trajectory.exists.data){
00156       
00157       //what is the last node of the trajectory the robot visited
00158       index = interpolation(trajectory, timeStep);
00159       
00160       if(index != -1){
00161         
00162         //time difference between present time and timestamp of the last visited node (s)
00163         duration = (ros::Time::now() - trajectory.poses[index].time).toSec();
00164         //where should the robot be on the trajectory at present time
00165         theoretical_pose = robotKinematic(trajectory.poses[index].pose, trajectory.poses[index+1].twist, duration);
00166         //compute corrected control
00167         corrected_control = kanayama(theoretical_pose, robot_pose, trajectory.poses[index+1].twist);
00168         
00169         //check the difference between the estimated robot pose and the theoretical pose
00170         double pose_error = sqrt(pow(theoretical_pose.position.x - robot_pose.position.x, 2) + pow(theoretical_pose.position.y - robot_pose.position.y, 2));
00171         controller_feedback.data = (pose_error < 0.3);
00172         
00173       }
00174       else{
00175         corrected_control = brake();
00176         controller_feedback.data = true;
00177       }
00178       
00179     }
00180     else{
00181       corrected_control = brake();
00182       controller_feedback.data = true;
00183     }
00184     
00185     //publish the corrected control
00186     controlPublisher.publish(corrected_control);
00187     //publish a message to tell the rrt if the robot position is ok
00188     controllerFeedbackPublisher.publish(controller_feedback);
00189     
00190     loop_rate.sleep();
00191   }
00192 
00193   return 0;
00194 }


riskrrt
Author(s): Gregoire Vignon
autogenerated on Thu Jun 6 2019 18:42:06