00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
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   
00040   
00041   
00042 
00043   
00044 
00045   
00046   
00047     
00048   
00049   
00050   
00051   
00052   
00053   
00054         
00055   
00056       
00057   
00058   
00059   
00060   
00061   
00062   
00063   
00064   
00065     
00066   
00067   
00068   
00069   
00070 
00071   
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         
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     
00143     
00144     
00145     
00146     
00147     
00148     
00149     
00150     
00151     
00152     
00153     
00154       
00155     
00156 
00157     
00158     
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     
00168     return result;
00169    
00170   }
00171   
00172   
00173   
00174 
00175   
00176 
00177   
00178 
00179   
00180   
00181   
00182   
00183     
00184   
00185   
00186   
00187   
00188 
00189   
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         
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     
00265     double center_p, radius;
00266     Vector2 center_r;
00267     
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     
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     
00296     
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); 
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     
00317     
00318     VO result = createRVO(position1, footprint1,vel1, position2, footprint2, vel2);
00319 
00320 
00321     Vector2 rel_velocity = vel1 - vel2;
00322     
00323 
00324     
00325     
00326     
00327     
00328     
00329     
00330     
00331     
00332         
00333     
00334     
00335     
00336     
00337     
00338     
00339     
00340     
00341     
00342     
00343     
00344     if (result.combined_radius > abs(result.relative_position)) {
00345       
00346       
00347       return result;
00348   
00349     }
00350       
00351     if (leftOf(Vector2(0.0, 0.0), result.relative_position, rel_velocity)) { 
00352       result.point = intersectTwoLines(result.point, result.left_leg_dir, vel2, result.right_leg_dir); 
00353       
00354     }
00355     else{ 
00356       result.point = intersectTwoLines(vel2,result.left_leg_dir, result.point, result.right_leg_dir); 
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       
00399       result.left_leg_dir = - normalize(normal(rel_position));
00400       result.right_leg_dir = - result.left_leg_dir;
00401       
00402       
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     
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); 
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)) { 
00435       result.point = intersectTwoLines(result.point, result.left_leg_dir, vel2, result.right_leg_dir); 
00436     }
00437     else{ 
00438       result.point = intersectTwoLines(vel2,result.left_leg_dir, result.point, result.right_leg_dir); 
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)); 
00492     if (discriminant > 0.0f) 
00493       {
00494         double t1 = -(point * dir) + std::sqrt(discriminant); 
00495         double t2 = -(point * dir) - std::sqrt(discriminant); 
00496         
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       
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           
00548           samples.push_back(intersection_point);
00549           
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) {
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;
00592       max_x = std::min(max_vel_x, cur_vel_x + acc_lim_x * sim_period);
00593 
00594       
00595 
00596       min_theta = -2*max_vel_theta;
00597       max_theta = 2*max_vel_theta;
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       
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           
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     
00630     
00631     
00632 
00633     
00634     
00635     
00636     
00637     
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     
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)){ 
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 { 
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         
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     
00719     
00720     
00721     
00722     
00723     
00724     
00725     
00726 
00727     
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); 
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); 
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); 
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); 
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); 
00767           
00768   
00769         }
00770         
00771       }
00772     }
00773     
00774 
00775     
00776 
00777     std::sort(samples.begin(), samples.end(), compareVelocitySamples);
00778 
00779     Vector2 new_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     
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   
00852   
00853   
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     
00860     if (!sorted)
00861       sort(P.begin(), P.end(), compareVectorsLexigraphically);
00862     
00863     
00864 
00865     
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     
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); 
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 }