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 }