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
00017
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
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
00037 pose_euclide_distance = sqrt(pow(pose.x - goal.x, 2) + pow(pose.y - goal.y, 2));
00038
00039 root_euclide_distance = sqrt(pow(root->pose.x - goal.x, 2) + pow(root->pose.y - goal.y, 2));
00040
00041
00042
00043 position_improvement = pose_euclide_distance / root_euclide_distance;
00044
00045 rotation_diff = atan2(goal.y - pose.y, goal.x - pose.x) - pose.theta;
00046
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
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
00070 for(i=0; i<node->possible_controls.size(); i++){
00071 if(node->possible_controls[i].open){
00072
00073 expected_pose = robotKinematic(node->pose, node->possible_controls[i]);
00074
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
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
00095 node->sons.push_back(new_node);
00096
00097 node->possible_controls[best_control_index].open = false;
00098
00099
00100 if(new_node->isFree && new_node->depth < params.maxDepth){
00101 candidate_nodes.push_back(new_node);
00102 }
00103
00104
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
00113 double RRT::computeNodeRisk(Node* node){
00114
00115
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
00132 l = params.robotLength/2.0;
00133 w = params.robotWidth/2.0;
00134
00135
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
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
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
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
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
00178 if(node->parent != NULL){
00179 max_risk = max(max_risk, node->parent->risk);
00180 }
00181
00182 return max_risk;
00183 }
00184
00185
00186
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
00198 void RRT::init(){
00199
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
00213 root = node;
00214
00215 best_node = node;
00216
00217 candidate_nodes.clear();
00218 candidate_nodes.push_back(root);
00219 }
00220
00221
00222 void RRT::grow(){
00223 Node* best_node_to_grow;
00224 custom_pose random_goal;
00225
00226 random_goal = chooseRandomGoal();
00227
00228 best_node_to_grow = chooseBestNode(random_goal);
00229
00230 if(best_node_to_grow != NULL){
00231
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
00239 }
00240
00241
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
00251 random_score = (rand() % 100)/100.0;
00252
00253 window_size_grid = (int)floor(params.windowSize / og_array.array[0].info.resolution);
00254
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
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
00264 random_goal = poseFromGridCoord(random_x, random_y);
00265 }
00266 else{
00267
00268 random_goal = final_goal;
00269 }
00270 return random_goal;
00271 }
00272
00273
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
00296
00297
00298 if(index != -1 && index != 0){
00299 deleteUnreachableNodes(traj[index]);
00300
00301 root = traj[index];
00302 root->depth = 0;
00303 root->parent = NULL;
00304 }
00305
00306
00307
00308 updateNodes();
00309 }
00310
00311
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
00323
00324
00325
00326
00327
00328
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
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
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
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
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
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
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
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
00430 best_node = chooseBestNode(final_goal);
00431
00432 if(best_node == NULL){
00433 best_node = root;
00434 }
00435
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
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
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
00477 traj_msg.exists.data = (traj_msg.poses.size() > 1);
00478 }
00479
00480
00481 bool RRT::isGoalReached(){
00482
00483 return (sqrt(pow(root->pose.x - final_goal.x, 2) + pow(root->pose.y - final_goal.y, 2)) < params.goalTh);
00484 }
00485
00486
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
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;
00502 max_angular_vel = node->vel.angular.z + params.accOmegaMax * params.timeStep;
00503
00504
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
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
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
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
00602
00603
00604
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