| | |
| | | #include "../jni_log.h" |
| | | #include "../defs.h" |
| | | #include "../test_common/car_sensor.h" |
| | | #include "../native-lib.h" |
| | | |
| | | #include <vector> |
| | | #include <list> |
| | |
| | | static uint32_t stopTimepoint = 0; |
| | | static bool reportStopCarOnRedArea; |
| | | static PointF stopPoint; |
| | | static bool prevGearError = false; |
| | | static bool prevGearNSlide = false; |
| | | |
| | | static bool slideLongDistance; |
| | | static bool slideNormalDistance; |
| | |
| | | int msec; |
| | | } crashGreenRunTime, crashGreenCmpTime, crashGreenStartTime, turnSignalChangeTime; |
| | | |
| | | static struct drive_timer gearErrorTimePoint; |
| | | static struct drive_timer gearNSlideTimePoint; |
| | | |
| | | static int gearErrorTime; |
| | | static int gearNSlideTime; |
| | | |
| | | static int currExamMapIndex; |
| | | |
| | | static const uint32_t GEAR_N_SLIDE_TIMEOUT = D_SEC(5); |
| | | static const uint32_t GEAR_ERROR_TIMEOUT = D_SEC(15); |
| | | static const uint32_t STOP_CAR_TIME = D_SEC(2); |
| | | static const uint32_t CHANGE_ROAD_MIN_INTERVAL = D_SEC(10); |
| | | static const uint32_t CRASH_DOTTED_LINE_TIMEOUT = D_SEC(10); |
| | | static const uint32_t TURN_SIGNAL_LAMP_ADVANCE = D_SEC(3); |
| | | |
| | | static const double MAX_SPEED = 40.0 * 1000.0 / 3600.0; |
| | | static const int SPEED_SHIFT_TABLE[][2] = {{0, 20}, {5, 30}, {15, 40}, {25, 10000}, {35, 10000}}; |
| | | static const int SPEED_GEAR_TABLE[][2] = {{0, 20}, {5, 30}, {15, 40}, {25, 10000}, {35, 10000}}; |
| | | |
| | | static void Rtk2DirveTimer(struct drive_timer &tm, const struct RtkTime *rtkTime); |
| | | static void Rtk2DriveTimer(struct drive_timer &tm, const struct RtkTime *rtkTime); |
| | | static char isTurn(int currYaw, int prevYaw); |
| | | static char CheckCarTurn(LIST_CAR_MODEL &CarModelList); |
| | | static bool CrashRedLine(LIST_ROAD_MAP &RoadMapList, const car_model *car); |
| | | static bool CrashRedArea(LIST_ROAD_MAP &RoadMapList, const car_model *car); |
| | | static bool CrashGreenLine(LIST_ROAD_MAP &RoadMapList, const car_model *car, PointF &p1, PointF &p2); |
| | | static int CrashTriggerLine(LIST_ROAD_MAP &RoadMapList, const car_model *car, LIST_CAR_MODEL &CarModelList); |
| | | static int FindMapIndexById(int id, LIST_ROAD_MAP &RoadMapList); |
| | | |
| | | void Init(void) |
| | | void InitRoadExam(void) |
| | | { |
| | | crashGreenCmpTime.hour = -1; |
| | | occurCrashRedLine = false; |
| | |
| | | occurSlide = false; |
| | | slideLongDistance = false; |
| | | slideNormalDistance = false; |
| | | prevGearError = false; |
| | | gearErrorTime = 0; |
| | | prevGearNSlide = false; |
| | | gearNSlideTime = 0; |
| | | |
| | | currExamMapIndex = -1; |
| | | } |
| | | |
| | | void TestRoadGeneral(LIST_ROAD_MAP &RoadMapList, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime) |
| | | { |
| | | // 超速检测 |
| | | if (moveDirect != 0 && speed > MAX_SPEED) { |
| | | if (!occurOverSpeed) { |
| | | occurOverSpeed = true; |
| | |
| | | } |
| | | |
| | | // 挡位匹配检测 |
| | | switch (ReadCarStatus(SHIFT)) { |
| | | case SHIFT_N: |
| | | bool currGearError = false; |
| | | bool currGearNSlide = false; |
| | | |
| | | switch (ReadCarStatus(GEAR)) { |
| | | case GEAR_N: |
| | | if (moveDirect != 0) { |
| | | |
| | | // 空档滑行 |
| | | currGearNSlide = true; |
| | | } |
| | | break; |
| | | case SHIFT_1: |
| | | if (ConvertMs2KMs(speed) < SPEED_SHIFT_TABLE[0][0] || ConvertMs2KMs(speed) > SPEED_SHIFT_TABLE[0][1]) { |
| | | |
| | | case GEAR_1: |
| | | if (ConvertMs2KMh(speed) < SPEED_GEAR_TABLE[0][0] || ConvertMs2KMh(speed) > SPEED_GEAR_TABLE[0][1]) { |
| | | currGearError = true; |
| | | } |
| | | break; |
| | | case SHIFT_2: |
| | | case GEAR_2: |
| | | if (ConvertMs2KMh(speed) < SPEED_GEAR_TABLE[1][0] || ConvertMs2KMh(speed) > SPEED_GEAR_TABLE[1][1]) { |
| | | currGearError = true; |
| | | } |
| | | break; |
| | | case SHIFT_3: |
| | | case GEAR_3: |
| | | if (ConvertMs2KMh(speed) < SPEED_GEAR_TABLE[2][0] || ConvertMs2KMh(speed) > SPEED_GEAR_TABLE[2][1]) { |
| | | currGearError = true; |
| | | } |
| | | break; |
| | | case SHIFT_4: |
| | | case GEAR_4: |
| | | if (ConvertMs2KMh(speed) < SPEED_GEAR_TABLE[3][0] || ConvertMs2KMh(speed) > SPEED_GEAR_TABLE[3][1]) { |
| | | currGearError = true; |
| | | } |
| | | break; |
| | | case SHIFT_5: |
| | | case GEAR_5: |
| | | if (ConvertMs2KMh(speed) < SPEED_GEAR_TABLE[4][0] || ConvertMs2KMh(speed) > SPEED_GEAR_TABLE[4][1]) { |
| | | currGearError = true; |
| | | } |
| | | break; |
| | | default:break; |
| | | } |
| | | // 空档滑行超时 |
| | | if (currGearNSlide && prevGearNSlide) { |
| | | gearNSlideTime += TimeGetDiff(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10, |
| | | gearNSlideTimePoint.hour, gearNSlideTimePoint.min, gearNSlideTimePoint.sec, gearNSlideTimePoint.msec*10); |
| | | } |
| | | if (gearNSlideTime > GEAR_N_SLIDE_TIMEOUT) { |
| | | // 空档滑行超5秒,不合格 |
| | | DEBUG("挡位滑行,超过5秒"); |
| | | AddExamFault(8, rtkTime); |
| | | gearNSlideTime = 0; |
| | | } |
| | | |
| | | prevGearNSlide = currGearNSlide; |
| | | if (prevGearNSlide) { |
| | | Rtk2DriveTimer(gearNSlideTimePoint, rtkTime); |
| | | } else { |
| | | gearNSlideTime = 0; |
| | | } |
| | | // 挡位不匹配超时 |
| | | if (currGearError && prevGearError) { |
| | | gearErrorTime += TimeGetDiff(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10, |
| | | gearErrorTimePoint.hour, gearErrorTimePoint.min, gearErrorTimePoint.sec, gearErrorTimePoint.msec*10); |
| | | } |
| | | if (gearErrorTime > GEAR_ERROR_TIMEOUT) { |
| | | // 累计15秒,挡位-车速不匹配,不合格 |
| | | DEBUG("挡位错误超过15秒"); |
| | | AddExamFault(6, rtkTime); |
| | | gearErrorTime = 0; |
| | | } |
| | | |
| | | prevGearError = currGearError; |
| | | if (prevGearError) { |
| | | Rtk2DriveTimer(gearErrorTimePoint, rtkTime); |
| | | } |
| | | |
| | | // 起步后滑 |
| | |
| | | case LEFT_TURN_LIGHT: |
| | | if (currTurnSignalStatus != LEFT_TURN_LIGHT) { |
| | | currTurnSignalStatus = LEFT_TURN_LIGHT; |
| | | Rtk2DirveTimer(turnSignalChangeTime, rtkTime); |
| | | Rtk2DriveTimer(turnSignalChangeTime, rtkTime); |
| | | } |
| | | break; |
| | | case RIGHT_TURN_LIGHT: |
| | | if (currTurnSignalStatus != RIGHT_TURN_LIGHT) { |
| | | currTurnSignalStatus = RIGHT_TURN_LIGHT; |
| | | Rtk2DirveTimer(turnSignalChangeTime, rtkTime); |
| | | Rtk2DriveTimer(turnSignalChangeTime, rtkTime); |
| | | } |
| | | break; |
| | | default: |
| | |
| | | reportTurnSignalError = false; |
| | | } |
| | | |
| | | |
| | | // 撞红线 |
| | | if (CrashRedLine(RoadMapList, car)) { |
| | | if (!occurCrashRedLine) { |
| | | // 车辆行驶中骑轧车道中心实线或者车道边缘实线,不合格 |
| | |
| | | occurCrashRedLine = false; |
| | | } |
| | | |
| | | // 撞绿线 |
| | | static PointF p1, p2; |
| | | |
| | | if (CrashGreenLine(RoadMapList, car, p1, p2)) { |
| | | // 压虚线 |
| | | if (moveDirect != 0) { |
| | | if (checkCrashGreenTimeout == 0) { |
| | | checkCrashGreenTimeout = 1; |
| | | Rtk2DirveTimer(crashGreenRunTime, rtkTime); // 运动中压虚线的开始时间点 |
| | | Rtk2DriveTimer(crashGreenRunTime, rtkTime); // 运动中压虚线的开始时间点 |
| | | } else if (checkCrashGreenTimeout == 1) { |
| | | uint32_t diff = TimeGetDiff(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10, |
| | | crashGreenRunTime.hour, crashGreenRunTime.min, crashGreenRunTime.sec, crashGreenRunTime.msec*10); |
| | |
| | | if (!occurCrashGreenLine) { |
| | | occurCrashGreenLine = true; |
| | | // 记录开始压线的时间,不确定是否有变道意图,待确认变道后再处理之 |
| | | Rtk2DirveTimer(crashGreenStartTime, rtkTime); |
| | | Rtk2DriveTimer(crashGreenStartTime, rtkTime); |
| | | turnSignalStatusWhenCrashGreenLine = currTurnSignalStatus; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // 记录本次变道时间点 |
| | | Rtk2DirveTimer(crashGreenCmpTime, rtkTime); |
| | | Rtk2DriveTimer(crashGreenCmpTime, rtkTime); |
| | | |
| | | // 检查变道前,是否提前转向灯 |
| | | if (inter == 1) { |
| | |
| | | occurCrashGreenLine = false; |
| | | checkCrashGreenTimeout = 0; |
| | | } |
| | | |
| | | // 触发线检测 |
| | | if (currExamMapIndex == -1) { |
| | | currExamMapIndex = CrashTriggerLine(RoadMapList, car, CarModelList); |
| | | if (currExamMapIndex != -1) { |
| | | DEBUG("进入路考子地图 index = %d id = %d item = %d", currExamMapIndex, RoadMapList[currExamMapIndex].id, RoadMapList[currExamMapIndex].type); |
| | | if (!RoadMapList[currExamMapIndex].tts.empty()) { |
| | | PlayTTS(RoadMapList[currExamMapIndex].tts.c_str(), 0); |
| | | } |
| | | } |
| | | } else { |
| | | |
| | | } |
| | | } |
| | | |
| | | static void Rtk2DirveTimer(struct drive_timer &tm, const struct RtkTime *rtkTime) |
| | | static void Rtk2DriveTimer(struct drive_timer &tm, const struct RtkTime *rtkTime) |
| | | { |
| | | tm.hour = rtkTime->hh; |
| | | tm.min = rtkTime->mm; |
| | |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /************************************************************ |
| | | * 检测车辆是否触发子考项地图 |
| | | * @param RoadMapList |
| | | * @param car |
| | | * @param CarModelList |
| | | * @return |
| | | */ |
| | | static int CrashTriggerLine(LIST_ROAD_MAP &RoadMapList, const car_model *car, LIST_CAR_MODEL &CarModelList) |
| | | { |
| | | int map_idx = -1; |
| | | |
| | | if (CarModelList.size() < 5) |
| | | return map_idx; |
| | | |
| | | Polygon trace; |
| | | |
| | | trace.num = 5; |
| | | trace.point = (PointF *) malloc(sizeof(PointF) * trace.num); |
| | | |
| | | list<car_model *>::iterator iter = CarModelList.begin(); |
| | | |
| | | int pn = 0; |
| | | while (iter != CarModelList.end() && pn < trace.num) { |
| | | trace.point[pn++] = ((car_model *)(*iter))->carXY[((car_model *)(*iter))->left_front_tire[TIRE_OUTSIDE]]; |
| | | ++iter; |
| | | } |
| | | |
| | | for (int i = 0; i < RoadMapList.size(); ++i) { |
| | | if (RoadMapList[i].type == 100) { |
| | | |
| | | // 每条线都检测 |
| | | for (int j = 0; j < RoadMapList[i].triggerLineNum; ++j) { |
| | | Line trigger_line; |
| | | |
| | | int kp = 0; |
| | | |
| | | // 触发线一般应该只有首尾2点(id, p1, p2) |
| | | for (int k = 1; k < RoadMapList[i].triggerLine[j].line.num; ++k) { |
| | | MakeLine(&trigger_line, &RoadMapList[i].triggerLine[j].line.point[kp], &RoadMapList[i].triggerLine[j].line.point[k]); |
| | | |
| | | int pp = 1; |
| | | for (int p = 2; p < pn; ++p) { |
| | | Line trace_line; |
| | | MakeLine(&trace_line, &trace.point[pp], &trace.point[p]); |
| | | |
| | | if (IntersectionOf(trace_line, trigger_line) == GM_Intersection && |
| | | IntersectionOfLine(trace.point[pp], trace.point[p], car->carXY[car->left_front_tire[TIRE_OUTSIDE]]) == -1 && |
| | | DistanceOf(car->carXY[car->left_front_tire[TIRE_OUTSIDE]], trace_line) > 0.1) { |
| | | // 碰到触发线 |
| | | map_idx = FindMapIndexById(RoadMapList[i].triggerLine[j].triggerMapId, RoadMapList); |
| | | goto SEARCH_TRIGGER_LINE_END; |
| | | } |
| | | |
| | | pp = p; |
| | | } |
| | | |
| | | kp = k; |
| | | } |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | |
| | | SEARCH_TRIGGER_LINE_END: |
| | | free(trace.point); |
| | | |
| | | return map_idx; |
| | | } |
| | | |
| | | static int FindMapIndexById(int id, LIST_ROAD_MAP &RoadMapList) |
| | | { |
| | | for (int i = 0; i < RoadMapList.size(); ++i) { |
| | | if (RoadMapList[i].id == id) { |
| | | return i; |
| | | } |
| | | } |
| | | return -1; |
| | | } |