// // Created by YY on 2019/10/23. // // // 0 ____________________________________7 // // // 1 _____________2 5_________________6 // 8| |9 // | | // | | // | | // 3--------4 // #include "park_bottom.h" #include "../common/apptimer.h" #include "../test_common/Geometry.h" #include "../native-lib.h" #include "../jni_log.h" #include "../driver_test.h" #include "../utils/xconvert.h" #include "../master/comm_if.h" #include "area_exam.h" #include "../test_common/car_sensor.h" #include "../test_common/odo_graph.h" #include "../teach/train.h" #include "../teach/teach.h" #include #include #include #define DEBUG(fmt, args...) LOGD(" <%s>: " fmt, __func__, ##args) using namespace std; typedef enum { NONE_CTRL_LINE, LEFT_CTRL_LINE, RIGHT_CTRL_LINE } ctrl_line_t; static bool occurCrashRedLine; static int parkCount; static int reverseCnt = 0; static bool stopFlag; static ctrl_line_t prevCrossedCtrlLine; static bool checkCtrlLine, checkParkspace; static int handleGearOb, handleMoveOb; static bool BodyCollidingLine(prime_t &prime); static ctrl_line_t CrossCtrlLine(prime_t &prime); static bool CheckParkspace(prime_t &prime); static void MoveOb(move_status_t curr, move_status_t prev, double distance); static void GearOb(int gear, int prevGear, double move_distance); enum { PREPARE_REVERSE, REVERSE_LEFT, REVERSE_RIGHT, OBVERSE_LEFT, OBVERSE_RIGHT }; /* 1. 进入 --- 首次倒库前 2. 倒库 ---- 停车到位前(右倒库) 3. 左出库 4. 倒库 ---- 停车到位前(左倒库) 5. 右出库(离开场地) */ void StartParkBottom(prime_t &prime) { DEBUG("进入倒库场地"); stopFlag = false; parkCount = 0; reverseCnt = 0; checkCtrlLine = false; checkParkspace = false; occurCrashRedLine = false; prime.examing_area.stage = PREPARE_REVERSE; testAll(); LoadStageTips(prime); prevCrossedCtrlLine = NONE_CTRL_LINE; handleGearOb = RegisterShiftObserver(GearOb); handleMoveOb = RegisterCarMoveObserver(MoveOb); PlayTTS("您已进入倒车入库区域", NULL); } static void ParkTimeout(apptimer_var_t var) { DEBUG("项目超时"); AddExamFault(20105); } static void MoveOb(move_status_t curr, move_status_t prev, double distance) { // 车辆由运动到停止,记录一下,当换挡发生时,避免原地来回换挡造成误判 if (curr == STOP && distance > 0.5) { stopFlag = true; } } static void GearOb(int gear, int prevGear, double move_distance) { DEBUG("GearOb %d %f", gear, move_distance); if (gear == GEAR_R && stopFlag) { // 移入倒挡 stopFlag = false; reverseCnt++; if (reverseCnt == 1) { AppTimer_delete(ParkTimeout); AppTimer_add(ParkTimeout, GetPrime().examParam.park_bottom_limit_time); } checkCtrlLine = true; } else if (prevGear == GEAR_R && stopFlag) { // 从倒挡移出 stopFlag = false; checkParkspace = true; } } void StopParkBottom(prime_t &prime) { if (prime.examing_area.type != MAP_TYPE_PARK_BUTTOM) return; DEBUG("离开倒库场地"); if (parkCount < 2) { DEBUG("直接驶离测试区,不按考试员指令驾驶"); AddExamFault(10103); } AppTimer_delete(ParkTimeout); prime.examing_area.type = MAP_TYPE_NONE; UnregisterShiftObserver(handleGearOb); UnregisterCarMoveObserver(handleMoveOb); } void TestParkBottom(prime_t &prime) { if (prime.examing_area.type != MAP_TYPE_PARK_BUTTOM) return; train(prime); if (checkCtrlLine) { ctrl_line_t crossCtrlLine = CrossCtrlLine(prime); if (crossCtrlLine == NONE_CTRL_LINE) { // 倒车前,前轮未驶过控制线 DEBUG("倒车前,前轮未驶过控制线"); AddExamFault(20104); } else if (crossCtrlLine == prevCrossedCtrlLine) { // 重复跨越同一控制线,不按规定线路,顺序形式,不合格 AddExamFault(20101); DEBUG("不按规定线路,顺序形式, 同 %d 侧", prevCrossedCtrlLine); } else { prevCrossedCtrlLine = crossCtrlLine; DEBUG("开始 %d 侧 倒库", prevCrossedCtrlLine); } if (DeltaYaw(YawOf(std::get(prime.maps)[prime.examing_area.idx].points[3], std::get(prime.maps)[prime.examing_area.idx].points[4]), prime.pModeling[prime.curr_modeling_index].yaw) < 90) { DEBUG("右侧倒库"); prime.examing_area.stage = REVERSE_RIGHT; } else { DEBUG("左侧倒库"); prime.examing_area.stage = REVERSE_LEFT; } LoadStageTips(prime); checkCtrlLine = false; } if (checkParkspace) { if (CheckParkspace(prime)) { DEBUG("倒库成功"); } else { DEBUG("倒库不入"); AddExamFault(20103); } parkCount++; if (prime.examing_area.stage == REVERSE_RIGHT) { prime.examing_area.stage = OBVERSE_LEFT; // 从左侧倒库 } else { prime.examing_area.stage = OBVERSE_RIGHT; // 离开场地 } LoadStageTips(prime); checkParkspace = false; } if (BodyCollidingLine(prime)) { if (!occurCrashRedLine) { occurCrashRedLine = true; // 车身出线,不合格 AddExamFault(10116); DEBUG("车身出线"); } } else { occurCrashRedLine = false; } teach(prime); } // 车身或车轮皆不得碰触实线 static bool BodyCollidingLine(prime_t &prime) { MakePolygon car_body(prime.pModel->body.size()); for (int i = 0; i < prime.pModel->body.size(); ++i) { car_body.AddPoint(prime.pModeling[prime.curr_modeling_index].points[prime.pModel->body[i]]); } Line frontAxle, rearAxle; MAKE_LINE(frontAxle, prime.pModeling[prime.curr_modeling_index].points[prime.pModel->left_front_tire[TIRE_OUTSIDE]], prime.pModeling[prime.curr_modeling_index].points[prime.pModel->right_front_tire[TIRE_OUTSIDE]]); MAKE_LINE(rearAxle, prime.pModeling[prime.curr_modeling_index].points[prime.pModel->left_rear_tire[TIRE_OUTSIDE]], prime.pModeling[prime.curr_modeling_index].points[prime.pModel->right_rear_tire[TIRE_OUTSIDE]]); const int red_lines[][2] = {{0, 7}, {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}}; for (int i = 0; i < sizeof(red_lines) / sizeof(red_lines[0]); ++i) { Line red_line; MAKE_LINE(red_line, std::get(prime.maps)[prime.examing_area.idx].points[red_lines[i][0]], std::get(prime.maps)[prime.examing_area.idx].points[red_lines[i][1]]); if (IntersectionOf(red_line, frontAxle) == GM_Intersection || IntersectionOf(red_line, rearAxle) == GM_Intersection || IntersectionOf(red_line, car_body.GetPolygon()) != GM_None) { return true; } } return false; } // 检测2前轮是否正向越过左右控制线 static ctrl_line_t CrossCtrlLine(prime_t &prime) { // 过右控制线 Line left_trace, right_trace; Line left_ctrl, right_ctrl; MAKE_LINE(left_trace, prime.pModeling[prime.curr_modeling_index].points[prime.pModel->left_front_tire[TIRE_OUTSIDE]], prime.pModeling[prime.curr_modeling_index].points[prime.pModel->left_rear_tire[TIRE_OUTSIDE]]); MAKE_LINE(right_trace, prime.pModeling[prime.curr_modeling_index].points[prime.pModel->right_front_tire[TIRE_OUTSIDE]], prime.pModeling[prime.curr_modeling_index].points[prime.pModel->right_rear_tire[TIRE_OUTSIDE]]); MAKE_LINE(left_ctrl, std::get(prime.maps)[prime.examing_area.idx].points[1], std::get(prime.maps)[prime.examing_area.idx].points[0]); MAKE_LINE(right_ctrl, std::get(prime.maps)[prime.examing_area.idx].points[6], std::get(prime.maps)[prime.examing_area.idx].points[7]); if (IntersectionOf(left_trace, left_ctrl) == GM_Intersection && IntersectionOf(right_trace, left_ctrl) == GM_Intersection && IntersectionOfLine(prime.pModeling[prime.curr_modeling_index].points[prime.pModel->left_front_tire[TIRE_OUTSIDE]], left_ctrl) == REL_POS_LEFT) { return LEFT_CTRL_LINE; } if (IntersectionOf(left_trace, right_ctrl) == GM_Intersection && IntersectionOf(right_trace, right_ctrl) == GM_Intersection && IntersectionOfLine(prime.pModeling[prime.curr_modeling_index].points[prime.pModel->left_front_tire[TIRE_OUTSIDE]], right_ctrl) == REL_POS_RIGHT) { return RIGHT_CTRL_LINE; } return NONE_CTRL_LINE; } static bool CheckParkspace(prime_t &prime) { MakePolygon car_body(prime.pModel->body.size()); for (int i = 0; i < prime.pModel->body.size(); ++i) { car_body.AddPoint(prime.pModeling[prime.curr_modeling_index].points[prime.pModel->body[i]]); } MakePolygon park_area({std::get(prime.maps)[prime.examing_area.idx].points[8], std::get(prime.maps)[prime.examing_area.idx].points[3], std::get(prime.maps)[prime.examing_area.idx].points[4], std::get(prime.maps)[prime.examing_area.idx].points[9]}); return (bool) (IntersectionOf(car_body.GetPolygon(), park_area.GetPolygon()) == GM_Containment); }