| | |
| | | #include "../common/apptimer.h" |
| | | #include "../test_common/odo_graph.h" |
| | | #include "../test_common/Geometry.h" |
| | | #include "../common/observer.h" |
| | | |
| | | #define DEBUG(fmt, args...) LOGD("<area_exam> <%s>: " fmt, __func__, ##args) |
| | | |
| | | static int CurrExamStatus = EXAM_AREA_NONE; // 1 测试完成 0 测试中 -1 测试错误退出 |
| | | static int CurrExamMapIndex = -1; |
| | | static int CurrEnterMapIndex = -1; |
| | | ilovers::Observer<std::function<void(move_status_t)>> CarMoveEvent; |
| | | |
| | | static void DetectEnterOrExitMap(int moveDirect, const car_model *CarModel, LIST_CAR_MODEL &CarModelList, LIST_AREA_MAP &mapList); |
| | | static int EnterMap(int moveDirect, const car_model *car, LIST_CAR_MODEL &CarModelList, LIST_AREA_MAP &mapList); |
| | | static bool ExitMap(const car_model *car, int index, LIST_AREA_MAP &mapList); |
| | | static bool CrashTriggerLine(Line triggerLine, const car_model *car, LIST_CAR_MODEL &CarModelList); |
| | | static void ExecuteExam(int index, LIST_AREA_MAP &AreaMapList, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int move, double azimuth, const struct RtkTime* rtkTime); |
| | | static bool ProximityArea(Line &base_line, Line &line); |
| | | static bool CrossingStartLine(Line &trace, Line &start_line); |
| | | static void ProximityReminders(prime_t &prime); |
| | | static void DetectCarMove(prime_t &prime); |
| | | |
| | | void AreaExam(prime_t &prime) |
| | | { |
| | | switch (prime.curr_exam_map.type) { |
| | | case MAP_TYPE_PARK_BUTTOM: |
| | | break; |
| | | case MAP_TYPE_PARK_EDGE: |
| | | break; |
| | | case MAP_TYPE_TURN_90: |
| | | break; |
| | | case MAP_TYPE_UPHILL: |
| | | break; |
| | | case MAP_TYPE_CURVE: |
| | | break; |
| | | default: |
| | | if (EnterMap()) { |
| | | |
| | | } |
| | | break; |
| | | } |
| | | DetectCarMove(prime); |
| | | } |
| | | |
| | | static void DetectCarMove(prime_t &prime) |
| | | { |
| | | static move_status_t prevMove = STOP; |
| | | if (prime.pMotion->move != prevMove) { |
| | | // Notify |
| | | CarMoveEvent.Notify(prime.pMotion->move); |
| | | prevMove = prime.pMotion->move; |
| | | } |
| | | } |
| | | |
| | | void RegisterCarMoveObserver(void (*ptr)(move_status_t)) |
| | | { |
| | | CarMoveEvent.Connect(ptr); |
| | | } |
| | | |
| | | void UnregisterCarMoveObserver(int handle) |
| | | { |
| | | CarMoveEvent.Disconnect(handle); |
| | | } |
| | | |
| | | void EnterMap(prime_t &prime) |
| | | { |
| | | if (prime.curr_exam_map.type != 0) { |
| | | return; |
| | | } |
| | | |
| | | if (prime.prev_modeling_index == -1 || prime.curr_modeling_index == -1) { |
| | | return; |
| | | } |
| | | |
| | | PointF &lp1 = prime.pModeling[prime.curr_modeling_index].points[prime.pModel->left_front_tire[TIRE_OUTSIDE]]; |
| | | PointF &lp2 = prime.pModeling[prime.prev_modeling_index].points[prime.pModel->left_front_tire[TIRE_OUTSIDE]]; |
| | | PointF &rp1 = prime.pModeling[prime.curr_modeling_index].points[prime.pModel->right_front_tire[TIRE_OUTSIDE]]; |
| | | PointF &rp2 = prime.pModeling[prime.prev_modeling_index].points[prime.pModel->right_front_tire[TIRE_OUTSIDE]]; |
| | | |
| | | Line left_trace, right_trace; |
| | | |
| | | MAKE_LINE(left_trace, lp1, lp2); |
| | | MAKE_LINE(right_trace, rp1, rp2); |
| | | |
| | | Line start_line; |
| | | for (int i = 0; i < prime.pMap->park_button_map.size(); ++i) { |
| | | MAKE_LINE(start_line, prime.pMap->park_button_map[i].map[1], prime.pMap->park_button_map[i].map[0]); |
| | | if (CrossingStartLine(left_trace, start_line)) { |
| | | prime.curr_exam_map.type = MAP_TYPE_PARK_BUTTOM; |
| | | prime.curr_exam_map.map_idx = i; |
| | | StartParkBottom(prime); |
| | | return; |
| | | } |
| | | MAKE_LINE(start_line, prime.pMap->park_button_map[i].map[7], prime.pMap->park_button_map[i].map[6]); |
| | | if (CrossingStartLine(left_trace, start_line)) { |
| | | prime.curr_exam_map.type = MAP_TYPE_PARK_BUTTOM; |
| | | prime.curr_exam_map.map_idx = i; |
| | | StartParkBottom(prime); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | for (int i = 0; i < prime.pMap->park_edge_map.size(); ++i) { |
| | | MAKE_LINE(start_line, prime.pMap->park_edge_map[i].map[1], prime.pMap->park_edge_map[i].map[0]); |
| | | if (CrossingStartLine(left_trace, start_line)) { |
| | | prime.curr_exam_map.type = MAP_TYPE_PARK_EDGE; |
| | | prime.curr_exam_map.map_idx = i; |
| | | return; |
| | | } |
| | | } |
| | | |
| | | for (int i = 0; i < prime.pMap->uphill_map.size(); ++i) { |
| | | PointF vPoint = Calc3Point(prime.pMap->uphill_map[i].map[8], prime.pMap->uphill_map[i].map[0], DistanceOf(prime.pMap->uphill_map[i].map[8], prime.pMap->uphill_map[i].map[7]), 'R'); |
| | | MAKE_LINE(start_line, prime.pMap->uphill_map[i].map[0], vPoint); |
| | | if (CrossingStartLine(left_trace, start_line)) { |
| | | prime.curr_exam_map.type = MAP_TYPE_UPHILL; |
| | | prime.curr_exam_map.map_idx = i; |
| | | return; |
| | | } |
| | | } |
| | | for (int i = 0; i < prime.pMap->curve_map.size(); ++i) { |
| | | MAKE_LINE(start_line, prime.pMap->curve_map[i].right_start_point, prime.pMap->curve_map[i].left_start_point); |
| | | if (CrossingStartLine(left_trace, start_line)) { |
| | | prime.curr_exam_map.type = MAP_TYPE_CURVE; |
| | | prime.curr_exam_map.map_idx = i; |
| | | return; |
| | | } |
| | | } |
| | | for (int i = 0; i < prime.pMap->turn_a90_map.size(); ++i) { |
| | | MAKE_LINE(start_line, prime.pMap->turn_a90_map[i].map[0], prime.pMap->turn_a90_map[i].map[1]); |
| | | if (CrossingStartLine(left_trace, start_line)) { |
| | | prime.curr_exam_map.type = MAP_TYPE_TURN_90; |
| | | prime.curr_exam_map.map_idx = i; |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 车轮驶过线,且车头位于右侧 |
| | | static bool CrossingStartLine(Line &trace, Line &start_line) |
| | | { |
| | | PointF head = {.X = trace.X1, .Y = trace.Y1}; |
| | | |
| | | if (IntersectionOf(trace, start_line) == GM_Intersection |
| | | && IntersectionOfLine(head, start_line) == RELATION_RIGHT) { |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | void FarawayMap(prime_t &prime) |
| | | { |
| | | if (prime.arriving_map.type != 0) { |
| | | PointF &car_head = prime.pModeling[prime.curr_modeling_index].points[prime.pModel->axial[AXIAL_FRONT]]; |
| | | PointF car_head_trend = PointExtend(car_head, 7, prime.pModeling->yaw); |
| | | Line car_head_line; |
| | | MAKE_LINE(car_head_line, car_head, car_head_trend); |
| | | |
| | | |
| | | } |
| | | } |
| | | |
| | | static void ProximityReminders(prime_t &prime) |
| | | { |
| | | if (prime.curr_exam_map.type != MAP_TYPE_NONE && prime.arriving_map.type != MAP_TYPE_NONE) { |
| | | return; |
| | | } |
| | | |
| | | PointF &car_head = prime.pModeling[prime.curr_modeling_index].points[prime.pModel->axial[AXIAL_FRONT]]; |
| | | PointF car_head_trend = PointExtend(car_head, 6, prime.pModeling->yaw); |
| | | Line car_head_line; |
| | | MAKE_LINE(car_head_line, car_head, car_head_trend); |
| | | |
| | | Line start_line; |
| | | for (int i = 0; i < prime.pMap->park_button_map.size(); ++i) { // 左右2条控制线都可作为入口 |
| | | MAKE_LINE(start_line, prime.pMap->park_button_map[i].map[1], prime.pMap->park_button_map[i].map[0]); |
| | | |
| | | MAKE_LINE(start_line, prime.pMap->park_button_map[i].map[7], prime.pMap->park_button_map[i].map[6]); |
| | | |
| | | } |
| | | for (int i = 0; i < prime.pMap->park_edge_map.size(); ++i) { |
| | | MAKE_LINE(start_line, prime.pMap->park_edge_map[i].map[1], prime.pMap->park_edge_map[i].map[0]); |
| | | } |
| | | |
| | | for (int i = 0; i < prime.pMap->uphill_map.size(); ++i) { |
| | | PointF vPoint = Calc3Point(prime.pMap->uphill_map[i].map[8], prime.pMap->uphill_map[i].map[0], DistanceOf(prime.pMap->uphill_map[i].map[8], prime.pMap->uphill_map[i].map[7]), 'R'); |
| | | MAKE_LINE(start_line, prime.pMap->uphill_map[i].map[0], vPoint); |
| | | } |
| | | for (int i = 0; i < prime.pMap->curve_map.size(); ++i) { |
| | | MAKE_LINE(start_line, prime.pMap->curve_map[i].right_start_point, prime.pMap->curve_map[i].left_start_point); |
| | | } |
| | | for (int i = 0; i < prime.pMap->turn_a90_map.size(); ++i) { |
| | | MAKE_LINE(start_line, prime.pMap->turn_a90_map[i].map[0], prime.pMap->turn_a90_map[i].map[1]); |
| | | } |
| | | } |
| | | |
| | | // 判断是否接近场地的起始线 |
| | | // 车头趋势线是否和入口线相交 |
| | | // 和入口线的夹角 |
| | | static bool ProximityArea(Line &base_line, Line &line) |
| | | { |
| | | PointF head = {.X = line.X1, .Y = line.Y1}; |
| | | |
| | | if (IntersectionOf(base_line, line) == GM_Intersection |
| | | && DistanceOf(head, base_line) > 1) { |
| | | double angle = AngleOfTowLine(base_line, line); |
| | | if (angle >= 240 && angle <= 300) { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | void TerminateAreaExam(void) |
| | | { |
| | |
| | | { |
| | | CurrExamMapIndex = -1; |
| | | ResetOdo(); |
| | | } |
| | | |
| | | void TestAreaGeneral(LIST_AREA_MAP &AreaMapList, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, double azimuth, const struct RtkTime *rtkTime) |
| | | { |
| | | UpdataOdo(speed, moveDirect, rtkTime); |
| | | |
| | | DetectEnterOrExitMap(moveDirect, car, CarModelList, AreaMapList); |
| | | |
| | | ExecuteExam(CurrExamMapIndex, AreaMapList, car, CarModelList, speed, moveDirect, azimuth, rtkTime); |
| | | } |
| | | |
| | | void DistanceOfTire2X(std::vector<double> &array, const car_model *car, std::vector<Line> line_set) |
| | | { |
| | | double ld = 100, rd = 100; |
| | | |
| | | array.clear(); |
| | | |
| | | for (auto line = line_set.begin(); line != line_set.end(); line++) { |
| | | double ld_t = 100, rd_t = 100; |
| | | double d; |
| | | if (VerticalPointOnLine(car->carXY[car->left_front_tire[TIRE_OUTSIDE]], *line)) { |
| | | d = DistanceOf(car->carXY[car->left_front_tire[TIRE_OUTSIDE]], *line); |
| | | if (d < ld_t) { |
| | | ld_t = d; |
| | | } |
| | | } |
| | | if (VerticalPointOnLine(car->carXY[car->left_rear_tire[TIRE_OUTSIDE]], *line)) { |
| | | d = DistanceOf(car->carXY[car->left_rear_tire[TIRE_OUTSIDE]], *line); |
| | | if (d < ld_t) { |
| | | ld_t = d; |
| | | } |
| | | } |
| | | |
| | | if (VerticalPointOnLine(car->carXY[car->right_front_tire[TIRE_OUTSIDE]], *line)) { |
| | | d = DistanceOf(car->carXY[car->right_front_tire[TIRE_OUTSIDE]], *line); |
| | | if (d < rd_t) { |
| | | rd_t = d; |
| | | } |
| | | } |
| | | if (VerticalPointOnLine(car->carXY[car->right_rear_tire[TIRE_OUTSIDE]], *line)) { |
| | | d = DistanceOf(car->carXY[car->right_rear_tire[TIRE_OUTSIDE]], *line); |
| | | if (d < rd_t) { |
| | | rd_t = d; |
| | | } |
| | | } |
| | | |
| | | if (isEqual2(ld_t, rd_t)) { |
| | | if (!isEqual(ld_t, 100)) { |
| | | if (rd_t < rd) |
| | | rd = rd_t; |
| | | if (ld_t < ld) |
| | | ld = ld_t; |
| | | } |
| | | } else if (ld_t > rd_t) { |
| | | if (rd_t < rd) |
| | | rd = rd_t; |
| | | } else { |
| | | if (ld_t < ld) |
| | | ld = ld_t; |
| | | } |
| | | } |
| | | |
| | | array.push_back(ld); |
| | | array.push_back(rd); |
| | | } |
| | | |
| | | static void DetectEnterOrExitMap(int moveDirect, const car_model *car, LIST_CAR_MODEL &CarModelList, LIST_AREA_MAP &mapList) |
| | | { |
| | | if (CurrExamMapIndex < 0) { |
| | | if (CurrEnterMapIndex < 0) { |
| | | CurrEnterMapIndex = EnterMap(moveDirect, car, CarModelList, mapList); |
| | | if (CurrEnterMapIndex >= 0) { |
| | | DEBUG("进入某个子项目 idx = %d", CurrEnterMapIndex); |
| | | CurrExamMapIndex = CurrEnterMapIndex; |
| | | CurrExamStatus = EXAM_AREA_START; |
| | | } |
| | | } else { |
| | | if (ExitMap(car, CurrEnterMapIndex, mapList)) { |
| | | DEBUG("离开某个子项目 idx = %d", CurrEnterMapIndex); |
| | | CurrEnterMapIndex = -1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | static void ExecuteExam(int index, LIST_AREA_MAP &AreaMapList, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int move, double azimuth, const struct RtkTime* rtkTime) |
| | | { |
| | | if (index >= 0) { |
| | | if (CurrExamStatus == EXAM_AREA_START) { |
| | | DEBUG("CurrExamMapIndex %d mtype %d", AreaMapList[index].id, AreaMapList[index].type); |
| | | |
| | | switch (AreaMapList[index].type) { |
| | | case MAP_TYPE_PARK_BUTTOM: |
| | | DEBUG("进入倒车入库场地 %d", AreaMapList[index].id); |
| | | |
| | | StartParkBottom(AreaMapList[index].id, move, rtkTime); |
| | | CurrExamStatus = EXAM_AREA_RUN; |
| | | break; |
| | | case MAP_TYPE_STOP_START: |
| | | DEBUG("进入上坡起步场地 %d", AreaMapList[index].id); |
| | | |
| | | StartSAS(AreaMapList[index].id, &AreaMapList[index].map, car, move, rtkTime); |
| | | CurrExamStatus = EXAM_AREA_RUN; |
| | | break; |
| | | case MAP_TYPE_PART_EDGE: |
| | | DEBUG("进入侧方位停车场地 %d", AreaMapList[index].id); |
| | | |
| | | StartParkEdge(AreaMapList[index].id, move, rtkTime); |
| | | CurrExamStatus = EXAM_AREA_RUN; |
| | | break; |
| | | case MAP_TYPE_CURVE: |
| | | DEBUG("进入曲线行驶场地 %d", AreaMapList[index].id); |
| | | |
| | | StartDrivingCurve(AreaMapList[index].id, move, rtkTime); |
| | | CurrExamStatus = EXAM_AREA_RUN; |
| | | break; |
| | | case MAP_TYPE_TURN_90: |
| | | DEBUG("进入直角转弯场地 %d", AreaMapList[index].id); |
| | | |
| | | StartTurnA90(AreaMapList[index].id, move, azimuth, rtkTime); |
| | | CurrExamStatus = EXAM_AREA_RUN; |
| | | break; |
| | | default:break; |
| | | } |
| | | } else if (CurrExamStatus == EXAM_AREA_RUN) { |
| | | int testing = 0; |
| | | switch (AreaMapList[index].type) { |
| | | case MAP_TYPE_PARK_BUTTOM: |
| | | testing = TestParkBottom(&AreaMapList[index].map, |
| | | car, NULL, speed, move, rtkTime); |
| | | break; |
| | | case MAP_TYPE_STOP_START: |
| | | testing = TestSAS(&AreaMapList[index].map, car, NULL, speed, move, rtkTime); |
| | | break; |
| | | case MAP_TYPE_PART_EDGE: |
| | | testing = TestParkEdge(&AreaMapList[index].map, car, NULL, speed, move, rtkTime); |
| | | break; |
| | | case MAP_TYPE_CURVE: |
| | | testing = TestDrivingCurve(&AreaMapList[index].map, &AreaMapList[index].map2, car, NULL, speed, move, rtkTime); |
| | | break; |
| | | case MAP_TYPE_TURN_90: |
| | | testing = TestTurnA90(&AreaMapList[index].map, car, NULL, azimuth, speed, move, rtkTime); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | if (testing > 0) { |
| | | CurrExamStatus = EXAM_AREA_RUN; |
| | | } else { |
| | | CurrExamStatus = EXAM_AREA_END; |
| | | } |
| | | } |
| | | if (CurrExamStatus != EXAM_AREA_RUN) { |
| | | // 某项结束 |
| | | CurrExamStatus = EXAM_AREA_NONE; |
| | | CurrExamMapIndex = -1; |
| | | DEBUG("结束当前项目"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | static int EnterMap(int moveDirect, const car_model *car, LIST_CAR_MODEL &CarModelList, LIST_AREA_MAP &mapList) |
| | | { |
| | | vector<int> score(mapList.size(), 0); // 场地重合时,车头尾都在内的优先 |
| | | |
| | | for (int i = 0; i < mapList.size() && car != NULL; ++i) { |
| | | // 车前轮或后轮轨迹越过触发线 |
| | | if (mapList[i].type == MAP_TYPE_STOP_START) { |
| | | // 构造虚拟的左上角点 |
| | | double x9, y9, xo, yo; |
| | | |
| | | xo = (mapList[i].map.point[0].X + mapList[i].map.point[7].X) / 2; |
| | | yo = (mapList[i].map.point[0].Y + mapList[i].map.point[7].Y) / 2; |
| | | |
| | | x9 = 2*xo - mapList[i].map.point[8].X; |
| | | y9 = 2*yo - mapList[i].map.point[8].Y; |
| | | |
| | | Line triggerLine; |
| | | |
| | | triggerLine.X1 = mapList[i].map.point[0].X; |
| | | triggerLine.Y1 = mapList[i].map.point[0].Y; |
| | | triggerLine.X2 = x9; |
| | | triggerLine.Y2 = y9; |
| | | |
| | | if (moveDirect > 0 && CrashTriggerLine(triggerLine, car, CarModelList)) |
| | | return i; |
| | | } |
| | | if (mapList[i].type == MAP_TYPE_PARK_BUTTOM) { |
| | | Line triggerLine; |
| | | |
| | | MakeLine(&triggerLine, &(mapList[i].map.point[1]), &(mapList[i].map.point[0])); |
| | | |
| | | if (moveDirect > 0 && CrashTriggerLine(triggerLine, car, CarModelList)) |
| | | return i; |
| | | |
| | | MakeLine(&triggerLine, &(mapList[i].map.point[7]), &(mapList[i].map.point[6])); |
| | | |
| | | if (moveDirect > 0 && CrashTriggerLine(triggerLine, car, CarModelList)) |
| | | return i; |
| | | |
| | | // 全车在场地内 |
| | | if (moveDirect == 0) { |
| | | Polygon carBody; |
| | | bool ret = false; |
| | | carBody.num = car->bodyNum; |
| | | carBody.point = (PointF *) malloc(carBody.num * sizeof(PointF)); |
| | | for (int i = 0; i < carBody.num; ++i) { |
| | | carBody.point[i] = car->carXY[car->body[i]]; |
| | | } |
| | | |
| | | if (IntersectionOf(&carBody, &mapList[i].map) == GM_Containment) { |
| | | ret = true; |
| | | } |
| | | |
| | | free(carBody.point); |
| | | |
| | | if (ret) |
| | | return i; |
| | | } |
| | | // // 车头顶点在场地内 |
| | | // if (IntersectionOf(car->carXY[ car->axial[AXIAL_FRONT] ], &mapList[i].map) == GM_Containment) { |
| | | // Line enterLine1, enterLine2; |
| | | // |
| | | // MakeLine(&enterLine1, &(mapList[i].map.point[0]), &(mapList[i].map.point[1])); |
| | | // MakeLine(&enterLine2, &(mapList[i].map.point[6]), &(mapList[i].map.point[7])); |
| | | // |
| | | // if (DistanceOf(car->carXY[car->axial[AXIAL_FRONT]], enterLine1) > 0.1 && |
| | | // DistanceOf(car->carXY[car->axial[AXIAL_FRONT]], enterLine2) > 0.1) |
| | | // score[i]++; |
| | | // } |
| | | // // 车尾顶点在场地内 |
| | | // if (IntersectionOf(car->carXY[ car->axial[AXIAL_REAR] ], &mapList[i].map) == GM_Containment) { |
| | | // Line enterLine1, enterLine2; |
| | | // |
| | | // MakeLine(&enterLine1, &(mapList[i].map.point[0]), &(mapList[i].map.point[1])); |
| | | // MakeLine(&enterLine2, &(mapList[i].map.point[6]), &(mapList[i].map.point[7])); |
| | | // |
| | | // if (DistanceOf(car->carXY[car->axial[AXIAL_REAR]], enterLine1) > 0.1 && |
| | | // DistanceOf(car->carXY[car->axial[AXIAL_REAR]], enterLine2) > 0.1) |
| | | // score[i]++; |
| | | // } |
| | | } |
| | | if (mapList[i].type == MAP_TYPE_PART_EDGE) { |
| | | Line triggerLine; |
| | | |
| | | MakeLine(&triggerLine, &(mapList[i].map.point[1]), &(mapList[i].map.point[0])); |
| | | |
| | | if (moveDirect > 0 && CrashTriggerLine(triggerLine, car, CarModelList)) |
| | | return i; |
| | | |
| | | // 全车在场地内 |
| | | if (moveDirect == 0) { |
| | | Polygon carBody; |
| | | bool ret = false; |
| | | carBody.num = car->bodyNum; |
| | | carBody.point = (PointF *) malloc(carBody.num * sizeof(PointF)); |
| | | for (int i = 0; i < carBody.num; ++i) { |
| | | carBody.point[i] = car->carXY[car->body[i]]; |
| | | } |
| | | |
| | | if (IntersectionOf(&carBody, &mapList[i].map) == GM_Containment) { |
| | | ret = true; |
| | | } |
| | | |
| | | free(carBody.point); |
| | | |
| | | if (ret) |
| | | return i; |
| | | } |
| | | // // 车头顶点在场地内 |
| | | // if (IntersectionOf(car->carXY[ car->axial[AXIAL_FRONT] ], &mapList[i].map) == GM_Containment) { |
| | | // Line enterLine; |
| | | // |
| | | // MakeLine(&enterLine, &(mapList[i].map.point[0]), &(mapList[i].map.point[1])); |
| | | // |
| | | // if (DistanceOf(car->carXY[car->axial[AXIAL_FRONT]], enterLine) > 0.1) |
| | | // score[i]++; |
| | | // } |
| | | // // 车尾顶点在场地内 |
| | | // if (IntersectionOf(car->carXY[ car->axial[AXIAL_REAR] ], &mapList[i].map) == GM_Containment) { |
| | | // Line enterLine; |
| | | // |
| | | // MakeLine(&enterLine, &(mapList[i].map.point[0]), &(mapList[i].map.point[1])); |
| | | // |
| | | // if (DistanceOf(car->carXY[car->axial[AXIAL_REAR]], enterLine) > 0.1) |
| | | // score[i]++; |
| | | // } |
| | | } |
| | | if (mapList[i].type == MAP_TYPE_TURN_90) { |
| | | // 车前轮或后轮轨迹越过触发线 |
| | | Line triggerLine; |
| | | |
| | | MakeLine(&triggerLine, &(mapList[i].map.point[0]), &(mapList[i].map.point[1])); |
| | | |
| | | if (moveDirect > 0 && CrashTriggerLine(triggerLine, car, CarModelList)) |
| | | return i; |
| | | } |
| | | if (mapList[i].type == MAP_TYPE_CURVE) { |
| | | // 车前轮或后轮轨迹越过触发线 |
| | | Line triggerLine; |
| | | |
| | | MakeLine(&triggerLine, &mapList[i].map2.point[0], &mapList[i].map.point[0]); |
| | | if (moveDirect > 0 && CrashTriggerLine(triggerLine, car, CarModelList)) |
| | | return i; |
| | | } |
| | | } |
| | | |
| | | for (int i = 0; i < score.size(); ++i) { |
| | | if (score[i] == 2) { |
| | | return i; |
| | | } |
| | | } |
| | | |
| | | for (int i = 0; i < score.size(); ++i) { |
| | | if (score[i] == 1) { |
| | | return i; |
| | | } |
| | | } |
| | | |
| | | return -1; |
| | | } |
| | | |
| | | static bool ExitMap(const car_model *car, int index, LIST_AREA_MAP &mapList) |
| | | { |
| | | bool ret = false; |
| | | if (index < 0 || index >= mapList.size()) return true; |
| | | |
| | | if (mapList[index].type == MAP_TYPE_PARK_BUTTOM || |
| | | mapList[index].type == MAP_TYPE_PART_EDGE || |
| | | mapList[index].type == MAP_TYPE_TURN_90) { |
| | | // 全车都需不在地图中 |
| | | Polygon carBody; |
| | | |
| | | carBody.num = car->bodyNum; |
| | | carBody.point = (PointF *)malloc(carBody.num * sizeof(PointF)); |
| | | for (int i = 0; i < carBody.num; ++i) { |
| | | carBody.point[i] = car->carXY[car->body[i]]; |
| | | } |
| | | |
| | | if (IntersectionOf(&carBody, &mapList[index].map) == GM_None) { |
| | | ret = true; |
| | | } |
| | | |
| | | free(carBody.point); |
| | | } |
| | | if (mapList[index].type == MAP_TYPE_STOP_START) { |
| | | // 构造虚拟的左上角点 |
| | | double x10, y10, x9, y9, xo, yo; |
| | | |
| | | bool enter = false; |
| | | |
| | | xo = (mapList[index].map.point[0].X + mapList[index].map.point[7].X) / 2; |
| | | yo = (mapList[index].map.point[0].Y + mapList[index].map.point[7].Y) / 2; |
| | | |
| | | x9 = 2*xo - mapList[index].map.point[8].X; |
| | | y9 = 2*yo - mapList[index].map.point[8].Y; |
| | | |
| | | if (mapList[index].map.num > 9) { |
| | | // 构造虚拟的右上角点 |
| | | xo = (mapList[index].map.point[9].X + mapList[index].map.point[7].X) / 2; |
| | | yo = (mapList[index].map.point[9].Y + mapList[index].map.point[7].Y) / 2; |
| | | x10 = 2*xo - mapList[index].map.point[8].X; |
| | | y10 = 2*yo - mapList[index].map.point[8].Y; |
| | | } |
| | | |
| | | Polygon map; |
| | | |
| | | map.num = 4; |
| | | map.point = (PointF *) malloc(map.num * sizeof(PointF)); |
| | | |
| | | if (mapList[index].map.num <= 9) { |
| | | map.point[0] = mapList[index].map.point[0]; |
| | | map.point[1] = mapList[index].map.point[8]; |
| | | map.point[2] = mapList[index].map.point[7]; |
| | | map.point[3].X = x9; |
| | | map.point[3].Y = y9; |
| | | } else { |
| | | map.point[0] = mapList[index].map.point[0]; |
| | | map.point[1] = mapList[index].map.point[9]; |
| | | map.point[2].X = x10; |
| | | map.point[2].Y = y10; |
| | | map.point[3].X = x9; |
| | | map.point[3].Y = y9; |
| | | } |
| | | // 全车都需不在地图中 |
| | | Polygon carBody; |
| | | |
| | | carBody.num = car->bodyNum; |
| | | carBody.point = (PointF *)malloc(carBody.num * sizeof(PointF)); |
| | | for (int i = 0; i < carBody.num; ++i) { |
| | | carBody.point[i] = car->carXY[car->body[i]]; |
| | | } |
| | | |
| | | if (IntersectionOf(&carBody, &map) == GM_None) { |
| | | ret = true; |
| | | } |
| | | |
| | | free(carBody.point); |
| | | free(map.point); |
| | | } |
| | | if (mapList[index].type == MAP_TYPE_CURVE) { |
| | | ret = ExitDrivingCurveArea(&mapList[index].map, &mapList[index].map2, car); |
| | | } |
| | | |
| | | return ret; |
| | | } |
| | | |
| | | static bool CrashTriggerLine(Line triggerLine, const car_model *car, LIST_CAR_MODEL &CarModelList) |
| | | { |
| | | bool trigger = false; |
| | | |
| | | if (CarModelList.size() < 5) |
| | | return trigger; |
| | | |
| | | Polygon trace, trace2; |
| | | int pn = 0; |
| | | |
| | | trace2.num = trace.num = 5; |
| | | trace.point = (PointF *) malloc(sizeof(PointF) * trace.num); |
| | | trace2.point = (PointF *) malloc(sizeof(PointF) * trace2.num); |
| | | |
| | | list<car_model *>::iterator iter = CarModelList.begin(); |
| | | |
| | | car_model *c1 = *iter; |
| | | |
| | | trace.point[pn] = centerOfTwoPoint(c1->carXY[c1->left_front_tire[TIRE_OUTSIDE]], c1->carXY[c1->right_front_tire[TIRE_OUTSIDE]]); |
| | | trace2.point[pn++] = centerOfTwoPoint(c1->carXY[c1->left_rear_tire[TIRE_OUTSIDE]], c1->carXY[c1->right_rear_tire[TIRE_OUTSIDE]]); |
| | | |
| | | ++iter; |
| | | |
| | | while (iter != CarModelList.end() && pn < trace.num) { |
| | | car_model *c2 = *iter; |
| | | |
| | | uint32_t tdiff = TimeGetDiff(c1->tm.hh, c1->tm.mm, c1->tm.ss, c1->tm.mss * 10, c2->tm.hh, c2->tm.mm, c2->tm.ss, c2->tm.mss*10); |
| | | |
| | | if (tdiff >= D_SEC(1)) { |
| | | trace.point[pn] = centerOfTwoPoint(c2->carXY[c2->left_front_tire[TIRE_OUTSIDE]], c2->carXY[c2->right_front_tire[TIRE_OUTSIDE]]); |
| | | trace2.point[pn++] = centerOfTwoPoint(c2->carXY[c2->left_rear_tire[TIRE_OUTSIDE]], c2->carXY[c2->right_rear_tire[TIRE_OUTSIDE]]); |
| | | c1 = c2; |
| | | } |
| | | ++iter; |
| | | } |
| | | |
| | | PointF p1, p2; |
| | | |
| | | p1.X = triggerLine.X1; |
| | | p1.Y = triggerLine.Y1; |
| | | p2.X = triggerLine.X2; |
| | | p2.Y = triggerLine.Y2; |
| | | |
| | | int pp = 0; |
| | | for (int p = 1; p < pn; ++p) { |
| | | Line trace_line, trace2_line; |
| | | |
| | | MakeLine(&trace_line, &trace.point[pp], &trace.point[p]); |
| | | MakeLine(&trace2_line, &trace2.point[pp], &trace2.point[p]); |
| | | |
| | | if ((IntersectionOf(trace_line, triggerLine) == GM_Intersection && |
| | | IntersectionOfLine(p1, p2, centerOfTwoPoint(car->carXY[car->left_front_tire[TIRE_OUTSIDE]], car->carXY[car->right_front_tire[TIRE_OUTSIDE]])) == -1 && |
| | | DistanceOf(centerOfTwoPoint(car->carXY[car->left_front_tire[TIRE_OUTSIDE]], car->carXY[car->right_front_tire[TIRE_OUTSIDE]]), triggerLine) > 0.1) || |
| | | (IntersectionOf(trace2_line, triggerLine) == GM_Intersection && |
| | | IntersectionOfLine(p1, p2, centerOfTwoPoint(car->carXY[car->left_rear_tire[TIRE_OUTSIDE]], car->carXY[car->right_rear_tire[TIRE_OUTSIDE]])) == -1 && |
| | | DistanceOf(centerOfTwoPoint(car->carXY[car->left_rear_tire[TIRE_OUTSIDE]], car->carXY[car->right_rear_tire[TIRE_OUTSIDE]]), triggerLine) > 0.1) ) { |
| | | // 碰到触发线 |
| | | DEBUG("碰撞触发线 引发地图"); |
| | | trigger = true; |
| | | goto SEARCH_TRIGGER_LINE_END; |
| | | } |
| | | } |
| | | |
| | | SEARCH_TRIGGER_LINE_END: |
| | | free(trace.point); |
| | | |
| | | return trigger; |
| | | } |