00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "navigator_internal.h"
00014 #include "obstacle.h"
00015 #include "Controller.h"
00016 #include "course.h"
00017 #include "parking.h"
00018 #include <art_map/rotate_translate_transform.h>
00019 #include <art/steering.h>
00020
00021 #include "safety.h"
00022 #include "stop.h"
00023 #include "halt.h"
00024
00025 int find_spot(const std::vector<WayPointNode> &new_waypts)
00026 {
00027 for (uint i=0; i < new_waypts.size()-1;i++)
00028 if (new_waypts[i].is_spot &&
00029 new_waypts[i+1].is_spot &&
00030 new_waypts[i].id.lane==
00031 new_waypts[i+1].id.lane)
00032 {
00033 return (int)i;
00034 }
00035 return -1;
00036 }
00037
00038 poly adjust_spot_and_return_poly(WayPointNode &p1,
00039 WayPointNode &p2,
00040 float dx,
00041 float dy) {
00042 poly spot;
00043
00044 {
00045 posetype way_pose(p1.map.x, p1.map.y,
00046 atan2f(p2.map.y-p1.map.y,
00047 p2.map.x-p1.map.x));
00048
00049 rotate_translate_transform trans;
00050 trans.find_transform(posetype(),way_pose);
00051
00052 float dist=Euclidean::DistanceTo(p1.map,
00053 p2.map);
00054
00055 p1.map = MapXY(trans.apply_transform(posetype(dx, dy, 0)));
00056 p2.map = MapXY(trans.apply_transform(posetype(dx + dist, dy, 0)));
00057 }
00058
00059 posetype way_pose(p1.map.x, p1.map.y,
00060 atan2f(p2.map.y-p1.map.y,
00061 p2.map.x-p1.map.x));
00062
00063 rotate_translate_transform trans;
00064 trans.find_transform(posetype(),way_pose);
00065
00066 float dist=Euclidean::DistanceTo(p1.map,
00067 p2.map);
00068
00069
00070 spot.p1 = MapXY(trans.apply_transform(posetype(0, p1.lane_width/2, 0)));
00071 spot.p2 = MapXY(trans.apply_transform(posetype(dist + 1, p2.lane_width/2, 0)));
00072 spot.p3 = MapXY(trans.apply_transform(posetype(dist + 1, -p2.lane_width/2, 0)));
00073 spot.p4 = MapXY(trans.apply_transform(posetype(0, -p1.lane_width/2, 0)));
00074
00075
00076
00077
00078
00079
00080
00081 return spot;
00082 }
00083
00084 int PARK_control::adjust_spot(std::vector<WayPointNode> &new_waypts,
00085 ObstacleList obstacles,
00086 float max_x_offset,
00087 float max_y_offset,
00088 float step_size) {
00089 PolyOps pops;
00090 int i = find_spot(new_waypts);
00091 if(i >= 0 && i < (int)new_waypts.size() - 1) {
00092 for(float dx = 0; dx <= max_x_offset; dx += step_size) {
00093 for(int x_sign = -1; x_sign <= 1; x_sign += 2) {
00094 for(float dy = 0; dy <= max_y_offset; dy += step_size) {
00095 for(int y_sign = -1; y_sign <= 1; y_sign += 2) {
00096 WayPointNode p1_new = new_waypts.at(i);
00097 WayPointNode p2_new = new_waypts.at(i+1);
00098
00099 poly spot = adjust_spot_and_return_poly(p1_new,
00100 p2_new,
00101 x_sign * dx,
00102 y_sign * dy);
00103
00104 int obstacles_in_spot = 0;
00105
00106 for(unsigned j = 0; j < obstacles.size(); j++) {
00107 if(pops.pointInPoly_ratio(obstacles[j], spot,1.1))
00108 obstacles_in_spot++;
00109 }
00110
00111 if(obstacles_in_spot <= min_obst) {
00112 float distt=sqrtf(dx*dx+dy*dy);
00113 if (distt <= min_adj_dist)
00114 {
00115 min_adj_dist=distt;
00116 min_obst=obstacles_in_spot;
00117 new_waypts.at(i) = p1_new;
00118 new_waypts.at(i+1) = p2_new;
00119
00120
00121 return 0;
00122 }
00123 }
00124 }
00125 }
00126 }
00127 }
00128 }
00129 return -1;
00130 }
00131
00132 PARK_control::PARK_control(Navigator *navptr, int _verbose):
00133 Controller(navptr, _verbose)
00134 {
00135 safety = new Safety(navptr, _verbose, 2);
00136 stop = new Stop(navptr, _verbose);
00137 halt = new Halt(navptr, _verbose);
00138 reset_me();
00139
00140 state=hit_waypoint;
00141 }
00142
00143 PARK_control::~PARK_control()
00144 {
00145 delete safety;
00146 delete stop;
00147 delete halt;
00148 }
00149
00150
00151 void PARK_control::configure(ConfigFile* cf, int section)
00152 {
00153 park_max_speed = cf->ReadFloat(section, "park_max_speed", 0.5);
00154
00155
00156 speed_limit = cf->ReadFloat(section, "park_control_speed_limit", 1.0);
00157 ART_MSG(2, "\tspeed limit for park_control is %.1f m/s", speed_limit);
00158
00159 min_distance = cf->ReadFloat(section, "park_min_distance", 0.5);
00160 ART_MSG(2, "\tmin_distance for park_control is %.1f m/s", min_distance);
00161
00162 min_theta = cf->ReadFloat(section, "park_min_theta", 0.25);
00163 ART_MSG(2, "\tmin_theta for park_control is %.1f m/s", min_theta);
00164
00165 park_turn_ratio = cf->ReadFloat(section, "park_turn_ratio", 1.0);
00166 ART_MSG(2, "\tturn_ratio for park_control is %.3f", park_turn_ratio);
00167
00168 find_a_better_spot = cf->ReadBool(section, "find_a_better_spot", false);
00169 ART_MSG(2, "\tfind_a_better_spot is %d", find_a_better_spot);
00170
00171 find_spot_max_x_offset = cf->ReadFloat(section,
00172 "find_spot_max_x_offset", 1.0);
00173 ART_MSG(2, "\tfind_spot_max_x_offset is %.3f m", find_spot_max_x_offset);
00174
00175 find_spot_max_y_offset = cf->ReadFloat(section,
00176 "find_spot_max_y_offset", 1.0);
00177 ART_MSG(2, "\tfind_spot_max_y_offset is %.3f m", find_spot_max_y_offset);
00178
00179 find_spot_step_size = cf->ReadFloat(section, "find_spot_step_size", 0.1);
00180 ART_MSG(2, "\tfind_spot_step_size is %.3f m", find_spot_step_size);
00181
00182 safety->configure(cf, section);
00183 }
00184
00185 inline float real_random(float multi=1.0){
00186 return float(random())/RAND_MAX*multi;
00187 }
00188
00189
00190
00191
00192
00193
00194 Controller::result_t PARK_control::control(pilot_command_t &pcmd,
00195 mapxy_list_t obs_list,
00196 bool voronoi_stuck) {
00197
00198 result_t result = OK;
00199 if (voronoi_stuck)
00200 {
00201 pcmd.velocity=speed_limit;
00202 navdata->reverse=true;
00203 pcmd.yawRate=0.0;
00204 result_t safe=safety->control(pcmd);
00205 int count=1;
00206 bool neg=false;
00207 float rand=real_random(Steering::maximum_yaw/2);
00208 while (safe>=Unsafe && fabsf(pcmd.yawRate) <= Steering::maximum_yaw)
00209 {
00210 if (!neg)
00211 pcmd.yawRate=rand*count;
00212 else
00213 {
00214 pcmd.yawRate=-rand*count;
00215 count++;
00216 }
00217 neg=!neg;
00218 pcmd.velocity=speed_limit;
00219 safe=safety->control(pcmd);
00220 }
00221 if (safe >= Unsafe)
00222 {
00223 pcmd.velocity=speed_limit;
00224 navdata->reverse=false;
00225 pcmd.yawRate=0;
00226 result_t safe=safety->control(pcmd);
00227 int count =1;
00228 bool neg=false;
00229 while (safe>=Unsafe && fabsf(pcmd.yawRate) <= Steering::maximum_yaw)
00230 {
00231 if (!neg)
00232 pcmd.yawRate=rand*count;
00233 else
00234 {
00235 pcmd.yawRate=-rand*count;
00236 count++;
00237 }
00238 neg=!neg;
00239 pcmd.velocity=speed_limit;
00240 safe=safety->control(pcmd);
00241 }
00242 }
00243
00244 result = safety->control(pcmd);
00245
00246
00247
00248 last_park_dist=pcmd.velocity;
00249 if (navdata->reverse)
00250 last_park_dist*=-1;
00251 last_park_turn=pcmd.yawRate;
00252
00253 if (result >=Unsafe)
00254 {
00255 pcmd.velocity=speed_limit;
00256 navdata->reverse=true;
00257 }
00258
00259 trace("park_control controller", pcmd, result);
00260 return result;
00261 }
00262
00263 std::vector<WayPointNode> new_waypts;
00264 for(int i = 0; i < N_ORDER_WAYPTS; i++)
00265 new_waypts.push_back(order->waypt[i]);
00266
00267 if(find_a_better_spot) {
00268 adjust_spot(new_waypts,
00269 obstacle->lasers->all_obstacle_list,
00270 find_spot_max_x_offset,
00271 find_spot_max_y_offset,
00272 find_spot_step_size);
00273 }
00274
00275 if (!new_waypts[1].is_spot)
00276 state=hit_waypoint;
00277 else
00278 if ((new_waypts[1].is_spot && new_waypts[2].is_spot &&
00279 new_waypts[1].id.pt==1 && new_waypts[2].id.pt==2))
00280 state=approach_spot;
00281 else
00282 if (new_waypts[1].is_spot && new_waypts[2].is_spot &&
00283 new_waypts[1].id.pt==2 && new_waypts[2].id.pt==1)
00284 state=pull_in;
00285 else state=pull_out;
00286
00287 if (course->spot_ahead())
00288 spot_points=course->calculate_spot_points(new_waypts);
00289 else if (!course->curr_spot())
00290 spot_points.clear();
00291
00292 for (uint i=0; i<spot_points.size(); i++)
00293 obs_list.push_back(spot_points[i]);
00294
00295
00296
00297
00298
00299
00300
00301 switch (state)
00302 {
00303 case hit_waypoint:
00304 case approach_spot:
00305 {
00306 posetype way_pose(new_waypts[1].map.x,new_waypts[1].map.y,
00307 atan2f(new_waypts[2].map.y-new_waypts[1].map.y,
00308 new_waypts[2].map.x-new_waypts[1].map.x));
00309
00310 rotate_translate_transform trans;
00311
00312 trans.find_transform(posetype(ArtVehicle::front_bumper_px,0,0),
00313 way_pose);
00314 posetype npose=trans.apply_transform(posetype(0,0,0));
00315
00316 new_end_pose.px=npose.x;
00317 new_end_pose.py=npose.y;
00318 new_end_pose.pa=npose.theta;
00319 }
00320 break;
00321 case pull_in:
00322 {
00323 posetype way_pose(new_waypts[1].map.x,new_waypts[1].map.y,
00324 atan2f(new_waypts[1].map.y-new_waypts[2].map.y,
00325 new_waypts[1].map.x-new_waypts[2].map.x));
00326
00327 rotate_translate_transform trans;
00328
00329 trans.find_transform(posetype(ArtVehicle::front_bumper_px,0,0),
00330 way_pose);
00331 posetype npose=trans.apply_transform(posetype());
00332
00333 new_end_pose.px=npose.x;
00334 new_end_pose.py=npose.y;
00335 new_end_pose.pa=npose.theta;
00336 }
00337 break;
00338 case pull_out:
00339 {
00340 posetype way_pose(new_waypts[1].map.x,new_waypts[1].map.y,
00341 atan2f(new_waypts[0].map.y-new_waypts[1].map.y,
00342 new_waypts[0].map.x-new_waypts[1].map.x));
00343 rotate_translate_transform trans;
00344
00345 trans.find_transform(posetype(ArtVehicle::front_bumper_px*2.0,0,0),
00346 way_pose);
00347 posetype npose=trans.apply_transform(posetype());
00348
00349 new_end_pose.px=npose.x;
00350 new_end_pose.py=npose.y;
00351 new_end_pose.pa=npose.theta;
00352 }
00353 break;
00354 }
00355
00356
00357
00358 pcmd.velocity=speed_limit;
00359 navdata->reverse=false;
00360
00361 if (Epsilon::equal(estimate->vel.px,0.0))
00362 halting=false;
00363 else if (Epsilon::gte(fabsf(estimate->vel.px),park_max_speed))
00364 halting=true;
00365
00366
00367
00368 result = initialize(pcmd, obs_list);
00369
00370 if (result==Finished)
00371 {
00372 ART_MSG(3,"PARK Finished");
00373 halting=true;
00374 halt->control(pcmd);
00375 return result;
00376 }
00377 else
00378 if (halting)
00379 {
00380
00381 pcmd.velocity=0.0;
00382 pcmd.yawRate=lastYaw;
00383 return OK;
00384 }
00385 else
00386 {
00387 if (result==OK)
00388 {
00389
00390 if (verbose >= 2)
00391 {
00392 ART_MSG(5, "Go to pose %.3f,%.3f,%.3f",
00393 new_end_pose.px, new_end_pose.py, new_end_pose.pa);
00394 }
00395 }
00396 else
00397 {
00398
00399
00400
00401 ART_MSG(3,"Not App.");
00402 pcmd.velocity=speed_limit;
00403 navdata->reverse=true;
00404 pcmd.yawRate=0;
00405 result_t safe=safety->control(pcmd);
00406 int count=1;
00407 bool neg=false;
00408 float rand=real_random(Steering::maximum_yaw/2);
00409 while (safe>=Unsafe && fabsf(pcmd.yawRate) <= Steering::maximum_yaw)
00410 {
00411 if (!neg)
00412 pcmd.yawRate=rand*count;
00413 else
00414 {
00415 pcmd.yawRate=-rand*count;
00416 count++;
00417 }
00418 neg=!neg;
00419 pcmd.velocity=speed_limit;
00420 safe=safety->control(pcmd);
00421 }
00422 if (safe >= Unsafe)
00423 {
00424 pcmd.velocity=speed_limit;
00425 navdata->reverse=false;
00426 pcmd.yawRate=0;
00427 result_t safe=safety->control(pcmd);
00428 int count =1;
00429 bool neg=false;
00430 while (safe>=Unsafe && fabsf(pcmd.yawRate) <= Steering::maximum_yaw)
00431 {
00432 if (!neg)
00433 pcmd.yawRate=rand*count;
00434 else
00435 {
00436 pcmd.yawRate=-rand*count;
00437 count++;
00438 }
00439 neg=!neg;
00440 pcmd.velocity=speed_limit;
00441 safe=safety->control(pcmd);
00442 }
00443 }
00444 }
00445
00446 }
00447
00448
00449
00450 result = safety->control(pcmd);
00451
00452 if (result >=Unsafe)
00453 {
00454 pcmd.velocity=speed_limit;
00455 navdata->reverse=true;
00456 }
00457
00458 pcmd.velocity=fminf(speed_limit,pcmd.velocity);
00459
00460 last_park_dist=pcmd.velocity;
00461 if (navdata->reverse)
00462 last_park_dist*=-1;
00463 last_park_turn=pcmd.yawRate;
00464
00465 lastYaw=pcmd.yawRate;
00466 trace("park_control controller", pcmd, result);
00467 return result;
00468 }
00469
00470
00471 void PARK_control::reset(void)
00472 {
00473 trace_reset("PARK_control");
00474 reset_me();
00475 halt->reset();
00476 safety->reset();
00477 stop->reset();
00478 }
00479
00480
00481
00482 void PARK_control::reset_me(void)
00483 {
00484 navdata->reverse = false;
00485 halting=true;
00486 park_distance=0.0;
00487 park_turn=0.0;
00488 last_park_turn=0.0;
00489 last_park_dist=0.0;
00490 min_adj_dist=Infinite::distance;
00491 min_obst=10000;
00492 }
00493
00494
00495
00496 Controller::result_t PARK_control::initialize(pilot_command_t& pcmd,
00497 const mapxy_list_t& obs_list)
00498 {
00499 int pcase=1;
00500
00501
00502 park_turn =Coordinates::bearing(estimate->pos,MapXY(new_end_pose));
00503
00504 park_distance = Euclidean::DistanceTo(new_end_pose,estimate->pos);
00505
00506
00507 float dheading=Coordinates::normalize(new_end_pose.pa-estimate->pos.pa);
00508
00509
00510
00511 if (hit_way_point(park_distance, park_turn, dheading) &&
00512 Epsilon::equal(estimate->vel.px,0.0))
00513 return Finished;
00514
00515 if (halting)
00516 return OK;
00517
00518 float b=fabsf(park_turn);
00519 float h=fabsf(dheading);
00520
00521
00522
00523 if (b < DTOR(45))
00524 if (h < DTOR(45))
00525 pcase=1;
00526 else if (h <DTOR(135) && dheading > 0)
00527 pcase=5;
00528 else if (h <DTOR(135) && dheading < 0)
00529 pcase=7;
00530 else pcase=6;
00531 else if (b < DTOR(135) && park_turn >0)
00532 if (h < DTOR(45))
00533 pcase=8;
00534 else if (h <DTOR(135) && dheading > 0)
00535 pcase=2;
00536 else if (h <DTOR(135) && dheading < 0)
00537 pcase=10;
00538 else pcase=9;
00539 else if (b < DTOR(135) && park_turn < 0)
00540 if (h < DTOR(45))
00541 pcase=14;
00542 else if (h <DTOR(135) && dheading > 0)
00543 pcase=15;
00544 else if (h <DTOR(135) && dheading < 0)
00545 pcase=4;
00546 else pcase=16;
00547 else
00548 if (h < DTOR(45))
00549 pcase=11;
00550 else if (h <DTOR(135) && dheading > 0)
00551 pcase=12;
00552 else if (h <DTOR(135) && dheading < 0)
00553 pcase=13;
00554 else pcase=3;
00555
00556 std::cerr << "Bearing: "<<RTOD(park_turn)<<"\t dhead: "<<RTOD(dheading)<<"\t distance "<<park_distance<<std::endl;
00557 std::cerr << "Case: "<<pcase<<"\n";
00558
00559 switch(pcase)
00560 {
00561 case 1:
00562 if (fabsf(sinf(park_turn)*park_distance) <
00563 fabsf(sinf(dheading)*(park_distance+ 3.5)))
00564 park_turn=dheading;
00565 break;
00566 case 2:
00567 case 4:
00568 if (fabsf(dheading) > fabsf(park_turn))
00569 park_turn = dheading;
00570 break;
00571 case 3:
00572 {
00573 float new_turn=Coordinates::normalize(park_turn+M_PI);
00574 float new_head=Coordinates::normalize(dheading+M_PI);
00575 if (fabsf(sinf(new_turn)*park_distance) <
00576 fabsf(sinf(new_head)*(park_distance+ 3.5)))
00577 park_turn=dheading;
00578 park_distance*=-1;
00579 navdata->reverse=true;
00580 }
00581 break;
00582 case 5:
00583 case 6:
00584 case 7:
00585 case 9:
00586 case 16:
00587 break;
00588 case 8:
00589 case 10:
00590 case 14:
00591 case 15:
00592 park_turn*=1;
00593 park_distance*=-1;
00594 navdata->reverse=true;
00595 break;
00596 case 11:
00597 park_distance*=-1;
00598 navdata->reverse=true;
00599 park_turn=0;
00600 break;
00601 case 12:
00602 case 13:
00603 park_turn=dheading;
00604 park_distance*=-1;
00605 navdata->reverse=true;
00606 break;
00607 }
00608
00609 if (fabsf(park_distance) < fmaxf(Steering::steer_speed_min,pcmd.velocity) && fabsf(park_turn) < Steering::maximum_yaw)
00610 pcmd.yawRate=park_turn;
00611 else
00612 pcmd.yawRate= fmaxf(Steering::steer_speed_min, pcmd.velocity)/
00613 fabs(park_distance)* park_turn * park_turn_ratio;
00614 pcmd.yawRate=fmaxf(-Steering::maximum_yaw/2,
00615 fminf(Steering::maximum_yaw/2,pcmd.yawRate));
00616
00617 if (safety->control(pcmd) < Unsafe)
00618 {
00619 return OK;
00620 }
00621 pcmd.velocity=speed_limit;
00622 navdata->reverse=true;
00623 pcmd.yawRate=dheading;
00624
00625 if (safety->control(pcmd) < Unsafe)
00626 {
00627 return OK;
00628 }
00629
00630 navdata->reverse=!navdata->reverse;
00631 pcmd.yawRate*=1;
00632 pcmd.velocity=speed_limit;
00633
00634 if (safety->control(pcmd) < Unsafe)
00635 {
00636 return OK;
00637 }
00638
00639
00640 return NotApplicable;
00641
00642 }
00643
00644 bool PARK_control::hit_way_point(float goal_distance, float goal_turn,
00645 float dheading) {
00646 bool done=false;
00647
00648 float car_bearing=Coordinates::bearing(new_end_pose,MapXY(estimate->pos));
00649
00650 switch(state)
00651 {
00652 case hit_waypoint:
00653 case approach_spot:
00654 {
00655 if (fabsf(dheading) < DTOR(30))
00656 if (goal_distance < 1.0 ||
00657 (fabsf(car_bearing) < HALFPI))
00658 done=true;
00659 }
00660 break;
00661 case pull_in:
00662 {
00663
00664 if (goal_distance < 0.75 ||
00665 fabsf(car_bearing) < HALFPI)
00666 done=true;
00667 }
00668 break;
00669 case pull_out:
00670 {
00671 if (fabsf(dheading) > DTOR(45) ||
00672 fabsf(car_bearing) > HALFPI ||
00673 goal_distance < 1.0)
00674
00675 done=true;
00676 }
00677 break;
00678 }
00679
00680 course->no_waypoint_reached();
00681
00682 if (done)
00683 {
00684 navdata->last_waypt=order->waypt[1].id;
00685 }
00686
00687 return done;
00688
00689 }
00690
00691 bool PARK_control::small_segment(float distance, float turn) {
00692 return (fabsf(distance) < min_distance &&
00693 fabsf(turn) < min_theta);
00694 }
00695