clearpath.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Daniel Claes, Maastricht University
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Maastricht University nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 
00031 
00032 #include "collvoid_local_planner/clearpath.h"
00033 #include <ros/ros.h>
00034 #include <float.h>
00035 #include <boost/foreach.hpp>
00036 namespace collvoid{
00037 
00038 
00039   // VO createObstacleVO(Vector2& position1, const std::vector<Vector2>& footprint1,Vector2& vel1,  Vector2& position2, const std::vector<Vector2>& footprint2){
00040   //   VO result;
00041   //   std::vector<Vector2> mink_sum = minkowskiSum(footprint1, footprint2);
00042 
00043   //   Vector2 rel_position = position2 - position1;
00044 
00045   //   Vector2 rel_position_normal = normal(rel_position);
00046   //   double min_dist = abs(rel_position);
00047     
00048   //   for (int i = 0; i< (int) mink_sum.size(); i++){
00049   //     Vector2 project_on_rel_position = intersectTwoLines(Vector2(0.0, 0.0), rel_position, rel_position + mink_sum[i], rel_position_normal);
00050   //     double dist = abs(project_on_rel_position);
00051   //     if (project_on_rel_position * rel_position < EPSILON){
00052   //    //      ROS_ERROR("Collision?");
00053   //    dist = -dist;
00054         
00055   //     }
00056       
00057   //     if (dist < min_dist) {
00058   //    min_dist = dist;
00059   //     }
00060   //   }
00061   //   result.left_leg_dir = - normalize(rel_position_normal);
00062   //   result.right_leg_dir = - result.left_leg_dir;
00063   //   result.relative_position = rel_position;
00064   //   result.combined_radius = abs(rel_position) - min_dist;
00065     
00066   //   result.point = normalize(rel_position) * min_dist; // * std::max(1 - abs(vel1), 0.0);
00067   //   result.trunc_left = result.point;
00068   //   result.trunc_right = result.point;
00069   //   result.trunc_line_center = result.point;
00070 
00071   //   return result;
00072     
00073   // }
00074 
00075   
00076 
00077 
00078   VO createObstacleVO(Vector2& position1, double radius1, const std::vector<Vector2>& footprint1, Vector2& obst1, Vector2& obst2){
00079     VO result;
00080 
00081     Vector2 position_obst = 0.5 * (obst1 + obst2);
00082     
00083     std::vector<Vector2> obst;
00084     obst.push_back(obst1 - position_obst);
00085     obst.push_back(obst2 - position_obst);
00086     
00087     std::vector<Vector2> mink_sum = minkowskiSum(footprint1, obst);
00088 
00089     Vector2 min_left, min_right;
00090     double min_ang =  0.0;
00091     double max_ang = 0.0; 
00092     Vector2 rel_position = position_obst - position1;
00093     
00094     Vector2 rel_position_normal = normal(rel_position);
00095     double min_dist = abs(rel_position);
00096     
00097     for (int i = 0; i< (int) mink_sum.size(); i++){
00098       double angle = angleBetween(rel_position, rel_position + mink_sum[i]);
00099       if (rightOf(Vector2(0.0,0.0), rel_position, rel_position + mink_sum[i])) {
00100         if (-angle < min_ang) {
00101           min_right = rel_position + mink_sum[i];
00102           min_ang = -angle;
00103         }
00104       }
00105       else {
00106         if (angle > max_ang) {
00107           min_left = rel_position + mink_sum[i];
00108           max_ang = angle;
00109         }
00110       }
00111       Vector2 project_on_rel_position = intersectTwoLines(Vector2(0.0, 0.0), rel_position, rel_position + mink_sum[i], rel_position_normal);
00112       double dist = abs(project_on_rel_position);
00113       if (project_on_rel_position * rel_position < -EPSILON){
00114         //      ROS_ERROR("Collision?");
00115         dist = -dist;
00116         
00117       }
00118       
00119       if (dist < min_dist) {
00120         min_dist = dist;
00121       }
00122     }
00123     if (min_dist < 0) {
00124       result.left_leg_dir = -normalize(obst1 - obst2);
00125       result.right_leg_dir = - result.left_leg_dir;
00126       
00127       result.point = rel_position - 1.5 * radius1 * normal(result.left_leg_dir);
00128       result.trunc_left = result.point;
00129       result.trunc_right = result.point;
00130       return result;
00131 
00132     }
00133 
00134     double ang_rel = atan2(rel_position.y(), rel_position.x());
00135     result.left_leg_dir = Vector2(cos(ang_rel + max_ang), sin(ang_rel + max_ang));
00136     result.right_leg_dir = Vector2(cos(ang_rel + min_ang), sin(ang_rel + min_ang));
00137 
00138     result.left_leg_dir = rotateVectorByAngle(result.left_leg_dir, 0.15);
00139     result.right_leg_dir = rotateVectorByAngle(result.right_leg_dir, -0.05);
00140     
00141     
00142     //double ang_between = angleBetween(result.right_leg_dir, result.left_leg_dir);
00143     //double opening_ang = ang_rel + min_ang + (ang_between) / 2.0;
00144     
00145     // Vector2 dir_center = Vector2(cos(opening_ang), sin(opening_ang));
00146     // min_dist = abs(rel_position);
00147     // Vector2 min_point = rel_position;
00148     // for(int i = 0; i< (int)mink_sum.size(); i++) {
00149     //   Vector2 proj_on_center = intersectTwoLines(Vector2(0.0,0.0), dir_center, rel_position+mink_sum[i], normal(dir_center));
00150     //   if (abs(proj_on_center) < min_dist) {
00151     //  min_dist = abs(proj_on_center);
00152     //  min_point = rel_position+mink_sum[i];
00153     //   }
00154       
00155     // }
00156 
00157     //result.left_leg_dir = rotateVectorByAngle(normalize(min), 0.1);
00158     //result.right_leg_dir = rotateVectorByAngle(normalize(max), -0.1);
00159 
00160     result.relative_position = rel_position;
00161     result.combined_radius = abs(rel_position) - min_dist;
00162     result.point = Vector2(0,0);
00163 
00164     result.trunc_left = intersectTwoLines(result.point, result.left_leg_dir, result.combined_radius / 2.0 * normalize(rel_position), obst2 - obst1);
00165     result.trunc_right = intersectTwoLines(result.point, result.right_leg_dir, result.combined_radius / 2.0 * normalize(rel_position), obst2 - obst1);
00166     
00167     //result = createTruncVO(result, 6.0);
00168     return result;
00169    
00170   }
00171   
00172   // VO createObstacleVO(Vector2& position1, double radius1,Vector2& vel1,  Vector2& position2, double radius2){
00173   //   VO result;
00174 
00175   //   Vector2 rel_position = position2 - position1;
00176 
00177   //   Vector2 rel_position_normal = normal(rel_position);
00178 
00179   //   result.left_leg_dir = - normalize(rel_position_normal);
00180   //   result.right_leg_dir = - result.left_leg_dir;
00181   //   result.relative_position = rel_position;
00182   //   result.combined_radius = radius1 + radius2;
00183     
00184   //   result.point = normalize(rel_position) * (abs(rel_position) - result.combined_radius); // * std::max(1 - abs(vel1), 0.0);
00185   //   result.trunc_left = result.point;
00186   //   result.trunc_right = result.point;
00187   //   result.trunc_line_center = result.point;
00188 
00189   //   return result;
00190     
00191   // }
00192 
00193   
00194   VO createVO(Vector2& position1, const std::vector<Vector2>& footprint1, Vector2& position2, const std::vector<Vector2>& footprint2, Vector2& vel2){
00195     VO result;
00196     std::vector<Vector2> mink_sum = minkowskiSum(footprint1, footprint2);
00197 
00198     Vector2 min_left, min_right;
00199     double min_ang =  0.0;
00200     double max_ang = 0.0; 
00201     Vector2 rel_position = position2 - position1;
00202 
00203     Vector2 rel_position_normal = normal(rel_position);
00204     double min_dist = abs(rel_position);
00205     
00206     for (int i = 0; i< (int) mink_sum.size(); i++){
00207       double angle = angleBetween(rel_position, rel_position + mink_sum[i]);
00208       if (rightOf(Vector2(0.0,0.0), rel_position, rel_position + mink_sum[i])) {
00209         if (-angle < min_ang) {
00210           min_right = rel_position + mink_sum[i];
00211           min_ang = -angle;
00212         }
00213       }
00214       else {
00215         if (angle > max_ang) {
00216           min_left = rel_position + mink_sum[i];
00217           max_ang = angle;
00218         }
00219       }
00220       Vector2 project_on_rel_position = intersectTwoLines(Vector2(0.0, 0.0), rel_position, rel_position + mink_sum[i], rel_position_normal);
00221       double dist = abs(project_on_rel_position);
00222       if (project_on_rel_position * rel_position < -EPSILON){
00223         //      ROS_ERROR("Collision?");
00224         dist = -dist;
00225         
00226       }
00227       
00228       if (dist < min_dist) {
00229         min_dist = dist;
00230       }
00231     }
00232     if (min_dist < 0) {
00233       result.left_leg_dir = - normalize(rel_position_normal);
00234       result.right_leg_dir = - result.left_leg_dir;
00235       result.relative_position = rel_position;
00236       result.combined_radius = abs(rel_position) - min_dist;
00237       result.point = vel2;
00238       return result;
00239     }
00240     
00241     double ang_rel = atan2(rel_position.y(), rel_position.x());
00242     result.left_leg_dir = Vector2(cos(ang_rel + max_ang), sin(ang_rel + max_ang));
00243     result.right_leg_dir = Vector2(cos(ang_rel + min_ang), sin(ang_rel + min_ang));
00244 
00245     result.left_leg_dir = rotateVectorByAngle(result.left_leg_dir, 0.15);
00246     result.right_leg_dir = rotateVectorByAngle(result.right_leg_dir, -0.05);
00247 
00248     
00249     double ang_between = angleBetween(result.right_leg_dir, result.left_leg_dir);
00250     double opening_ang = ang_rel + min_ang + (ang_between) / 2.0;
00251 
00252     Vector2 dir_center = Vector2(cos(opening_ang), sin(opening_ang));
00253     min_dist = abs(rel_position);
00254     Vector2 min_point = rel_position;
00255     for(int i = 0; i< (int)mink_sum.size(); i++) {
00256       Vector2 proj_on_center = intersectTwoLines(Vector2(0.0,0.0), dir_center, rel_position+mink_sum[i], normal(dir_center));
00257       if (abs(proj_on_center) < min_dist) {
00258         min_dist = abs(proj_on_center);
00259         min_point = rel_position+mink_sum[i];
00260       }
00261      
00262     }
00263 
00264     //ROS_ERROR("min_right %f, %f, min_left %f,%f,", min_right.x(), min_right.y(), min_left.x(), min_left.y());
00265     double center_p, radius;
00266     Vector2 center_r;
00267     //test left/right
00268     if ( abs(min_left) < abs(min_right)) {
00269       center_p = abs(min_left) / cos(ang_between / 2.0);
00270       radius = tan(ang_between/2.0) * abs(min_left);
00271       center_r = center_p * dir_center;
00272     }
00273     else {
00274       center_p = abs(min_right) / cos(ang_between / 2.0);
00275       center_r = center_p * dir_center;
00276       radius = tan(ang_between/2.0) * abs(min_right);
00277     }
00278     //check min_point, if failed stupid calc for new radius and point;
00279     if (abs(min_point - center_r) > radius) {
00280       double gamma = min_point.x() * dir_center.x() + min_point.y() * dir_center.y();
00281       double sqrt_exp = absSqr(min_point) / (sqr(sin(ang_between/2.0)) -1) + sqr(gamma/(sqr(sin(ang_between/2.0)) - 1) );
00282       if (fabs(sqrt_exp)<EPSILON) {
00283         sqrt_exp =0;
00284       }
00285       if (sqrt_exp >= 0) {
00286         center_p = - gamma / (sqr(sin(ang_between/2.0)) -1) + std::sqrt(sqrt_exp);
00287         center_r = center_p * dir_center;
00288         radius = abs(min_point - center_r);
00289       }
00290       else {
00291         ROS_ERROR("ang = %f, sqrt_ext = %f", ang_between, sqrt_exp);
00292         ROS_ERROR("rel position %f, %f, radius %f, center_p %f", rel_position.x(), rel_position.y(), radius, center_p);
00293       }
00294     }
00295     //result.relative_position = rel_position;
00296     //result.combined_radius = abs(rel_position) - min_dist;
00297   
00298     result.relative_position = center_r;
00299     result.combined_radius = radius;
00300     result.point = vel2;
00301     return result;
00302     
00303   }
00304 
00305 
00306   
00307   VO createRVO(Vector2& position1, const std::vector<Vector2>& footprint1, Vector2& vel1, Vector2& position2, const std::vector<Vector2>& footprint2, Vector2& vel2){
00308     VO result = createVO(position1, footprint1, position2, footprint2, vel2);
00309     result.point = 0.5 * (vel1 + vel2); //TODO add uncertainty
00310     return result;
00311    
00312 
00313   }
00314 
00315   VO createHRVO(Vector2& position1, const std::vector<Vector2>& footprint1, Vector2& vel1, Vector2& position2, const std::vector<Vector2>& footprint2, Vector2& vel2){
00316     //std::vector<Vector2> mink_sum = minkowskiSum(footprint1, footprint2);
00317     //std::vector<Vector2> empty;
00318     VO result = createRVO(position1, footprint1,vel1, position2, footprint2, vel2);
00319 
00320 
00321     Vector2 rel_velocity = vel1 - vel2;
00322     // Vector2 rel_position = position2 - position1;
00323 
00324     // //Test if origin is inside mink_sum (Then we are in collision)!!!)
00325     // bool inside = true;
00326     // for (int i = 0; i<(int)mink_sum.size(); i++){
00327     //   int j = i+1;
00328     //   if (j == (int) mink_sum.size())
00329     //  j = 0;
00330     //   if (leftOf(rel_position + mink_sum[i], mink_sum[j]-mink_sum[i], Vector2(0.0,0.0))) {
00331     //  inside = false;
00332         
00333     //  break;
00334     //   }
00335     // }
00336     // Vector2 new_position = position1;
00337     // int max_tries = 0;
00338     // while (result.combined_radius > abs(result.relative_position) && max_tries > 0) {
00339     //   //      ROS_ERROR("inside minkowskiSum!!");
00340     //   new_position = new_position - normalize(result.relative_position) * 0.1;
00341     //   //result = createRVO(new_position, footprint1,vel1, position2, footprint2, vel2);
00342     //   max_tries--;
00343     // }
00344     if (result.combined_radius > abs(result.relative_position)) {
00345       //ROS_ERROR("comb.rad. %f, relPos %f, %f (abs = %f)", result.combined_radius, result.relative_position.x(), result.relative_position.y(), abs(result.relative_position));
00346       //result.point = 0.5 * (vel2 + vel1) -  ((result.combined_radius - abs(result.relative_position)) / (2.0f * 0.1)) * normalize(result.relative_position);
00347       return result;
00348   
00349     }
00350       
00351     if (leftOf(Vector2(0.0, 0.0), result.relative_position, rel_velocity)) { //left of centerline
00352       result.point = intersectTwoLines(result.point, result.left_leg_dir, vel2, result.right_leg_dir); // TODO add uncertainty
00353       
00354     }
00355     else{ //right of centerline
00356       result.point = intersectTwoLines(vel2,result.left_leg_dir, result.point, result.right_leg_dir); // TODO add uncertainty
00357     }
00358     
00359     return result;
00360    
00361 
00362   }
00363   
00364 
00365   VO createVO(Vector2& position1, const std::vector<Vector2>& footprint1, Vector2& vel1, Vector2& position2, const std::vector<Vector2>& footprint2, Vector2& vel2, int TYPE) {
00366     if (TYPE == HRVOS) {
00367       return createHRVO(position1, footprint1, vel1, position2, footprint2, vel2);
00368     }
00369     else if (TYPE == RVOS) {
00370       return createRVO(position1, footprint1, vel1, position2, footprint2, vel2);
00371     } 
00372     else{
00373       return createVO(position1, footprint1, position2, footprint2, vel2);
00374     }
00375   }
00376 
00377   
00378   VO createVO(Vector2& position1, double radius1, Vector2& vel1, Vector2& position2, double radius2, Vector2& vel2, int TYPE) {
00379     if(TYPE == HRVOS) {
00380       return createHRVO(position1, radius1, vel1, position2, radius2, vel2);
00381     }
00382     else if(TYPE == RVOS) {
00383       return createRVO(position1, radius1, vel1, position2, radius2, vel2);
00384     } 
00385     else {
00386       return createVO(position1, radius1, position2, radius2, vel2);
00387     }
00388   }
00389 
00390   
00391   VO createVO(Vector2& position1, double radius1, Vector2& position2, double radius2, Vector2& vel2) {
00392     VO result;
00393     Vector2 rel_position = position2 - position1;
00394     double ang_to_other = atan (rel_position);
00395     double combined_radius = radius2+radius1;
00396     double angle_of_opening;
00397     if (abs(rel_position) < combined_radius) {
00398       // angle_of_opening = M_PI/2.0-EPSILON;
00399       result.left_leg_dir = - normalize(normal(rel_position));
00400       result.right_leg_dir = - result.left_leg_dir;
00401       // result.right_leg_dir = Vector2(std::cos(ang_to_other - angle_of_opening), std::sin(ang_to_other - angle_of_opening));
00402       // result.left_leg_dir = Vector2(std::cos(ang_to_other + angle_of_opening), std::sin(ang_to_other + angle_of_opening));
00403     }
00404     else {
00405       angle_of_opening = std::asin(combined_radius / abs(rel_position));
00406       result.right_leg_dir = Vector2(std::cos(ang_to_other - angle_of_opening), std::sin(ang_to_other - angle_of_opening));
00407       result.left_leg_dir = Vector2(std::cos(ang_to_other + angle_of_opening), std::sin(ang_to_other + angle_of_opening));
00408     }
00409     //    ROS_ERROR("angle_of_opening %f, combined_radius %f, rel_position %f", angle_of_opening, combined_radius, abs(rel_position));
00410     result.point = vel2;
00411     result.relative_position = rel_position;
00412     result.combined_radius = radius1 + radius2;
00413   
00414     return result;
00415   }
00416 
00417   VO createRVO(Vector2& position1, double radius1, Vector2& vel1, Vector2& position2, double radius2, Vector2& vel2) {
00418     VO result = createVO(position1, radius1, position2, radius2, vel2);
00419     result.point = 0.5 * (vel1 + vel2); //TODO add uncertainty
00420     return result;
00421   }
00422 
00423   VO createHRVO(Vector2& position1, double radius1, Vector2& vel1, Vector2& position2, double radius2, Vector2& vel2){
00424 
00425     VO result = createRVO(position1, radius1, vel1, position2, radius2, vel2);
00426 
00427     Vector2 rel_velocity = vel1 - vel2;
00428     Vector2 rel_position = position2 - position1;
00429     if (abs(rel_position) < radius1 + radius2){
00430       result.point = 0.5 * (vel2 + vel1);
00431       return result;
00432     }
00433       
00434     if (leftOf(Vector2(0.0, 0.0), rel_position, rel_velocity)) { //left of centerline
00435       result.point = intersectTwoLines(result.point, result.left_leg_dir, vel2, result.right_leg_dir); // TODO add uncertainty
00436     }
00437     else{ //right of centerline
00438       result.point = intersectTwoLines(vel2,result.left_leg_dir, result.point, result.right_leg_dir); // TODO add uncertainty
00439     }
00440     return result;
00441     
00442   }
00443   
00444   VO createTruncVO (VO& vo, double time) {
00445     VO result;
00446     result.point = vo.point;
00447     result.left_leg_dir = vo.left_leg_dir;
00448     result.right_leg_dir = vo.right_leg_dir;
00449     result.relative_position = vo.relative_position;
00450     result.combined_radius = vo.combined_radius;
00451     double trunc_radius = vo.combined_radius / time;
00452     double angle_of_opening;
00453     
00454     if (abs(vo.relative_position) < vo.combined_radius) {
00455       result.trunc_left = result.point;
00456       result.trunc_right = result.point;
00457       result.trunc_line_center = result.point;
00458       return result;
00459     }
00460     else {
00461       angle_of_opening = std::asin(vo.combined_radius / abs(vo.relative_position));
00462       double trunc_dist = trunc_radius / std::sin(angle_of_opening) - trunc_radius;
00463       result.trunc_line_center = normalize(vo.relative_position) * trunc_dist;
00464       Vector2 intersectLeft = intersectTwoLines(result.point + result.trunc_line_center, Vector2(result.trunc_line_center.y(), - result.trunc_line_center.x()), result.point, result.left_leg_dir);
00465       result.trunc_left = intersectLeft;
00466       result.trunc_right = intersectTwoLines(result.point + result.trunc_line_center, Vector2(result.trunc_line_center.y(), - result.trunc_line_center.x()), result.point, result.right_leg_dir);
00467 
00468       return result;
00469     }
00470   }
00471 
00472   bool isInsideVO(VO vo, Vector2 point, bool use_truncation) {
00473     bool trunc = leftOf(vo.trunc_left, vo.trunc_right - vo.trunc_left, point);
00474     if (abs(vo.trunc_left - vo.trunc_right) < EPSILON)
00475       trunc = true;
00476     return rightOf(vo.point, vo.left_leg_dir, point) && leftOf(vo.point, vo.right_leg_dir, point) && (!use_truncation || trunc);
00477   }
00478 
00479   bool isWithinAdditionalConstraints(const std::vector<Line>& additional_constraints, const Vector2& point) {
00480     BOOST_FOREACH(Line line, additional_constraints){
00481       if (rightOf(line.point, line.dir, point) ) {
00482         return false;
00483       }
00484     }
00485     return true;
00486   }
00487 
00488   
00489   void addCircleLineIntersections(std::vector<VelocitySample>& samples, const Vector2& pref_vel, double maxSpeed, bool use_truncation, const Vector2& point, const Vector2& dir){
00490 
00491     double discriminant = sqr(maxSpeed) - sqr(det(point, dir)); // http://stackoverflow.com/questions/1073336/circle-line-collision-detection
00492     if (discriminant > 0.0f) //intersection with line
00493       {
00494         double t1 = -(point * dir) + std::sqrt(discriminant); //first solution
00495         double t2 = -(point * dir) - std::sqrt(discriminant); //second solution
00496         //ROS_ERROR("Adding circle line dist %f, %f", t1, t2);
00497         Vector2 point1 = point + t1 * dir;
00498         Vector2 point2 = point + t2 * dir;
00499             
00500         if (t1 >= 0.0f) {
00501             VelocitySample intersection_point;
00502             intersection_point.velocity = point1;
00503             intersection_point.dist_to_pref_vel = absSqr(pref_vel - intersection_point.velocity);
00504             samples.push_back(intersection_point);
00505           }
00506         if (t2 >= 0.0f) {
00507             VelocitySample intersection_point;
00508             intersection_point.velocity = point2;
00509             intersection_point.dist_to_pref_vel = absSqr(pref_vel - intersection_point.velocity);
00510             samples.push_back(intersection_point);
00511           }
00512       }
00513   }
00514 
00515 
00516   void addRayVelocitySamples(std::vector<VelocitySample>& samples, const Vector2& pref_vel, Vector2 point1, Vector2 dir1, Vector2 point2, Vector2 dir2, double max_speed, int TYPE) {
00517     double r, s;
00518     
00519     double x1, x2, x3,x4, y1, y2,y3,y4;
00520     x1 = point1.x();
00521     y1 = point1.y();
00522     x2 = x1 + dir1.x();
00523     y2 = y1 + dir1.y();
00524     x3 = point2.x();
00525     y3 = point2.y();
00526     x4 = x3 + dir2.x();
00527     y4 = y3 + dir2.y();
00528     
00529     double det = (((x2 - x1) * (y4 - y3)) - (y2 - y1) * (x4 - x3));
00530     
00531     if (det == 0.0) {
00532       //ROS_WARN("No Intersection found");
00533       return;
00534     }
00535     if (det != 0){
00536       r = (((y1 - y3) * (x4 - x3)) - (x1 - x3) * (y4 - y3)) / det;
00537       s = (((y1 - y3) * (x2 - x1)) - (x1 - x3) * (y2 - y1)) / det;
00538 
00539       if ( (TYPE == LINELINE) || (TYPE == RAYLINE && r>=0 )  || (TYPE == SEGMENTLINE && r>= 0 && r <= 1) || (TYPE == RAYRAY && r>= 0 && s >= 0) ||
00540            (TYPE == RAYSEGMENT && r>=0 && s >= 0 && s <=1) || (TYPE==SEGMENTSEGMENT && r>=0 && s>=0 && r<=1 && s<=1)  ) {
00541         
00542         
00543         VelocitySample intersection_point;
00544         intersection_point.velocity = Vector2(x1 + r * (x2 - x1), y1 + r * (y2 - y1));
00545         intersection_point.dist_to_pref_vel = absSqr(pref_vel - intersection_point.velocity);
00546         if (absSqr(intersection_point.velocity) < sqr(1.2*max_speed)){
00547           //ROS_ERROR("adding VelocitySample");
00548           samples.push_back(intersection_point);
00549           //ROS_ERROR("size of VelocitySamples %d", (int) samples->size());
00550           
00551         }
00552       }
00553     }   
00554   }
00555   
00556 
00557 
00558   void createSamplesWithinMovementConstraints(std::vector<VelocitySample>& samples, double  cur_vel_x, double cur_vel_y, double cur_vel_theta,  double acc_lim_x, double acc_lim_y, double acc_lim_theta, double min_vel_x, double max_vel_x, double min_vel_y, double max_vel_y, double min_vel_theta, double max_vel_theta, double heading, Vector2 pref_vel, double sim_period, int num_samples, bool holo_robot){
00559 
00560     if (holo_robot) {//holonomic drive
00561        double min_x, max_x, min_y, max_y;
00562 
00563        min_x = std::max(-max_vel_x, cur_vel_x - acc_lim_x * sim_period);
00564        max_x = std::min(max_vel_x, cur_vel_x + acc_lim_x * sim_period);
00565               
00566        min_y = std::max(-max_vel_y, cur_vel_y - acc_lim_y * sim_period);
00567        max_y = std::min(max_vel_y, cur_vel_y + acc_lim_y * sim_period);
00568        
00569        double step_x, step_y;
00570        
00571        int num_samples_per_dir = (int )std::sqrt(num_samples);
00572 
00573        step_x = (max_x - min_x) / num_samples_per_dir;
00574        step_y = (max_y - min_y) / num_samples_per_dir;
00575          
00576       for (int i = 0; i < num_samples_per_dir; i++) {
00577         for (int j = 0; j < num_samples_per_dir; j++) {
00578           VelocitySample p;
00579           Vector2 vel = Vector2(min_x + i* step_x, min_y + j * step_y);
00580           p.dist_to_pref_vel = absSqr(vel - Vector2(cur_vel_x, cur_vel_y));
00581           p.velocity = rotateVectorByAngle(Vector2(min_x + i* step_x, min_y + j * step_y), heading);
00582           samples.push_back(p);
00583         }
00584 
00585       }
00586       
00587     }
00588     else {
00589       double min_x, max_x, min_theta, max_theta;
00590       
00591       min_x = -0.3;//std::max(-0.2, cur_vel_x - acc_lim_x * sim_period);
00592       max_x = std::min(max_vel_x, cur_vel_x + acc_lim_x * sim_period);
00593 
00594       //cur_vel_theta = 0.0; //HACK
00595 
00596       min_theta = -2*max_vel_theta;//std::max(-max_vel_theta, cur_vel_theta - acc_lim_theta * sim_period);
00597       max_theta = 2*max_vel_theta;//std::min(max_vel_theta, cur_vel_theta + acc_lim_theta * sim_period);
00598 
00599       double step_x, step_theta;
00600 
00601       int num_samples_per_dir = (int )std::sqrt(num_samples);
00602       
00603       step_x = (max_x - min_x) / num_samples_per_dir;
00604       step_theta = (max_theta - min_theta) / num_samples_per_dir;
00605 
00606       // ROS_ERROR("heading %f, min_theta %f, %f cur_vel_theta %f", heading, min_theta, max_theta, cur_vel_theta);
00607    
00608       for (int i = 0; i < num_samples_per_dir; i++) {
00609         for (int j = 0; j < num_samples_per_dir; j++) {
00610           VelocitySample p;
00611           double th_dif =  min_theta + j*step_theta;
00612           double x_dif = (min_x + i * step_x) * cos(heading + th_dif/2.0);
00613           double y_dif = (min_x + i * step_x) * sin(heading + th_dif/2.0);
00614           p.dist_to_pref_vel = absSqr(Vector2(cur_vel_x, cur_vel_y));
00615 
00616           p.velocity = Vector2(x_dif,y_dif);
00617           //p.velocity = rotateVectorByAngle(Vector2(min_x + i* step_x, 0), heading + min_theta + j * step_theta);
00618           
00619           samples.push_back(p);
00620         } 
00621         
00622       }
00623     }
00624 
00625   }
00626 
00627   Vector2 calculateNewVelocitySampled(std::vector<VelocitySample>& samples, const std::vector<VO>& truncated_vos, const Vector2& pref_vel,double max_speed, bool use_truncation) {
00628         
00629     // VelocitySample pref_vel_sample;
00630     // pref_vel_sample.velocity = pref_vel;
00631     // samples.push_back(pref_vel_sample);
00632 
00633     
00634     // VelocitySample null_vel;
00635     // null_vel.velocity = Vector2(0,0);
00636     // null_vel.dist_to_pref_vel = absSqr(pref_vel);
00637     // samples.push_back(null_vel);
00638 
00639     double min_cost = DBL_MAX;
00640     Vector2 best_vel;
00641     
00642     for(int i = 0; i < (int) samples.size(); i++){
00643       VelocitySample cur = samples[i];
00644       double cost = calculateVelCosts(cur.velocity, truncated_vos, pref_vel, max_speed, use_truncation);
00645       cost += cur.dist_to_pref_vel;
00646       if (cost < min_cost) {
00647         min_cost = cost;
00648         best_vel = cur.velocity;
00649       }
00650     }
00651     //ROS_ERROR("min_cost %f", min_cost);
00652     return best_vel;
00653   }
00654 
00655   double calculateVelCosts(const Vector2& test_vel, const std::vector<VO>& truncated_vos, const Vector2& pref_vel, double max_speed, bool use_truncation) {
00656     double cost = 0.0;
00657     double COST_IN_VO = 1000.0;
00658     for (int j = 0; j < (int) truncated_vos.size(); j++) {
00659       if (isInsideVO(truncated_vos[j], test_vel, use_truncation)) {
00660         cost += (truncated_vos.size() - j) * COST_IN_VO;
00661       }
00662     }
00663     cost += absSqr(pref_vel - test_vel);
00664     return cost;
00665   }
00666     
00667  
00668 
00669   Vector2 calculateClearpathVelocity(std::vector<VelocitySample>& samples, const std::vector<VO>& truncated_vos, const std::vector<Line>& additional_constraints, const Vector2& pref_vel, double max_speed, bool use_truncation) {
00670     
00671     if (!isWithinAdditionalConstraints(additional_constraints, pref_vel)) {
00672       BOOST_FOREACH (Line line, additional_constraints) {
00673         VelocitySample pref_vel_sample;
00674         pref_vel_sample.velocity = intersectTwoLines(line.point, line.dir, pref_vel, Vector2(line.dir.y(), -line.dir.x()));
00675         pref_vel_sample.dist_to_pref_vel = absSqr(pref_vel - pref_vel_sample.velocity);
00676         samples.push_back(pref_vel_sample);
00677       }
00678     }
00679     else {
00680       VelocitySample pref_vel_sample;
00681       pref_vel_sample.velocity = pref_vel;
00682       pref_vel_sample.dist_to_pref_vel = 0;
00683       samples.push_back(pref_vel_sample);
00684     }
00685     VelocitySample null_vel_sample;
00686     null_vel_sample.velocity = Vector2(0,0);
00687     null_vel_sample.dist_to_pref_vel = absSqr(pref_vel);
00688     samples.push_back(null_vel_sample);
00689 
00690     BOOST_FOREACH(Line line, additional_constraints) {
00691       BOOST_FOREACH(Line line2, additional_constraints) {
00692         addRayVelocitySamples(samples, pref_vel, line.point, line.dir,line2.point, line2.dir, max_speed, LINELINE);
00693       }
00694     }
00695     
00696     for (int i= 0 ; i< (int) truncated_vos.size(); i++){
00697       if (isInsideVO(truncated_vos[i], pref_vel, use_truncation)){
00698 
00699         VelocitySample leg_projection;
00700         if (leftOf(truncated_vos[i].point, truncated_vos[i].relative_position, pref_vel)){ //left of centerline, project on left leg
00701           leg_projection.velocity = intersectTwoLines(truncated_vos[i].point, truncated_vos[i].left_leg_dir, pref_vel, Vector2(truncated_vos[i].left_leg_dir.y(), -truncated_vos[i].left_leg_dir.x()));
00702         }
00703         else { //project on right leg
00704           leg_projection.velocity = intersectTwoLines(truncated_vos[i].point, truncated_vos[i].right_leg_dir, pref_vel, Vector2(truncated_vos[i].right_leg_dir.y(), -truncated_vos[i].right_leg_dir.x()));
00705         }
00706 
00707         //if(absSqr(leg_projection.velocity) < max_speed) { //only add if below max_speed
00708         leg_projection.dist_to_pref_vel = absSqr(pref_vel- leg_projection.velocity);
00709         samples.push_back(leg_projection);
00710         //}
00711         
00712         if (use_truncation) { 
00713           addRayVelocitySamples(samples, pref_vel, pref_vel, -truncated_vos[i].relative_position, truncated_vos[i].trunc_left, truncated_vos[i].trunc_right - truncated_vos[i].trunc_left, max_speed, RAYSEGMENT);
00714         }
00715       }
00716     }
00717 
00718     // for (int i= 0 ; i< (int) truncated_vos.size(); i++){ //intersect with max_speed circle
00719     //   if (!use_truncation) {
00720     //  addCircleLineIntersections(samples, pref_vel, max_speed, use_truncation, truncated_vos[i].point, truncated_vos[i].left_leg_dir); //intersect with left leg_dir
00721     //  addCircleLineIntersections(samples, pref_vel, max_speed, use_truncation, truncated_vos[i].point, truncated_vos[i].right_leg_dir); //intersect with right_leg_dir
00722     //   }
00723     //   else {
00724     //  addCircleLineIntersections(samples, pref_vel, max_speed, use_truncation, truncated_vos[i].trunc_left, truncated_vos[i].left_leg_dir); //intersect with left leg_dir
00725     //  addCircleLineIntersections(samples, pref_vel, max_speed, use_truncation, truncated_vos[i].trunc_right, truncated_vos[i].right_leg_dir); //intersect with right_leg_dir
00726 
00727     //          //addCircleLineIntersections(samples, pref_vel, max_speed, use_truncation, truncated_vos[i].trunc_left, truncated_vos[i].trunc_right - truncated_vos[i].trunc_left, i, truncated_vos[i]); //intersect with truncation line
00728     //   }
00729     // }
00730 
00731     for (int i= 0 ; i< (int) truncated_vos.size(); i++){
00732       for (int j = 0; j<(int) additional_constraints.size(); j++){
00733         if(!use_truncation) {
00734           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].point, truncated_vos[i].left_leg_dir, additional_constraints[j].point, additional_constraints[j].dir, max_speed, RAYLINE);
00735           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].point, truncated_vos[i].right_leg_dir, additional_constraints[j].point, additional_constraints[j].dir, max_speed, RAYLINE);
00736         }
00737         else {
00738           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].trunc_left, truncated_vos[i].left_leg_dir, additional_constraints[j].point, additional_constraints[j].dir, max_speed, RAYLINE);
00739           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].trunc_right, truncated_vos[i].right_leg_dir, additional_constraints[j].point, additional_constraints[j].dir, max_speed, RAYLINE);
00740           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].trunc_left, truncated_vos[i].trunc_right - truncated_vos[i].trunc_left, additional_constraints[j].point, additional_constraints[j].dir, max_speed, SEGMENTLINE);
00741         }
00742       }
00743       
00744       for (int j = i+1; j < (int) truncated_vos.size(); j++){
00745 
00746         if (!use_truncation) {
00747           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].point, truncated_vos[i].left_leg_dir, truncated_vos[j].point, truncated_vos[j].left_leg_dir, max_speed, RAYRAY);
00748           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].point, truncated_vos[i].left_leg_dir, truncated_vos[j].point, truncated_vos[j].right_leg_dir, max_speed, RAYRAY);
00749           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].point, truncated_vos[i].right_leg_dir, truncated_vos[j].point, truncated_vos[j].left_leg_dir, max_speed, RAYRAY);
00750           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].point, truncated_vos[i].right_leg_dir, truncated_vos[j].point, truncated_vos[j].right_leg_dir, max_speed, RAYRAY);
00751           
00752         }
00753         else {
00754           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].trunc_left, truncated_vos[i].left_leg_dir, truncated_vos[j].trunc_left, truncated_vos[j].left_leg_dir, max_speed, RAYRAY);
00755           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].trunc_left, truncated_vos[i].left_leg_dir, truncated_vos[j].trunc_right, truncated_vos[j].right_leg_dir, max_speed, RAYRAY);
00756           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].trunc_right, truncated_vos[i].right_leg_dir, truncated_vos[j].trunc_left, truncated_vos[j].left_leg_dir, max_speed, RAYRAY);
00757           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].trunc_right, truncated_vos[i].right_leg_dir, truncated_vos[j].trunc_left, truncated_vos[j].right_leg_dir, max_speed, RAYRAY);
00758 
00759 
00760           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].trunc_left, truncated_vos[i].left_leg_dir, truncated_vos[j].trunc_left, truncated_vos[j].trunc_right - truncated_vos[j].trunc_left, max_speed, RAYSEGMENT); //left trunc
00761           addRayVelocitySamples(samples, pref_vel, truncated_vos[j].trunc_left, truncated_vos[j].left_leg_dir, truncated_vos[i].trunc_left, truncated_vos[i].trunc_right - truncated_vos[i].trunc_left, max_speed, RAYSEGMENT); //trunc left
00762           
00763           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].trunc_right, truncated_vos[i].right_leg_dir, truncated_vos[j].trunc_left, truncated_vos[j].trunc_right - truncated_vos[j].trunc_left, max_speed, RAYSEGMENT); //right trunc
00764           addRayVelocitySamples(samples, pref_vel, truncated_vos[j].trunc_right, truncated_vos[j].right_leg_dir, truncated_vos[i].trunc_left, truncated_vos[i].trunc_right - truncated_vos[i].trunc_left, max_speed, RAYSEGMENT); //trunc right
00765 
00766           addRayVelocitySamples(samples, pref_vel, truncated_vos[i].trunc_left, truncated_vos[i].trunc_right - truncated_vos[i].trunc_left, truncated_vos[j].trunc_left, truncated_vos[j].trunc_right - truncated_vos[j].trunc_left, max_speed, SEGMENTSEGMENT); //trunc trunc
00767           
00768   
00769         }
00770         
00771       }
00772     }
00773     
00774 
00775     //    ROS_ERROR("projection list length  = %d", samples.size());
00776 
00777     std::sort(samples.begin(), samples.end(), compareVelocitySamples);
00778 
00779     Vector2 new_vel; // = pref_vel;
00780 
00781     bool valid = false;
00782     bool foundOutside = false;
00783     bool outside = true;
00784     int optimal = -1;
00785     
00786     for (int i = 0; i < (int) samples.size(); i++) {
00787       outside = true;
00788       valid = true;
00789       if (!isWithinAdditionalConstraints(additional_constraints, samples[i].velocity) ) {
00790         outside = false;
00791       }
00792 
00793       
00794       for (int j = 0; j < (int) truncated_vos.size(); j++) {
00795         if (isInsideVO(truncated_vos[j], samples[i].velocity, use_truncation)) {
00796           valid = false;
00797           if (j> optimal) {
00798             optimal = j;
00799             new_vel = samples[i].velocity;
00800           }
00801           break;
00802         }
00803       }
00804       if (valid && outside){
00805         return samples[i].velocity;
00806       }
00807       if (valid && !outside && !foundOutside) {
00808         optimal = truncated_vos.size();
00809         new_vel = samples[i].velocity;
00810         foundOutside = true;    
00811       }
00812       
00813     }
00814     //    ROS_INFO("selected j %d, of size %d", optimal, (int) truncated_vos.size()); 
00815 
00816     
00817     return new_vel;
00818   }
00819 
00820 
00821   std::vector<Vector2> minkowskiSum(const std::vector<Vector2> polygon1, const std::vector<Vector2> polygon2){
00822     std::vector<Vector2> result;
00823     std::vector<ConvexHullPoint> convex_hull;
00824 
00825     
00826     for (int i = 0; i < (int) polygon1.size(); i++) {
00827       for (int j = 0; j < (int) polygon2.size(); j++) {
00828         ConvexHullPoint p;
00829         p.point = polygon1[i] + polygon2[j];
00830         convex_hull.push_back(p);
00831       }
00832       
00833     }
00834     convex_hull = convexHull(convex_hull,false);
00835     for (int i = 0; i<(int)convex_hull.size(); i++) {
00836       result.push_back(convex_hull[i].point);
00837     }
00838     return result;
00839 
00840   }
00841 
00842   
00843   bool compareVectorsLexigraphically(const ConvexHullPoint & v1, const ConvexHullPoint & v2){
00844     return  v1.point.x() < v2.point.x() || (v1.point.x() == v2.point.x() && v1.point.y() < v2.point.y());
00845   }
00846 
00847   double cross(const ConvexHullPoint & O, const ConvexHullPoint & A, const ConvexHullPoint & B){
00848     return (A.point.x() - O.point.x()) * (B.point.y() - O.point.y()) - (A.point.y() - O.point.y()) * (B.point.x() - O.point.x());
00849   }
00850 
00851   // Returns a list of points on the convex hull in counter-clockwise order.
00852   // Note: the last point in the returned list is the same as the first one.
00853   //Wikipedia Monotone chain...
00854   std::vector<ConvexHullPoint > convexHull(std::vector<ConvexHullPoint > P, bool sorted)
00855   {
00856     int n = P.size(), k = 0;
00857     std::vector<ConvexHullPoint > result(2*n);
00858 
00859     // Sort points lexicographically
00860     if (!sorted)
00861       sort(P.begin(), P.end(), compareVectorsLexigraphically);
00862     
00863     //    ROS_WARN("points length %d", (int)P.size());
00864 
00865     // Build lower hull
00866     for (int i = 0; i < n; i++) {
00867       while (k >= 2 && cross(result[k-2], result[k-1], P[i]) <= 0) k--;
00868       result[k++] = P[i];
00869     }
00870 
00871     // Build upper hull
00872     for (int i = n-2, t = k+1; i >= 0; i--) {
00873       while (k >= t && cross(result[k-2], result[k-1], P[i]) <= 0) k--;
00874       result[k++] = P[i];
00875     }
00876     result.resize(k);
00877     
00878     return result;
00879   }
00880   
00881 
00882 
00883   bool compareVelocitySamples(const VelocitySample& p1, const VelocitySample& p2){
00884     return p1.dist_to_pref_vel < p2.dist_to_pref_vel;
00885   }
00886   
00887   Vector2 intersectTwoLines(Vector2 point1, Vector2 dir1, Vector2 point2, Vector2 dir2) {
00888     double x1, x2, x3,x4, y1, y2,y3,y4;
00889     x1 = point1.x();
00890     y1 = point1.y();
00891     x2 = x1 + dir1.x();
00892     y2 = y1 + dir1.y();
00893     x3 = point2.x();
00894     y3 = point2.y();
00895     x4 = x3 + dir2.x();
00896     y4 = y3 + dir2.y();
00897     
00898     double det = (x1-x2)*(y3-y4) - (y1-y2)*(x3-x4);
00899 
00900     if (det == 0) {
00901       return Vector2(0,0); //TODO fix return NULL
00902       
00903     }
00904     double x_i = ( (x3-x4) * (x1*y2-y1*x2) - (x1-x2) * (x3*y4-y3*x4)) / det;
00905     double y_i = ( (y3-y4) * (x1*y2-y1*x2) - (y1-y2) * (x3*y4-y3*x4)) / det;
00906     
00907     return Vector2(x_i, y_i);
00908  }
00909  
00910  Vector2 intersectTwoLines(Line line1, Line line2) {
00911     return intersectTwoLines(line1.point, line1.dir, line2.point,line2.dir);
00912   }
00913 
00914 
00915 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


collvoid_local_planner
Author(s): Daniel Claes
autogenerated on Sun Aug 25 2013 10:10:23