00001 #include <ros/ros.h> 00002 #include <geometry_msgs/Point.h> 00003 #include <geometry_msgs/Pose.h> 00004 #include <geometry_msgs/PoseStamped.h> 00005 #include <geometry_msgs/Twist.h> 00006 #include <geometry_msgs/PoseWithCovarianceStamped.h> 00007 #include <nav_msgs/Odometry.h> 00008 #include <visualization_msgs/MarkerArray.h> 00009 #include <riskrrt/PoseTwistStamped.h> 00010 #include <riskrrt/Trajectory.h> 00011 #include <nav_msgs/OccupancyGrid.h> 00012 #include <riskrrt/OccupancyGridArray.h> 00013 #include <vector> 00014 #include <tf/tf.h> 00015 00016 using namespace std; 00017 00018 struct Params{ 00019 double timeStep;//time step between each node (s) 00020 int maxDepth;//maximum depth a node can have 00021 int nv;//discretization of the robot's linear speed, used to create the set of possible controls from a node 00022 int nphi;//discretization of the robot's angular speed, used to create the set of possible controls from a node 00023 double threshold;//maximum risk value a node can have to be considered free 00024 double socialWeight;//weight of the risk component in the computation of the node's score 00025 double rotationWeight;//weight of the node's orientation toward the goal (compared to the distance) 00026 double growTime;//time allocated for the tree growth between map updates (s) /!\: issue forces growtime < timestep 00027 double bias;//percentage of the time the final goal is chosen as random goal 00028 double goalTh;//maximum distance the robot can be from the final goal to consider the goal reached (m) 00029 double windowSize;//size of the window from which to pick a random goal (m) 00030 double robotLength;//robot lenght (m) /!\: the wheel axis is assumed to be in the middle 00031 double robotWidth;//robot width (m) 00032 double vMin;//minimum robot linear speed (m/s), set it to 0 or a negative value to allow reverse 00033 double vMax;//maximum robot linear speed (m/s) 00034 double accMax;//maximum linear acceleration (m/s^2) 00035 double omegaMax;//maximum angular speed (rad/s) 00036 double accOmegaMax;//maximum angular acceleration (rad/s^2) 00037 }; 00038 00039 struct custom_pose{//function provided by the tf library to get yaw from quaternion is terrible, hence this. 00040 double x;//in meters 00041 double y;//in meters 00042 double theta;//in radians (-PI, PI) 00043 }; 00044 00045 struct Control{ 00046 geometry_msgs::Twist twist; 00047 bool open;//whether the control has already been tested or not (doesn't matter if the resulting node was in collision or was effectively added to the tree) 00048 }; 00049 00050 struct Node{ 00051 ros::Time time;//time at which node is valid 00052 custom_pose pose;//pose of the node 00053 geometry_msgs::Twist vel;//velocity the robot should have at this node 00054 Node* parent;//parent node 00055 vector<Node*> sons;//list of sons 00056 vector<Control> possible_controls;//list of all possible controls from that node considering nv, nphi, velocities and acceleration limits 00057 double risk;//node risk (=/= node weight, we don't consider distance to goal) 00058 int depth;//depth of node in the tree 00059 bool isFree;//false if the node is in collision (the risk is higher than the threshold set by user) 00060 bool isOpen;//true if at least one control among all possible controls remain open 00061 }; 00062 00063 00064 class RRT{ 00065 public: 00066 00068 ros::NodeHandle nodeHandle; 00069 custom_pose robot_pose;//pose of the robot 00070 geometry_msgs::Twist robot_vel;//velocity of the robot 00071 Node* root;//tree root 00072 Node* best_node;//best node to reach final goal (=/= best node to reach random goal) 00073 vector<Node*> candidate_nodes;//all the nodes that are candidates to grow, list is created and updated during growing phase, then deleted 00074 custom_pose final_goal;//final goal set by user (=/= random goal) 00075 bool goal_received;//flag to know when a new goal has been received 00076 bool robot_on_traj;//is the robot close enough to its theoretical pose, flag for reinit 00077 riskrrt::OccupancyGridArray og_array;//array of maps, time of map = timeStep * position in array. TODO: multiple gridArray 00078 riskrrt::Trajectory traj_msg;//trajectory msg for controller 00079 vector<Node*> traj;//trajectory with pointer to the nodes, used to update tree 00080 Params params;//list of params 00081 //tree markers 00082 visualization_msgs::MarkerArray node_markers; 00083 visualization_msgs::MarkerArray path_markers; 00084 //subscribers 00085 ros::Subscriber controllerFeedbackSubscriber; 00086 ros::Subscriber ogArraySubscriber; 00087 ros::Subscriber poseSubscriber; 00088 ros::Subscriber goalSubscriber; 00089 ros::Subscriber odomSubscriber; 00090 00091 00093 RRT(Params params); 00094 ~RRT(); 00095 void init();//initialisation, creates a root at robot location 00096 void grow();//adds 1 new node to the tree 00097 void grow_to_goal(Node* best_node, custom_pose goal);//TODO 00098 void update();//updates the tree, deletes unreachable nodes and updates remaining nodes 00099 void updateNodes();//depth first update of all nodes in tree, also creates node markers 00100 void deleteUnreachableNodes(Node* new_root);//deletes the tree minus the subtree defined by new_root 00101 Node* chooseBestNode(custom_pose goal);//returns the best node among candidates nodes with respect to goal 00102 void findPath();//select the best node with respect to the final goal and creates the path from root to that node 00103 bool isGoalReached();//returns true if robot close enough to the goal (threshold set by user) 00104 custom_pose chooseRandomGoal();//returns a random pose inside a user defined window 00105 double computeNodeWeight(Node* node, custom_pose goal);//returns the node score given the goal to reach (final or random) 00106 void extend(Node* node, custom_pose random_goal);//extends the tree from by creating a new node given an already existing node and a goal 00107 vector<Control> discretizeVelocities(Node* node);//returns a list of all possible controls for a node 00108 double trajLength(custom_pose pose, custom_pose goal);//return a distance from pose to goal based on both euclidian distance and orientation 00109 custom_pose robotKinematic(custom_pose pose, Control control);//get the pose of the new node for a differential robot 00110 double computeControlScore(custom_pose expected_pose, custom_pose random_goal);//returns control score given the pose that would be obtained by applying the control during timestep and a goal 00111 double computeNodeRisk(Node* node);//read the risks from the grid and compute a global risk 00112 00113 //bunch of functions to help switching between coordinates types 00114 int gridIndexFromPose(custom_pose pose); 00115 int gridIFromPose(custom_pose pose); 00116 int gridJFromPose(custom_pose pose); 00117 int gridIndexFromCoord(int i, int j); 00118 int gridIFromIndex(int index); 00119 int gridJFromIndex(int index); 00120 custom_pose poseFromGridIndex(int index); 00121 custom_pose poseFromGridCoord(int i, int j); 00122 00123 //subscribers initializations and callbacks 00124 void controllerFeedbackCallback(const std_msgs::Bool::ConstPtr& msg); 00125 void initcontrollerFeedbackSub(); 00126 void ogArrayCallback(const riskrrt::OccupancyGridArray::ConstPtr& msg); 00127 void initOgArraySub(); 00128 void odomCallback(const nav_msgs::Odometry::ConstPtr& msg); 00129 void initOdomSub(); 00130 void poseCallback(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg); 00131 void initPoseSub(); 00132 void goalCallback(const geometry_msgs::PoseStamped::ConstPtr& msg); 00133 void initGoalSub(); 00134 00135 };