// // Created by YY on 2019/10/23. // #include "park_edge.h" #include "../Geometry.h" #include "../driver_test.h" #include "../common/apptimer.h" #include "../native-lib.h" #include #include using namespace std; enum { ARRIVED_START, PARK_CAR, START_CAR }; const int PARK_TIMEOUT = 90; const uint32_t STOP_CAR_TIME = D_SEC(2); static int prev_run_status; static int runStatusBeforeStop; static uint32_t stopTimepoint = 0; static bool parkTimeout; static bool occurCrashRedLine1, occurCrashRedLine2; static bool PETesting = false; static int currTarget; static bool carStopEvent; // 中途停车标记 static bool carParkSuccess; // 是否停在库位 static int leaveParkCnt; // 车辆离开库位刚发生的时,检查是否开启转向灯 static void ParkEdgeTimeout(union sigval sig); static bool CrashRedLine1(const Polygon *map, const car_model_cache_t *car); static bool CrashRedLine2(const Polygon *map, const car_model_cache_t *car); static bool EnterParking(const Polygon *map, const car_model_cache_t *car); static bool ExitParkArea(const Polygon *map, const car_model_cache_t *car); static bool ExitTestArea(const Polygon *map, const car_model_cache_t *car); bool EnterParkEdgeArea(const Polygon *car, const Polygon *tire, const Polygon *map) { if (IntersectionOf(tire->point[0], map) == GM_Containment && IntersectionOf(tire->point[1], map) == GM_Containment && IntersectionOf(tire->point[4], map) == GM_Containment && IntersectionOf(tire->point[5], map) == GM_Containment) { return true; } return false; } void StartParkEdge(void) { prev_run_status = 0; parkTimeout = false; occurCrashRedLine1 = occurCrashRedLine2 = false; // 这个科目规定特殊点,发生一次扣10分,而不直接淘汰 PETesting = true; currTarget = ARRIVED_START; } void StopParkEdge(void) { AppTimer_delete(ParkEdgeTimeout); PETesting = false; } int TestParkEdge(vector&err, const Polygon *map, const car_model_cache_t *car, double speed, int run_status) { int status = 0; if (!PETesting) return 0; if (currTarget >= PARK_CAR) { if (CrashRedLine1(map, car)) { if (!occurCrashRedLine1) { occurCrashRedLine1 = true; // 车轮压边线,每次扣10分 err.push_back(23); } } else { occurCrashRedLine1 = false; } if (CrashRedLine2(map, car)) { if (!occurCrashRedLine2) { occurCrashRedLine2 = true; // 车身压库位线,每次扣10分 err.push_back(24); } } else { occurCrashRedLine2 = false; } if (parkTimeout) { // 超时90秒,不合格 err.push_back(22); status = -1; } if (prev_run_status != run_status) { if (run_status == 0) { // 车停了 runStatusBeforeStop = prev_run_status; stopTimepoint = AppTimer_GetTickCount(); } else { // 车动了,且和停车前的运行状态一致 if (runStatusBeforeStop == run_status && AppTimer_GetTickCount() - stopTimepoint > STOP_CAR_TIME) { // 中途停车,扣5分 err.push_back(26); } } } } if (currTarget == ARRIVED_START) { if (ExitTestArea(map, car)) { // 直接驶离测试区域 status = -2; } else if (run_status < 0) { AppTimer_add(ParkEdgeTimeout, D_SEC(PARK_TIMEOUT)); currTarget = PARK_CAR; TextOsd(0, "开始倒库"); } } else if (currTarget == PARK_CAR) { if (run_status < 0) { carStopEvent = false; } else if (run_status == 0) { // 立即检查是否停车到位,也许是中途停车,先不管,待发生前进事件后,再断定是否停车到位 if (!carStopEvent) { carStopEvent = true; carParkSuccess = EnterParking(map, car); } } else { if (carStopEvent) { if (!carParkSuccess) { // 不合格:车身出线 err.push_back(21); status = -1; } } carStopEvent = false; leaveParkCnt = 0; currTarget = START_CAR; TextOsd(0, "开始出库"); } } else if (currTarget == START_CAR) { if (run_status > 0) { leaveParkCnt++; if (leaveParkCnt == 1) { // 未开启转向灯,扣10分 err.push_back(25); } if (ExitParkArea(map, car)) { // 项目完成 status = 1; TextOsd(0, "项目完成"); } } } if (status != 0) { StopParkEdge(); } prev_run_status = run_status; return status; } static void ParkEdgeTimeout(union sigval sig) { AppTimer_delete(ParkEdgeTimeout); parkTimeout = true; } // 车轮是否压道路边线 static bool CrashRedLine1(const Polygon *map, const car_model_cache_t *car) { bool ret = false; Line red_line; const int red_lines[][2] = {{0, 7}, {1, 2}, {5, 6}}; Line frontAxle, rearAxle; MakeLine(&frontAxle, &car->points[car->desc->front_left_tire[TIRE_OUTSIDE]], &car->points[car->desc->front_right_tire[TIRE_OUTSIDE]]); MakeLine(&rearAxle, &car->points[car->desc->rear_left_tire[TIRE_OUTSIDE]], &car->points[car->desc->rear_right_tire[TIRE_OUTSIDE]]); for (int i = 0; i < sizeof(red_lines) / sizeof(red_lines[0]); ++i) { MakeLine(&red_line, &map->point[red_lines[i][0]], &map->point[red_lines[i][1]]); if (IntersectionOf(red_line, frontAxle) == GM_Intersection || IntersectionOf(red_line, rearAxle) == GM_Intersection) { ret = true; break; } } return ret; } // 车身是否压库位线 static bool CrashRedLine2(const Polygon *map, const car_model_cache_t *car) { bool ret = false; Line red_line; const int red_lines[][2] = {{2, 3}, {3, 4}, {4, 5}}; Polygon car_body; car_body.num = car->desc->body_num; car_body.point = (PointF *) malloc(sizeof(PointF) * car_body.num); for (int i = 0; i < car_body.num; ++i) { car_body.point[i] = car->points[car->desc->body[i]]; } for (int i = 0; i < sizeof(red_lines) / sizeof(red_lines[0]); ++i) { MakeLine(&red_line, &map->point[red_lines[i][0]], &map->point[red_lines[i][1]]); if (IntersectionOf(red_line, &car_body) != GM_None) { ret = true; break; } } free(car_body.point); return ret; } static bool EnterParking(const Polygon *map, const car_model_cache_t *car) { bool succ = false; Polygon parking; Polygon car_body; car_body.num = car->desc->body_num; car_body.point = (PointF *) malloc(sizeof(PointF) * car_body.num); for (int i = 0; i < car_body.num; ++i) { car_body.point[i] = car->points[car->desc->body[i]]; } MakePolygon(&parking, {map->point[2], map->point[3], map->point[4], map->point[5]}); if (IntersectionOf(&car_body, &parking) == GM_Containment) { succ = true; } CleanPolygon(&parking); free(car_body.point); return succ; } // 整个车辆都要驶过前库位线 static bool ExitParkArea(const Polygon *map, const car_model_cache_t *car) { for (int i = 0; i < car->point_num; ++i) { if (IntersectionOfLine(map->point[4], map->point[5], car->points[i]) != -1) return false; } return true; } // 整个车辆都要驶过最前端控制线 static bool ExitTestArea(const Polygon *map, const car_model_cache_t *car) { for (int i = 0; i < car->point_num; ++i) { if (IntersectionOfLine(map->point[6], map->point[7], car->points[i]) != -1) return false; } return true; }