riskrrt.cpp
Go to the documentation of this file.
00001 #include "riskrrt/riskrrt.hpp"
00002 #include <cmath>
00003 #include <algorithm>
00004 
00005 using namespace std;
00006 
00007 RRT::RRT(Params params){
00008   this->params = params;
00009   
00010 }
00011 
00012 RRT::~RRT(){
00013   
00014 }
00015 
00016 //returns the node score given the goal to reach (final or random)
00017 //the bigger the weight, the better the node
00018 double RRT::computeNodeWeight(Node* node, custom_pose goal){
00019 
00020   double weight;
00021   
00022   weight = 1.0 / (params.socialWeight * node->risk + trajLength(node->pose, goal)) * 1e-9;
00023   
00024   return weight;
00025 }
00026 
00027 //return a distance from pose to goal based on both euclidian distance and orientation
00028 double RRT::trajLength(custom_pose pose, custom_pose goal){
00029   
00030   double pose_euclide_distance;
00031   double root_euclide_distance;
00032   double position_improvement;
00033   double rotation_diff;
00034   double distance_from_goal;
00035   
00036   //distance from pose to goal
00037   pose_euclide_distance = sqrt(pow(pose.x - goal.x, 2) + pow(pose.y - goal.y, 2));
00038   //distance from root to goal
00039   root_euclide_distance = sqrt(pow(root->pose.x - goal.x, 2) + pow(root->pose.y - goal.y, 2));
00040   //position improvement with respect to the goal
00041   //ratio < 1 means we are getting closer to the goal
00042   //ratio > 1 means we are getting further away from the goal
00043   position_improvement = pose_euclide_distance / root_euclide_distance;
00044   //angle difference between pose orientation and the pose-goal vector
00045   rotation_diff = atan2(goal.y - pose.y, goal.x - pose.x) - pose.theta;
00046   //angle must be in [-PI;PI]
00047   if(rotation_diff > M_PI){
00048     rotation_diff -= 2 * M_PI;
00049   }
00050   if(rotation_diff < -M_PI){
00051     rotation_diff += 2 * M_PI;
00052   }
00053   distance_from_goal = position_improvement + params.rotationWeight * fabs(rotation_diff);
00054   
00055   return distance_from_goal;
00056 }
00057 
00058 //extends the tree from by creating a new node given an already existing node and a goal
00059 void RRT::extend(Node* node, custom_pose random_goal){
00060   Node* new_node;
00061   new_node = new Node;
00062   custom_pose expected_pose;
00063   int best_control_index;
00064   double control_score, best_control_score;
00065   int i, j;
00066   bool node_still_open;
00067   
00068   best_control_score = 0.0;
00069   //choose the best control among the (still open) possible controls
00070   for(i=0; i<node->possible_controls.size(); i++){
00071     if(node->possible_controls[i].open){
00072       //compute what pose would be obtained with that control
00073       expected_pose = robotKinematic(node->pose, node->possible_controls[i]);
00074       //compute the score for that pose
00075       control_score = computeControlScore(expected_pose, random_goal);
00076       if(control_score >= best_control_score){
00077         best_control_score = control_score;
00078         best_control_index = i;
00079       }
00080     }
00081   }
00082   
00083   //create the new node from the best control
00084   new_node->time = node->time + ros::Duration(params.timeStep);
00085   new_node->pose = robotKinematic(node->pose, node->possible_controls[best_control_index]);
00086   new_node->vel = node->possible_controls[best_control_index].twist;
00087   new_node->parent = node;
00088   new_node->sons.clear();
00089   new_node->possible_controls = discretizeVelocities(new_node);
00090   new_node->depth = node->depth + 1;
00091   new_node->risk = computeNodeRisk(new_node);
00092   new_node->isFree = (new_node->risk <= params.threshold);
00093   new_node->isOpen = true;
00094   //add new node to the tree (even if it is in collision, the candidate nodes vector is here to sort the nodes)
00095   node->sons.push_back(new_node);
00096   //close the control used to create the new node so it is impossible to create a duplicate node later
00097   node->possible_controls[best_control_index].open = false;
00098   
00099   //add the newly created node to the candidates vector (if it is free) to be taken into account for future expansion during the same growing phase
00100   if(new_node->isFree && new_node->depth < params.maxDepth){
00101     candidate_nodes.push_back(new_node);
00102   }
00103   
00104   //check if the last opened control was used and, if so, close the node so that it won't be selected as best node again
00105   node_still_open = false;
00106   for(j=0; j<node->possible_controls.size(); j++){
00107     node_still_open = node_still_open || node->possible_controls[j].open;
00108   }
00109   node->isOpen = node_still_open;
00110 }
00111 
00112 //read the risks from the grid and compute a global risk
00113 double RRT::computeNodeRisk(Node* node){
00114   
00115   //robot's footprint is assumed to be a rectangle
00116         custom_pose front_left;
00117   custom_pose front_right;
00118   custom_pose rear_left;
00119   custom_pose rear_right;
00120         int grid_front_left_x, grid_front_left_y;
00121         int grid_front_right_x, grid_front_right_y;
00122         int grid_rear_left_x, grid_rear_left_y;
00123         int grid_rear_right_x, grid_rear_right_y;
00124         double l, w;
00125   double node_theta;
00126         vector<int> grid_cells;
00127   int i, j;
00128   double risk, max_risk;
00129   int grid_max_x, grid_max_y, grid_min_x, grid_min_y;
00130   
00131   //the wheel axis is assumed to be in the middle
00132   l = params.robotLength/2.0;
00133   w = params.robotWidth/2.0;
00134         
00135         //computing the poses of each corner of the robot's footprint
00136         front_left.x = node->pose.x + (l * cos(node->pose.theta) + w * cos(node->pose.theta + M_PI/2.0));
00137         front_left.y = node->pose.y + (l * sin(node->pose.theta) + w * sin(node->pose.theta + M_PI/2.0));
00138         front_right.x = node->pose.x + (l * cos(node->pose.theta) + w * cos(node->pose.theta - M_PI/2.0));
00139         front_right.y = node->pose.y + (l * sin(node->pose.theta) + w * sin(node->pose.theta - M_PI/2.0));
00140         rear_left.x = node->pose.x + (l * cos(node->pose.theta + M_PI) + w * cos(node->pose.theta  + M_PI - M_PI/2.0));
00141         rear_left.y = node->pose.y + (l * sin(node->pose.theta + M_PI) + w * sin(node->pose.theta  + M_PI - M_PI/2.0));
00142         rear_right.x = node->pose.x + (l * cos(node->pose.theta + M_PI) + w * cos(node->pose.theta + M_PI + M_PI/2.0));
00143         rear_right.y = node->pose.y + (l * sin(node->pose.theta + M_PI) + w * sin(node->pose.theta + M_PI + M_PI/2.0));
00144         
00145         //the corners poses in grid coordinates
00146   grid_front_left_x = gridIFromPose(front_left);
00147   grid_front_left_y = gridJFromPose(front_left);
00148   grid_front_right_x = gridIFromPose(front_right);
00149   grid_front_right_y = gridJFromPose(front_right);
00150   grid_rear_left_x = gridIFromPose(rear_left);
00151   grid_rear_left_y = gridJFromPose(rear_left);
00152   grid_rear_right_x = gridIFromPose(rear_right);
00153   grid_rear_right_y = gridJFromPose(rear_right);
00154         
00155         //testing: simple bounding box TODO: exact footprint
00156         grid_max_x = max(grid_front_left_x, max(grid_front_right_x, max(grid_rear_left_x, grid_rear_right_x)));
00157         grid_max_y = max(grid_front_left_y, max(grid_front_right_y, max(grid_rear_left_y, grid_rear_right_y)));
00158         grid_min_x = min(grid_front_left_x, min(grid_front_right_x, min(grid_rear_left_x, grid_rear_right_x)));
00159         grid_min_y = min(grid_front_left_y, min(grid_front_right_y, min(grid_rear_left_y, grid_rear_right_y)));
00160         
00161   //creating a list of all the grid cells within the robot's footprint
00162         for(i=grid_min_x ; i<=grid_max_x ; i++){
00163                 for(j=grid_min_y ; j<=grid_max_y ; j++){
00164                         if (i >=0 && i < (int)og_array.array[0].info.width && j >=0 && j< (int)og_array.array[0].info.height){
00165                                 grid_cells.push_back(gridIndexFromCoord(i,j));
00166                         }
00167                 }
00168         }
00169   
00170   //going through all the cells in robot footprint and getting the maximum risk
00171   max_risk = 0.0;
00172   for(i=0; i<grid_cells.size(); i++){     
00173     risk = og_array.array[node->depth].data[grid_cells[i]];
00174     max_risk = max(risk, max_risk);
00175   }
00176   
00177   //risk propagation from a node to his sons if their risk is lower
00178   if(node->parent != NULL){
00179     max_risk = max(max_risk, node->parent->risk);
00180   }
00181   
00182         return max_risk;
00183 }
00184 
00185 //returns control score given the pose that would be obtained by applying the control during timestep and a goal
00186 //the bigger the score, the better the control
00187 double RRT::computeControlScore(custom_pose expected_pose,  custom_pose random_goal){
00188   double distance_from_random_goal;
00189   double score;
00190   
00191   distance_from_random_goal = trajLength(expected_pose, random_goal);
00192   score = 1.0 / distance_from_random_goal + 1e-9;
00193   
00194   return score;
00195 }
00196 
00197 //initialisation, creates a root at robot location
00198 void RRT::init(){
00199   //creating a new node at the robot current location, with its current speed
00200   Node* node;
00201   node = new Node;
00202   node->time = ros::Time::now();
00203   node->pose = robot_pose;
00204   node->vel = robot_vel;
00205   node->parent = NULL;
00206   node->sons.clear();
00207   node->possible_controls = discretizeVelocities(node);
00208   node->isOpen = true;
00209   node->depth = 0;
00210   node->risk = computeNodeRisk(node);
00211   node->isFree = (node->risk <= params.threshold);
00212   //set this new node as the tree root
00213   root = node;
00214   //set root as the best node to reach the final goal (this is needed to set the window in order to choose the next random goal)
00215   best_node = node;
00216   //the tree root is the first candidate to grow
00217   candidate_nodes.clear();
00218   candidate_nodes.push_back(root);
00219 }
00220 
00221 //adds 1 new node to the tree
00222 void RRT::grow(){
00223   Node* best_node_to_grow;
00224   custom_pose random_goal;
00225   //choosing a random point in window
00226   random_goal = chooseRandomGoal();
00227   //choosing the best node within the tree to grow toward the random point
00228   best_node_to_grow = chooseBestNode(random_goal);
00229   //checking if there is an actual best node (in some situations, it is possible to have none. for instance, if root is in collision)
00230   if(best_node_to_grow != NULL){
00231     //extend the tree from the best node to the random point by choosing the best control
00232     extend(best_node_to_grow, random_goal);
00233   }
00234   else ROS_INFO("ROBOT STUCK");
00235 }
00236 
00237 void RRT::grow_to_goal(Node* best_node, custom_pose goal){
00238   //TODO
00239 }
00240 
00241 //returns a random pose inside a user defined window
00242 custom_pose RRT::chooseRandomGoal(){
00243   double window_size;
00244   double random_score;
00245   int window_size_grid;
00246   int x_min_limit, x_max_limit, y_min_limit, y_max_limit;
00247   int random_x, random_y;
00248   custom_pose random_goal;
00249   
00250   //getting a random number between 0 and 99 for bias
00251   random_score = (rand() % 100)/100.0;
00252   //computing the window size in grid cells
00253   window_size_grid = (int)floor(params.windowSize / og_array.array[0].info.resolution);
00254   //reducing the window size if it exceeds the map dimensions
00255   x_min_limit = max(gridIFromPose(best_node->pose) - window_size_grid, 0);
00256   x_max_limit = min(gridIFromPose(best_node->pose) + window_size_grid, (int)og_array.array[0].info.width);
00257   y_min_limit = max(gridJFromPose(best_node->pose) - window_size_grid, 0);
00258   y_max_limit = min(gridJFromPose(best_node->pose) + window_size_grid, (int)og_array.array[0].info.height);
00259   if(random_score > params.bias){
00260     //choosing random position within limits (window or map edges)
00261     random_x = x_min_limit + rand() % (x_max_limit - x_min_limit);
00262     random_y = y_min_limit + rand() % (y_max_limit - y_min_limit);
00263     //same position but in map coordinates
00264     random_goal = poseFromGridCoord(random_x, random_y);
00265   }
00266   else{
00267     //choosing the final goal as random goal with a set probability (bias)
00268     random_goal = final_goal;
00269   }
00270   return random_goal;
00271 }
00272 
00273 //updates the tree, deletes unreachable nodes and updates remaining nodes
00274 void RRT::update(){
00275   
00276   
00277   int index;
00278   ros::Time present;
00279   
00280   present = ros::Time::now();
00281   
00282         if(traj.size() <= 1){
00283     index = -1;
00284         }
00285         else if(traj.front()->time > present){
00286     index = -1;
00287         }
00288         else if(traj.back()->time < present){
00289                 index = -1;
00290         }
00291   else{
00292     index = floor((present - traj.front()->time).toSec() / params.timeStep);
00293   }
00294   
00295   //to delete the unreachable nodes, there has to be an actual trajectory with at least 2 nodes (root and one other node)
00296   //if(traj.size() > 1){
00297     //if(ros::Time::now() >= traj[1]->time){
00298     if(index != -1 && index != 0){
00299       deleteUnreachableNodes(traj[index]);
00300       //making the first node in trajectory the new root
00301       root = traj[index];
00302       root->depth = 0;
00303       root->parent = NULL;
00304     }
00305     //}
00306   //}
00307   //update remaining tree
00308   updateNodes();
00309 }
00310 
00311 //depth first update of all nodes in tree, also creates node markers
00312 void RRT::updateNodes(){
00313   Node* current_node;
00314   vector<Node*> node_stack;
00315   int i;
00316   int nb_nodes;
00317   visualization_msgs::Marker node_marker;
00318   
00319   nb_nodes = 0;
00320   candidate_nodes.clear();
00321   
00322   //robot is always somewhere between root and the first node of the trajectory
00323   //thus, when the robot is moving, root and its descendants (except the subtree defined by the first node of the trajectory) are unreachable
00324   //there is no need in updating them or adding them in the candidate nodes vector
00325   //if(traj.size() > 1){
00326     //node_stack.push_back(traj[1]);
00327   //}
00328   //else{
00329     node_stack.push_back(root);
00330   //}
00331   while(!node_stack.empty()){
00332     current_node = node_stack.back();
00333     node_stack.pop_back();
00334     if(!current_node->sons.empty()){
00335       for(i=0; i<current_node->sons.size(); i++){
00336         node_stack.push_back(current_node->sons[i]);
00337       }
00338     }
00339     //update the depth
00340     if(current_node->parent != NULL){
00341       current_node->depth = current_node->parent->depth + 1;
00342     }
00343     current_node->risk = computeNodeRisk(current_node);
00344     current_node->isFree = (current_node->risk <= params.threshold);
00345     //add the "good" nodes to the candidate nodes vector
00346     if(current_node->isFree && current_node->depth < params.maxDepth && current_node->isOpen){
00347       candidate_nodes.push_back(current_node);
00348     }
00349     nb_nodes++;
00350     //rviz marker for nodes
00351     node_marker.header.frame_id = "/map";
00352     node_marker.header.stamp = ros::Time::now();
00353     node_marker.id = nb_nodes;
00354     node_marker.ns = "tree";
00355     node_marker.type = visualization_msgs::Marker::SPHERE;
00356     node_marker.action = visualization_msgs::Marker::ADD;
00357     node_marker.pose.position.x = current_node->pose.x;
00358     node_marker.pose.position.y = current_node->pose.y;
00359     node_marker.pose.position.z = 0.05;
00360     node_marker.scale.x = 0.1;
00361     node_marker.scale.y = 0.1;
00362     node_marker.scale.z = 0.1;
00363     node_marker.color.r = 0.0f;
00364     node_marker.color.g = 1.0f;
00365     node_marker.color.b = 0.0f;
00366     node_marker.color.a = 1.0;
00367     node_marker.lifetime = ros::Duration(1.0);
00368     node_markers.markers.push_back(node_marker);
00369     
00370   }
00371 }
00372 
00373 //deletes the tree minus the subtree defined by new_root
00374 void RRT::deleteUnreachableNodes(Node* new_root){
00375   Node* current_node;
00376   vector<Node*> node_stack;
00377   int i;
00378   
00379   node_stack.push_back(root);
00380   while(!node_stack.empty()){
00381     current_node = node_stack.back();
00382     node_stack.pop_back();
00383     if(!current_node->sons.empty()){
00384       for(i=0; i<current_node->sons.size(); i++){
00385         if(current_node->sons[i] != new_root){
00386           node_stack.push_back(current_node->sons[i]);
00387         }
00388       }
00389     }
00390     current_node->sons.clear();
00391     current_node->parent = NULL;
00392     current_node->possible_controls.clear();
00393     delete current_node;
00394   }
00395 }
00396 
00397 //returns the best node among candidates nodes with respect to goal
00398 Node* RRT::chooseBestNode(custom_pose goal){
00399   
00400   Node* best_rated_node;
00401   Node* current_node;
00402   double best_weight;
00403   double current_weight;
00404   int i;
00405   
00406   best_rated_node = NULL;
00407   best_weight = 0.0;
00408   for(i=0; i<candidate_nodes.size(); i++){
00409     current_node = candidate_nodes[i];
00410     current_weight = computeNodeWeight(current_node, goal);
00411     //node weight is better, node is free and open, node depth is less than maximum depth
00412     if(best_weight <= current_weight && current_node->isOpen){
00413       best_rated_node = current_node;
00414       best_weight = current_weight;
00415     }
00416   }
00417   
00418   return best_rated_node;
00419 }
00420 
00421 //select the best node with respect to the final goal and creates the path from root to that node
00422 void RRT::findPath(){
00423   riskrrt::PoseTwistStamped pose_twist;
00424   Node* current_node;
00425   visualization_msgs::Marker path_marker; 
00426   
00427   traj_msg.poses.clear();
00428   traj.clear();
00429   //find the best node to go toward the final goal and add it to the trajectory
00430   best_node = chooseBestNode(final_goal);
00431   //if there is no best node, pick root
00432   if(best_node == NULL){
00433     best_node = root;
00434   }
00435   //fill the twist message with node attributes
00436   pose_twist.pose.position.x = best_node->pose.x;
00437   pose_twist.pose.position.y = best_node->pose.y;
00438   pose_twist.pose.orientation = tf::createQuaternionMsgFromYaw(best_node->pose.theta);
00439   pose_twist.twist = best_node->vel;
00440   pose_twist.time = best_node->time;
00441   current_node = best_node;
00442   traj_msg.poses.push_back(pose_twist);
00443   traj.push_back(current_node);
00444   //add all bestnode's ancestor to the trajectory until root is reached
00445   while(current_node->parent != NULL){
00446     current_node = current_node->parent;
00447     pose_twist.pose.position.x = current_node->pose.x;
00448     pose_twist.pose.position.y = current_node->pose.y;
00449     pose_twist.pose.orientation = tf::createQuaternionMsgFromYaw(current_node->pose.theta);
00450     pose_twist.twist = current_node->vel;
00451     pose_twist.time = current_node->time;
00452     traj_msg.poses.insert(traj_msg.poses.begin(), pose_twist);
00453     traj.insert(traj.begin(), current_node);
00454     
00455     //create a marker for the nodes in the trajectory
00456     path_marker.header.frame_id = "/map";
00457     path_marker.header.stamp = ros::Time::now();
00458     path_marker.id = rand();
00459     path_marker.ns = "tree";
00460     path_marker.type = visualization_msgs::Marker::SPHERE;
00461     path_marker.action = visualization_msgs::Marker::ADD;
00462     path_marker.pose.position.x = current_node->pose.x;
00463     path_marker.pose.position.y = current_node->pose.y;
00464     path_marker.pose.position.z = 0.06;
00465     path_marker.scale.x = 0.1;
00466     path_marker.scale.y = 0.1;
00467     path_marker.scale.z = 0.1;
00468     path_marker.color.r = 1.0f;
00469     path_marker.color.g = 0.0f;
00470     path_marker.color.b = 0.0f;
00471     path_marker.color.a = 1.0;
00472     path_marker.lifetime = ros::Duration(1.0);
00473     path_markers.markers.push_back(path_marker);
00474     
00475   }
00476   //set the trajectory flag to stop robot from executing deprecated trajectories if this trajectory is empty
00477   traj_msg.exists.data = (traj_msg.poses.size() > 1);  
00478 }
00479 
00480 //returns true if robot close enough to the goal (threshold set by user)
00481 bool RRT::isGoalReached(){
00482   //this is a distance criteria, orientation is not taken into account
00483   return (sqrt(pow(root->pose.x - final_goal.x, 2) + pow(root->pose.y - final_goal.y, 2)) < params.goalTh);
00484 }
00485 
00486 //returns a list of all possible controls for a node
00487 vector<Control> RRT::discretizeVelocities(Node* node){
00488   
00489   vector<Control> controls;
00490   Control control;
00491   double min_linear_vel;
00492   double max_linear_vel;
00493   double min_angular_vel;
00494   double max_angular_vel;
00495   int i, j;
00496   double delta_linear, delta_angular;
00497   
00498   //compute maximum and minimum velocities that can be reached from that node given the speed and acceleration limits of the robot
00499   min_linear_vel = node->vel.linear.x - params.accMax * params.timeStep;
00500   max_linear_vel = node->vel.linear.x + params.accMax * params.timeStep;
00501   min_angular_vel = node->vel.angular.z - params.accOmegaMax * params.timeStep;//right
00502   max_angular_vel = node->vel.angular.z + params.accOmegaMax * params.timeStep;//left
00503   
00504   //make sure that speed limits are not exceeded
00505   min_linear_vel = max(params.vMin, min_linear_vel);
00506   max_linear_vel = min(params.vMax, max_linear_vel);
00507   min_angular_vel = max(-params.omegaMax, min_angular_vel);
00508   max_angular_vel = min(params.omegaMax, max_angular_vel);
00509   
00510   //create the set of controls
00511   delta_linear = (max_linear_vel - min_linear_vel) / double(params.nv);
00512         delta_angular = (max_angular_vel - min_angular_vel) / double(params.nphi);
00513   for(i=0; i<params.nv; i++){
00514     control.twist.linear.x = min_linear_vel + i * delta_linear;
00515     for(j=0; j<params.nphi; j++){
00516       control.twist.angular.z = min_angular_vel + j * delta_angular;
00517       control.open = true;
00518       controls.push_back(control);
00519     }
00520   }
00521   
00522   return controls;
00523 }
00524 
00525 //get the pose of the new node for a differential robot
00526 custom_pose RRT::robotKinematic(custom_pose pose, Control control){
00527   custom_pose new_pose;
00528   double rotation_radius;
00529   double delta_theta, delta_x, delta_y;
00530   
00531   if(control.twist.linear.x == 0.0){
00532     delta_theta = control.twist.angular.z * params.timeStep;
00533     delta_x = 0.0;
00534     delta_y = 0.0;
00535         }
00536         else if(control.twist.angular.z == 0.0){
00537     delta_theta = 0.0;
00538     delta_x = control.twist.linear.x * params.timeStep;
00539     delta_y = 0.0;
00540   }
00541   else{
00542     rotation_radius = control.twist.linear.x / control.twist.angular.z;
00543     delta_theta = control.twist.angular.z * params.timeStep;
00544     delta_x = rotation_radius * sin(delta_theta);
00545     delta_y = rotation_radius * (1.0 - cos(delta_theta));
00546   }
00547   new_pose.x = pose.x + (delta_x * cos(pose.theta) - delta_y * sin(pose.theta));
00548   new_pose.y = pose.y + (delta_x * sin(pose.theta) + delta_y * cos(pose.theta));
00549   new_pose.theta = atan2(sin(pose.theta + delta_theta), cos(pose.theta + delta_theta));
00550   
00551   return new_pose;
00552 }
00553 
00554 
00555 //bunch of functions to help switching between coordinates types
00556 int RRT::gridIndexFromPose(custom_pose pose){
00557   int index, i, j;
00558   i = gridIFromPose(pose);
00559   j = gridJFromPose(pose);
00560   index = gridIndexFromCoord(i, j);
00561   return index;
00562 }
00563 
00564 int RRT::gridIFromPose(custom_pose pose){
00565   return (int)round((pose.x - og_array.array[0].info.origin.position.x) / og_array.array[0].info.resolution);
00566 }
00567 
00568 int RRT::gridJFromPose(custom_pose pose){
00569   return (int)round((pose.y - og_array.array[0].info.origin.position.y) / og_array.array[0].info.resolution);
00570 }
00571 
00572 int RRT::gridIndexFromCoord(int i, int j){
00573   return i + og_array.array[0].info.width * j;
00574 }
00575 
00576 int RRT::gridIFromIndex(int index){
00577   return  index % og_array.array[0].info.width;
00578 }
00579 
00580 int RRT::gridJFromIndex(int index){
00581   return floor(index / og_array.array[0].info.width);
00582 }
00583 
00584 custom_pose RRT::poseFromGridIndex(int index){
00585   int i, j;
00586   custom_pose pose;
00587   
00588   i = gridIFromIndex(index);
00589   j = gridJFromIndex(index);
00590   pose = poseFromGridCoord(i, j);
00591   
00592   return pose;
00593 }
00594 
00595 custom_pose RRT::poseFromGridCoord(int i, int j){
00596   custom_pose pose;
00597   pose.x = og_array.array[0].info.resolution * i + og_array.array[0].info.origin.position.x;
00598         pose.y = og_array.array[0].info.resolution * j + og_array.array[0].info.origin.position.y;
00599   return pose;
00600 }
00601 //end of functions to help switching between coordinates types
00602 
00603 
00604 //subscribers initializations and callbacks
00605 void RRT::controllerFeedbackCallback(const std_msgs::Bool::ConstPtr& msg){
00606   robot_on_traj = msg->data;
00607 }
00608 
00609 void RRT::initcontrollerFeedbackSub(){
00610   controllerFeedbackSubscriber = nodeHandle.subscribe("/controller_feedback", 1, &RRT::controllerFeedbackCallback, this);
00611 }
00612 
00613 void RRT::ogArrayCallback(const riskrrt::OccupancyGridArray::ConstPtr& msg){
00614   og_array = *msg;
00615 }
00616 
00617 void RRT::initOgArraySub(){
00618   ogArraySubscriber = nodeHandle.subscribe("/ogarray", 1, &RRT::ogArrayCallback, this);
00619 }
00620 
00621 void RRT::odomCallback(const nav_msgs::Odometry::ConstPtr& msg){
00622   robot_vel = msg->twist.twist;
00623 }
00624 
00625 void RRT::initOdomSub(){
00626   odomSubscriber = nodeHandle.subscribe("/odom", 1, &RRT::odomCallback, this);
00627 }
00628 
00629 void RRT::poseCallback(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg){
00630   robot_pose.x = msg->pose.pose.position.x;
00631   robot_pose.y = msg->pose.pose.position.y;
00632   robot_pose.theta = tf::getYaw(msg->pose.pose.orientation);
00633 }
00634 
00635 void RRT::initPoseSub(){
00636   poseSubscriber = nodeHandle.subscribe("/amcl_pose", 1, &RRT::poseCallback, this);
00637 }
00638 
00639 void RRT::goalCallback(const geometry_msgs::PoseStamped::ConstPtr& msg){
00640   final_goal.x = msg->pose.position.x;
00641   final_goal.y = msg->pose.position.y;
00642   final_goal.theta = tf::getYaw(msg->pose.orientation);
00643   goal_received = true;
00644 }
00645   
00646 void RRT::initGoalSub(){
00647   goalSubscriber = nodeHandle.subscribe("/goal", 1, &RRT::goalCallback, this);
00648 }
00649 //end of subscribers initializations and callbacks


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