| | |
| | | #include "operate_gear.h" |
| | | #include "../test_common/odo_graph.h" |
| | | #include "car_start.h" |
| | | #include "overtake.h" |
| | | #include "change_lane.h" |
| | | |
| | | #include <cmath> |
| | | #include <vector> |
| | |
| | | |
| | | using namespace std; |
| | | |
| | | #define TURN_CHECK_CNT 6 |
| | | |
| | | enum { |
| | | START_CAR_NOT_DO, |
| | | START_CAR_DOING, |
| | | START_CAR_DONE |
| | | }; |
| | | |
| | | enum { |
| | | STOP_CAR_NOT_DO, |
| | | STOP_CAR_DOING, |
| | | STOP_CAR_DONE |
| | | }; |
| | | |
| | | enum { |
| | | CROSSING_NOT_HINT, |
| | |
| | | |
| | | static const int CROSSING_TURN_THRESHOLD = 45; |
| | | static const int TURN_THRESHOLD = 3; |
| | | static const int TURN_CHECK_INTERVAL = 500; |
| | | |
| | | const double SLIDE_DISTANCE_THRESHOLD_RED = 0.3; |
| | | const double SLIDE_DISTANCE_THRESHOLD_YELLOW = 0.1; |
| | | const double CHANGE_LANE_RANGE = 100.0; |
| | | const double OVERTAKE_RANGE = 150.0; |
| | | const int OVERTAKE_HOLD_TIME = D_SEC(3); // 在超车道行驶的一段时间 |
| | | |
| | | const double EXAM_RANGE = 3000.0; // 至少驾驶距离 |
| | | |
| | | static const double NEXT_ROAD_TIP = 100.0; // 到达路口前提示下一个怎么走 |
| | | |
| | | |
| | | static bool occurCrashRedLine; |
| | | static bool occurCrashGreenLine; |
| | | static bool occurOverSpeed; |
| | | static bool occurSecondBreak; |
| | | |
| | | static char carIntersectionOfGreenLine; |
| | | static int currTurnSignalStatus; |
| | | static int turnSignalStatusWhenCrashGreenLine; |
| | | |
| | | static int prevMoveDirect; |
| | | static uint32_t stopTimepoint = 0; |
| | |
| | | |
| | | static struct drive_timer gearErrorTimePoint; |
| | | static struct drive_timer gearNSlideTimePoint; |
| | | static struct drive_timer startCarLeftTurnSignalTime; |
| | | static struct drive_timer overTakeCmpTime; |
| | | |
| | | static int gearErrorTime; |
| | | static int gearNSlideTime; |
| | | |
| | | static int stopCar; |
| | | static int currExamMapIndex; |
| | | static trigger_line_t *currRoadItem; |
| | | static PointF roadItemStartPoint; |
| | | static struct drive_timer roadItemStartTime; |
| | | static bool overtake = false; |
| | | static bool checkTurn = false; |
| | | |
| | | static lane_t Lane; |
| | | static change_lane_t ChangeLane; |
| | |
| | | static const uint32_t CRASH_DOTTED_LINE_TIMEOUT = D_SEC(10); |
| | | static const uint32_t TURN_SIGNAL_LAMP_ADVANCE = D_SEC(3); |
| | | |
| | | static const int CRL_NONE = 0; |
| | | static const int CRL_SEP_DOTTED = 1; |
| | | static const int CRL_SEP_SOLID = 2; |
| | | static const int CRL_EDGE_DOTTED = 3; |
| | | static const int CRL_EDGE_SOLID = 4; |
| | | |
| | | static const double MAX_SPEED = 60.0 * 1000.0 / 3600.0; |
| | | static const double MAX_SPEED = 60.0 * 1000.0 / 3600.0; // 超速确认 |
| | | static const double DEC_MAX_SPEED = 55.0 * 1000.0 / 3600.0; // 超速取消 |
| | | static const int SPEED_GEAR_TABLE[][2] = {{0, 20}, {5, 30}, {15, 40}, {25, 10000}, {35, 10000}}; |
| | | |
| | | static void ItemExam(road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime, double straight, double road_end); |
| | | static void ItemExam(road_exam_map &RoadMap, int roadIndex, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime, double straight, double road_end); |
| | | static int isTurn(int currYaw, int prevYaw, int thres); |
| | | static void ResetTurnDetect(const car_model *car); |
| | | static void DetectTurn(const car_model *car, int moveDirect, const struct RtkTime *rtkTime); |
| | |
| | | static int NearbyCrossingGuide(int &stopLineIndex, int roadIndex, road_t &road, const car_model *car); |
| | | |
| | | static trigger_line_t * EntryItem(int index, road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList); |
| | | |
| | | static bool AllCmp(road_exam_map &map); |
| | | |
| | | static int CalcRoadIndex(int currRoadIndex, road_exam_map &RoadMap, const car_model *car); |
| | | |
| | |
| | | { |
| | | DEBUG("Start road_exam"); |
| | | |
| | | occurCrashRedLine = false; |
| | | occurCrashGreenLine = false; |
| | | occurOverSpeed = false; |
| | | |
| | | occurSecondBreak = false; |
| | | |
| | | carIntersectionOfGreenLine = 0; |
| | | |
| | | currTurnSignalStatus = OFF_LIGHT; |
| | | prevMoveDirect = 0; |
| | | |
| | | reportStopCarOnRedArea = false; |
| | |
| | | |
| | | currExamMapIndex = -1; |
| | | |
| | | stopCar = STOP_CAR_NOT_DO; |
| | | |
| | | currRoadItem = NULL; |
| | | |
| | | Lane.road = Lane.sep = Lane.no = -1; |
| | | Lane.guide = 0; |
| | | |
| | | checkTurn = false; |
| | | |
| | | CrashLineType = -1; |
| | | turnCnt = -1; |
| | |
| | | DEBUG("变调未打灯!!"); |
| | | // 没打灯,不合格 |
| | | AddExamFault(13, rtkTime); |
| | | } else if (TimeGetDiff(&crashGreenStartTime, &lamp.time) >= D_SEC(3)) { |
| | | } else if (TimeGetDiff(&crashGreenStartTime, &lamp.time) >= TURN_SIGNAL_LAMP_ADVANCE) { |
| | | DEBUG("转向灯时间不足"); |
| | | // 不足3秒,不合格 |
| | | AddExamFault(14, rtkTime); |
| | |
| | | DEBUG("变调未打灯!!"); |
| | | // 没打灯,不合格 |
| | | AddExamFault(13, rtkTime); |
| | | } else if (TimeGetDiff(&crashGreenStartTime, &lamp.time) >= D_SEC(3)) { |
| | | } else if (TimeGetDiff(&crashGreenStartTime, &lamp.time) >= TURN_SIGNAL_LAMP_ADVANCE) { |
| | | DEBUG("转向灯时间不足"); |
| | | // 不足3秒,不合格 |
| | | AddExamFault(14, rtkTime); |
| | |
| | | return guide; |
| | | } |
| | | |
| | | static uint8_t itemExec[4] = {0}; |
| | | static double odo; |
| | | |
| | | void TestRoadGeneral(road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime) |
| | | { |
| | | double BigStraightRoadFree = 0, RoadCrossingFree = 0; |
| | |
| | | UpdataOdo(speed, moveDirect, rtkTime); |
| | | |
| | | // 超速检测 |
| | | if (moveDirect != 0 && speed > MAX_SPEED) { |
| | | if (speed > MAX_SPEED) { |
| | | if (!occurOverSpeed) { |
| | | occurOverSpeed = true; |
| | | // 超速,不合格 |
| | | DEBUG("超速 %f", speed); |
| | | DEBUG("超速 %f", ConvertMs2KMh(speed)); |
| | | AddExamFault(10, rtkTime); |
| | | } |
| | | } else { |
| | | } else if (speed < DEC_MAX_SPEED ) { |
| | | occurOverSpeed = false; |
| | | } |
| | | |
| | |
| | | |
| | | RoadCrossingFree = freeSepDis; |
| | | |
| | | DEBUG("直道剩余距离 %f, 车道剩余距离 %f", BigStraightRoadFree, RoadCrossingFree); |
| | | // DEBUG("累计行驶距离 %f, 直道剩余距离 %f, 车道剩余距离 %f", ReadOdo(), BigStraightRoadFree, RoadCrossingFree); |
| | | } |
| | | |
| | | // 检测压线状态 |
| | |
| | | // 额外的转向检测 |
| | | DetectTurn(car, moveDirect, rtkTime); |
| | | |
| | | ItemExam(RoadMap, car, CarModelList, speed, moveDirect, rtkTime, BigStraightRoadFree, RoadCrossingFree); |
| | | |
| | | if (ReadOdo() > EXAM_RANGE && currRoadItem == NULL && AllCmp(RoadMap) && stopCar == STOP_CAR_NOT_DO) { |
| | | // 在合适条件下停车结束考试 |
| | | StartStopCarExam("请靠边停车"); |
| | | stopCar = STOP_CAR_DOING; |
| | | } else if (stopCar == STOP_CAR_DOING) { |
| | | if (ExecuteStopCarExam(RoadMap.roads[currExamMapIndex], car, CarModelList, speed, moveDirect, rtkTime) < 0) |
| | | stopCar = STOP_CAR_DONE; |
| | | } |
| | | |
| | | // 执行某个项目 |
| | | /*if (currRoadItem != NULL) { |
| | | if (currRoadItem->active == ROAD_ITEM_CHANGE_LANE) { |
| | | if (DistanceOf(car->basePoint, roadItemStartPoint) > CHANGE_LANE_RANGE) { |
| | | DEBUG("变道距离超标"); |
| | | AddExamFault(3, rtkTime); |
| | | currRoadItem = NULL; |
| | | } |
| | | } else if (currRoadItem->active == ROAD_ITEM_OVERTAKE) { |
| | | if (!overtake && DistanceOf(car->basePoint, roadItemStartPoint) > OVERTAKE_RANGE) { |
| | | DEBUG("超车距离超标"); |
| | | AddExamFault(3, rtkTime); |
| | | currRoadItem = NULL; |
| | | } else if (overtake && TimeGetDiff(rtkTime->hh, rtkTime->mm, rtkTime->ss, |
| | | rtkTime->mss * 10, |
| | | overTakeCmpTime.hour, overTakeCmpTime.min, |
| | | overTakeCmpTime.sec, overTakeCmpTime.msec * 10) > OVERTAKE_HOLD_TIME) { |
| | | DEBUG("回原车道"); |
| | | PlayTTS("请返回原车道"); |
| | | currRoadItem = NULL; |
| | | } |
| | | } else if (currRoadItem->active == ROAD_ITEM_OPERATE_GEAR) { |
| | | if (ExecuteOperateGearExam(rtkTime) < 0) { |
| | | currRoadItem = NULL; |
| | | } |
| | | } else if (currRoadItem->active == ROAD_ITEM_STRAIGHT) { |
| | | if (ExecuteDriveStraightExam(RoadMap.roads[currExamMapIndex], car, currRoadItem, rtkTime) < 0) { |
| | | currRoadItem = NULL; |
| | | } |
| | | } |
| | | } // 检测由触发线控制的项目 |
| | | else if (currExamMapIndex >= 0) { |
| | | trigger_line_t *new_item = EntryItem(currExamMapIndex, RoadMap, car, CarModelList); |
| | | |
| | | if (new_item != NULL && !new_item->cmp) { |
| | | currRoadItem = new_item; |
| | | if (!currRoadItem->tts.empty()) |
| | | PlayTTS(currRoadItem->tts.c_str()); |
| | | |
| | | // 初始时间和距离限制 |
| | | roadItemStartPoint = car->basePoint; |
| | | Rtk2DriveTimer(roadItemStartTime, rtkTime); |
| | | |
| | | if (currRoadItem->active == ROAD_ITEM_OVERTAKE) { |
| | | overtake = false; |
| | | } else if (currRoadItem->active == ROAD_ITEM_OPERATE_GEAR) { |
| | | StartOperateGearExam(rtkTime); |
| | | } else if (currRoadItem->active == ROAD_ITEM_STRAIGHT) { |
| | | StartDriveStraightExam(currRoadItem->tts); |
| | | } |
| | | } |
| | | }*/ |
| | | ItemExam(RoadMap, currExamMapIndex, car, CarModelList, speed, moveDirect, rtkTime, BigStraightRoadFree, RoadCrossingFree); |
| | | } |
| | | |
| | | static void ItemExam(road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime, double straight, double road_end) |
| | | static void ItemExam(road_exam_map &RoadMap, int roadIndex, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime, double straight, double road_end) |
| | | { |
| | | static double freeRunDistance; |
| | | static double totalRunDistance; |
| | | static double freeRunExceptDistance = 50.0; |
| | | |
| | | if (RoadExamStatus == ROAD_EXAM_READY_NEXT) { |
| | | if (RoadExamItem[ROAD_EXAM_ITEM_CAR_START] == ROAD_EXAM_ITEM_NOT_EXEC) { |
| | |
| | | totalRunDistance = ReadOdo(); |
| | | RoadExamStatus = ROAD_EXAM_ITEM_CAR_START; |
| | | } else { |
| | | if (RoadExamItem[ROAD_EXAM_ITEM_STRAIGHT] == ROAD_EXAM_ITEM_NOT_EXEC) { |
| | | if (straight > 170 && road_end > 170) { |
| | | bool not_complete = false; |
| | | |
| | | if (RoadExamItem[ROAD_EXAM_ITEM_STRAIGHT] == ROAD_EXAM_ITEM_NOT_EXEC) { |
| | | not_complete = true; |
| | | if (straight > 170 && road_end > 170) { |
| | | StartDriveStraightExam(); |
| | | RoadExamStatus = ROAD_EXAM_ITEM_STRAIGHT; |
| | | return; |
| | | } |
| | | } |
| | | if (RoadExamItem[ROAD_EXAM_ITEM_OP_GEAR] == ROAD_EXAM_ITEM_NOT_EXEC) { |
| | | if (straight > 150 && road_end > 150) { |
| | | not_complete = true; |
| | | if (road_end > 170) { |
| | | StartOperateGearExam(); |
| | | RoadExamStatus = ROAD_EXAM_ITEM_OP_GEAR; |
| | | return; |
| | | } |
| | | } |
| | | if (RoadExamItem[ROAD_EXAM_ITEM_CHANGE_LANE] == ROAD_EXAM_ITEM_NOT_EXEC) { |
| | | |
| | | not_complete = true; |
| | | if (road_end > 150 && Lane.total > 1) { |
| | | StartChaneLaneExam(Lane.no); |
| | | RoadExamStatus = ROAD_EXAM_ITEM_CHANGE_LANE; |
| | | return; |
| | | } |
| | | } |
| | | if (RoadExamItem[ROAD_EXAM_ITEM_OVER_TAKE] == ROAD_EXAM_ITEM_NOT_EXEC) { |
| | | |
| | | not_complete = true; |
| | | if (road_end > 200 && Lane.total > 1) { |
| | | if (Lane.no == 0) { |
| | | // 已在最左车道,先变更车道? |
| | | StartChaneLaneExam(Lane.no); |
| | | RoadExamStatus = ROAD_EXAM_ITEM_CHANGE_LANE; |
| | | } else { |
| | | StartOvertakeExam(Lane.no); |
| | | RoadExamStatus = ROAD_EXAM_ITEM_OVER_TAKE; |
| | | } |
| | | return; |
| | | } |
| | | } |
| | | |
| | | if (!not_complete) { |
| | | if (road_end > 200 && ReadOdo() > EXAM_RANGE) { |
| | | RoadExamStatus = ROAD_EXAM_ITEM_CAR_STOP; |
| | | StartStopCarExam(); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | } else if (RoadExamStatus == ROAD_EXAM_FREE_RUN) { |
| | | if (ReadOdo() - freeRunDistance > 300) { |
| | | if (ReadOdo() - freeRunDistance > freeRunExceptDistance) { |
| | | RoadExamStatus = ROAD_EXAM_READY_NEXT; |
| | | |
| | | } |
| | | } else { |
| | | bool testing = false; |
| | |
| | | case ROAD_EXAM_ITEM_OP_GEAR: |
| | | testing = TestOperateGear(rtkTime); |
| | | break; |
| | | case ROAD_EXAM_ITEM_CHANGE_LANE: |
| | | testing = TestChangeLane(Lane.no, rtkTime); |
| | | break; |
| | | case ROAD_EXAM_ITEM_OVER_TAKE: |
| | | testing = TestOvertake(Lane.no, rtkTime); |
| | | break; |
| | | case ROAD_EXAM_ITEM_STRAIGHT: |
| | | testing = TestDriveStraight(car, rtkTime); |
| | | break; |
| | | case ROAD_EXAM_ITEM_CAR_STOP: |
| | | testing = TestStopCar(RoadMap, roadIndex, car, moveDirect, rtkTime); |
| | | break; |
| | | default:break; |
| | | } |
| | | |
| | | if (!testing) { |
| | | RoadExamItem[RoadExamStatus] = ROAD_EXAM_ITEM_EXECED; |
| | | if (RoadExamStatus == ROAD_EXAM_ITEM_CAR_START) { |
| | | freeRunExceptDistance = 60.0; |
| | | } else { |
| | | freeRunExceptDistance = 200.0; |
| | | } |
| | | |
| | | RoadExamStatus = ROAD_EXAM_FREE_RUN; |
| | | freeRunDistance = ReadOdo(); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | void Rtk2DriveTimer(struct drive_timer &tm, const struct RtkTime *rtkTime) |
| | |
| | | DEBUG("变调未打灯!!"); |
| | | // 没打灯,不合格 |
| | | AddExamFault(13, rtkTime); |
| | | } else if (TimeGetDiff(&beginTurnTime, &lamp.time) >= D_SEC(3)) { |
| | | } else if (TimeGetDiff(&beginTurnTime, &lamp.time) >= TURN_SIGNAL_LAMP_ADVANCE) { |
| | | DEBUG("转向灯时间不足"); |
| | | // 不足3秒,不合格 |
| | | AddExamFault(14, rtkTime); |
| | |
| | | DEBUG("变调未打灯!!"); |
| | | // 没打灯,不合格 |
| | | AddExamFault(13, rtkTime); |
| | | } else if (TimeGetDiff(&beginTurnTime, &lamp.time) >= D_SEC(3)) { |
| | | } else if (TimeGetDiff(&beginTurnTime, &lamp.time) >= TURN_SIGNAL_LAMP_ADVANCE) { |
| | | DEBUG("转向灯时间不足"); |
| | | // 不足3秒,不合格 |
| | | AddExamFault(14, rtkTime); |
| | |
| | | } |
| | | |
| | | return NULL; |
| | | } |
| | | |
| | | static bool AllCmp(road_exam_map &map) |
| | | { |
| | | for (int i = 0; i < map.triggerLines.size(); ++i) { |
| | | if (!map.triggerLines[i].cmp) |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | static double AnalysisRoad(road_exam_map &RoadMap, int roadIndex, lane_t lane, const car_model *car) |