| | |
| | | #include "stop_car.h" |
| | | #include "operate_gear.h" |
| | | #include "../test_common/odo_graph.h" |
| | | #include "car_start.h" |
| | | |
| | | #include <cmath> |
| | | #include <vector> |
| | |
| | | PointF point; |
| | | } projection_t; |
| | | |
| | | typedef struct |
| | | { |
| | | int name; |
| | | int value; |
| | | struct RtkTime time; |
| | | } car_sensor_value_t; |
| | | |
| | | typedef struct { |
| | | int gain; |
| | | struct RtkTime time; |
| | |
| | | |
| | | static const int INVALID_ROAD = -1; |
| | | |
| | | 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; |
| | |
| | | static int prevMoveDirect; |
| | | static uint32_t stopTimepoint = 0; |
| | | static bool reportStopCarOnRedArea; |
| | | static PointF stopPoint, startPoint; |
| | | static PointF stopPoint; |
| | | static bool prevGearError = false; |
| | | static bool prevGearNSlide = false; |
| | | |
| | | static bool slideLongDistance; |
| | | static bool slideNormalDistance; |
| | | static bool occurSlide; |
| | | static bool startCarLeftTurnSignal, checkStartCarSignal; |
| | | |
| | | static struct RtkTime crashGreenRunTime, crashGreenStartTime; |
| | | |
| | |
| | | static int gearErrorTime; |
| | | static int gearNSlideTime; |
| | | |
| | | static int startCar, stopCar; |
| | | 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 bool checkDoor = false; |
| | | static bool handBreakActive = false; |
| | | static bool reportRPMOver = false; |
| | | |
| | | static lane_t Lane; |
| | | static change_lane_t ChangeLane; |
| | |
| | | static map<int, int> CrossingHint; |
| | | static map<int, bool> ErrorLaneReport; |
| | | |
| | | #define ROAD_EXAM_READY_NEXT 0 |
| | | #define ROAD_EXAM_FREE_RUN 1 |
| | | #define ROAD_EXAM_ITEM_CAR_START 2 |
| | | #define ROAD_EXAM_ITEM_STRAIGHT 3 |
| | | #define ROAD_EXAM_ITEM_OP_GEAR 4 |
| | | #define ROAD_EXAM_ITEM_CHANGE_LANE 5 |
| | | #define ROAD_EXAM_ITEM_OVER_TAKE 6 |
| | | #define ROAD_EXAM_ITEM_CAR_STOP 7 |
| | | |
| | | #define ROAD_EXAM_ITEM_NOT_EXEC 0 |
| | | #define ROAD_EXAM_ITEM_EXECING 1 |
| | | #define ROAD_EXAM_ITEM_EXECED 2 |
| | | |
| | | |
| | | typedef struct { |
| | | int name; |
| | | int status; |
| | | } RoadExamItem_t; |
| | | static map<int, int> RoadExamItem; |
| | | static int RoadExamStatus; |
| | | |
| | | static struct RtkTime beginTurnTime, prevDetectTurnTime; |
| | | static int startTurnYaw, prevYaw; |
| | | static int turnCnt, turnTimeCnt; |
| | | static int prevTurnWise; |
| | | |
| | | static const int MAX_ENGINE_RPM = 2500; |
| | | static const double START_CAR_MOVE_DISTANCE = 10.0; |
| | | static const double START_CAR_CHECK_DOOR_DISTANCE = 1.0; |
| | | 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 double MAX_SPEED = 60.0 * 1000.0 / 3600.0; |
| | | static const int SPEED_GEAR_TABLE[][2] = {{0, 20}, {5, 30}, {15, 40}, {25, 10000}, {35, 10000}}; |
| | | |
| | | static int TestRoadStartCar(const car_model *car, double speed, int moveDirect, const struct RtkTime *rtkTime); |
| | | |
| | | 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 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); |
| | |
| | | |
| | | currExamMapIndex = -1; |
| | | |
| | | startCar = START_CAR_NOT_DO; |
| | | stopCar = STOP_CAR_NOT_DO; |
| | | |
| | | currRoadItem = NULL; |
| | | |
| | | checkDoor = false; |
| | | handBreakActive = false; |
| | | reportRPMOver = false; |
| | | |
| | | checkStartCarSignal = startCarLeftTurnSignal = false; |
| | | |
| | | Lane.road = Lane.sep = Lane.no = -1; |
| | | Lane.guide = 0; |
| | |
| | | ResetOdo(); |
| | | ResetTarget(RoadMap); |
| | | // 初始化考项 |
| | | RoadExamItem.clear(); |
| | | RoadExamItem[ROAD_EXAM_ITEM_CAR_START] = ROAD_EXAM_ITEM_NOT_EXEC; |
| | | RoadExamItem[ROAD_EXAM_ITEM_STRAIGHT] = ROAD_EXAM_ITEM_NOT_EXEC; |
| | | RoadExamItem[ROAD_EXAM_ITEM_OP_GEAR] = ROAD_EXAM_ITEM_NOT_EXEC; |
| | | RoadExamItem[ROAD_EXAM_ITEM_CHANGE_LANE] = ROAD_EXAM_ITEM_NOT_EXEC; |
| | | RoadExamItem[ROAD_EXAM_ITEM_OVER_TAKE] = ROAD_EXAM_ITEM_NOT_EXEC; |
| | | RoadExamItem[ROAD_EXAM_ITEM_CAR_STOP] = ROAD_EXAM_ITEM_NOT_EXEC; |
| | | |
| | | RoadExamStatus = ROAD_EXAM_READY_NEXT; |
| | | } |
| | | |
| | | void TerminateRoadExam(void) |
| | | { |
| | | TerminateDummyLightExam(); |
| | | TerminateStopCarExam(); |
| | | TerminateOperateGearExam(); |
| | | TerminateDriveStraightExam(); |
| | | // TerminateDummyLightExam(); |
| | | // TerminateStopCarExam(); |
| | | // TerminateOperateGearExam(); |
| | | // TerminateDriveStraightExam(); |
| | | } |
| | | |
| | | /********************************************************************* |
| | |
| | | } |
| | | } |
| | | |
| | | static car_sensor_value_t ReadCarSensorValue(int name) |
| | | car_sensor_value_t ReadCarSensorValue(int name) |
| | | { |
| | | car_sensor_value_t nv = {.name = -1}; |
| | | |
| | |
| | | WriteCarSensorValue(SECOND_BREAK, ReadCarStatus(SECOND_BREAK), rtkTime); |
| | | WriteCarSensorValue(GEAR, ReadCarStatus(GEAR), rtkTime); |
| | | WriteCarSensorValue(BREAK, ReadCarStatus(BREAK), rtkTime); |
| | | } |
| | | |
| | | static int TestRoadStartCar(const car_model *car, double speed, int moveDirect, const struct RtkTime *rtkTime) |
| | | { |
| | | double moveDistance; |
| | | |
| | | if (startCar == START_CAR_NOT_DO) { |
| | | startPoint = car->basePoint; |
| | | reportRPMOver = false; |
| | | startCar = START_CAR_DOING; |
| | | |
| | | PlayTTS("请起步"); |
| | | } else if (startCar == START_CAR_DOING) { |
| | | moveDistance = DistanceOf(startPoint, car->basePoint); |
| | | DEBUG("起步行驶距离 %f", moveDistance); |
| | | |
| | | if (!startCarLeftTurnSignal && ReadCarStatus(TURN_SIGNAL_LAMP) == LEFT_TURN_LIGHT) { |
| | | startCarLeftTurnSignal = true; |
| | | Rtk2DriveTimer(startCarLeftTurnSignalTime, rtkTime); |
| | | } |
| | | |
| | | if (!checkStartCarSignal && moveDirect == 1) { |
| | | checkStartCarSignal = true; |
| | | if (!startCarLeftTurnSignal) { |
| | | AddExamFault(13, rtkTime); |
| | | } else if (TimeGetDiff(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10, |
| | | startCarLeftTurnSignalTime.hour, startCarLeftTurnSignalTime.min, startCarLeftTurnSignalTime.sec, startCarLeftTurnSignalTime.msec*10) < TURN_SIGNAL_LAMP_ADVANCE) { |
| | | AddExamFault(14, rtkTime); |
| | | } |
| | | } |
| | | |
| | | if (moveDistance > START_CAR_MOVE_DISTANCE) { |
| | | if (ReadCarStatus(HAND_BREAK) == BREAK_ACTIVE) { |
| | | DEBUG("Handbreak active move over 10m"); |
| | | // 手刹拉起状态下,行驶了10米以上,不合格 |
| | | AddExamFault(25, rtkTime); |
| | | } else if (handBreakActive) { |
| | | // 手刹拉起状态下,行驶了1米以上,扣10分 |
| | | DEBUG("Handbreak active move over 1M"); |
| | | AddExamFault(26, rtkTime); |
| | | } |
| | | |
| | | PlayTTS("完成起步"); |
| | | DEBUG("############# 完成起步 ############"); |
| | | startCar = START_CAR_DONE; |
| | | } else if (moveDistance >= START_CAR_CHECK_DOOR_DISTANCE) { |
| | | if (!checkDoor) { |
| | | checkDoor = true; |
| | | |
| | | if (ReadCarStatus(DOOR) == DOOR_OPEN) { |
| | | // 车门未完全关闭,不合格 |
| | | DEBUG("车门未关闭"); |
| | | AddExamFault(23, rtkTime); |
| | | } |
| | | |
| | | if (ReadCarStatus(HAND_BREAK) == BREAK_ACTIVE) { |
| | | handBreakActive = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (ReadCarStatus(ENGINE_RPM) > MAX_ENGINE_RPM && !reportRPMOver) { |
| | | // 转速超标,不合格 |
| | | DEBUG("转速超标"); |
| | | AddExamFault(29, rtkTime); |
| | | reportRPMOver = true; |
| | | } |
| | | } else { |
| | | |
| | | } |
| | | |
| | | return startCar; |
| | | } |
| | | |
| | | static void DetectLine(int roadIndex, road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, int moveDirect, const struct RtkTime *rtkTime) |
| | |
| | | if (GetCrossingStatus(roadIndex, stopIndex) == CROSSING_NOT_HINT) { |
| | | if (!RoadMap.roads[roadIndex].stopLine[stopIndex].tts.empty()) { |
| | | DEBUG("路口提示 %s", RoadMap.roads[roadIndex].stopLine[stopIndex].tts.c_str()); |
| | | PlayTTS(RoadMap.roads[roadIndex].stopLine[stopIndex].tts.c_str()); |
| | | PlayTTS(RoadMap.roads[roadIndex].stopLine[stopIndex].tts.c_str(), NULL); |
| | | } |
| | | ChangeCrossingStatus(roadIndex, stopIndex, CROSSING_HAS_HINT); |
| | | } |
| | |
| | | |
| | | void TestRoadGeneral(road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime) |
| | | { |
| | | // uint32_t cts = AppTimer_GetTickCount(); |
| | | // int ri = CalcRoadIndex(-1, RoadMap, car); |
| | | // bool crash = CrashRedLine(CrashLineType, 0, RoadMap, car, CarModelList); |
| | | // lane_t laneInfo; |
| | | // double redist = -1; |
| | | // |
| | | // laneInfo.road = -1; |
| | | // laneInfo.sep = -1; |
| | | // laneInfo.no = -1; |
| | | // |
| | | // if (ri >= 0) { |
| | | // GetLane(laneInfo, car->carXY[car->axial[AXIAL_FRONT]], RoadMap, ri); |
| | | // |
| | | // int m = RoadMap.roads[ri].rightEdge.size(); |
| | | // int n = RoadMap.roads[ri].rightEdge[m-1].points.size(); |
| | | // |
| | | // PointF base; |
| | | // |
| | | // base.X = 428922.2985; base.Y = 3292119.5457; |
| | | // |
| | | // redist = CalcDistanceReference(car->carXY[car->axial[AXIAL_FRONT]], base, |
| | | // RoadMap.roads[ri].rightEdge); |
| | | // } |
| | | // |
| | | // DEBUG("当前道路索引 %d, 触发红线 %d lane %d 距离 %f %ld", ri, crash, laneInfo.no, redist, AppTimer_GetTickCount() - cts); |
| | | double BigStraightRoadFree = 0, RoadCrossingFree = 0; |
| | | |
| | | UpdateCarSensor(rtkTime); |
| | | |
| | |
| | | } |
| | | |
| | | if (currExamMapIndex >= 0 && Lane.guide == 0) { |
| | | double BigStraightRoad = AnalysisRoad(RoadMap, currExamMapIndex, Lane, car); |
| | | BigStraightRoadFree = AnalysisRoad(RoadMap, currExamMapIndex, Lane, car); |
| | | |
| | | road_end_point_t ep = NearbyRoadEndPoint(currExamMapIndex, RoadMap, car); |
| | | |
| | |
| | | freeSepDis = ep.distance; |
| | | } |
| | | |
| | | DEBUG("直道剩余距离 %f, 车道剩余距离 %f", BigStraightRoad, freeSepDis); |
| | | RoadCrossingFree = freeSepDis; |
| | | |
| | | if (startCar == START_CAR_DONE) { |
| | | if (itemExec[0] == 1 || itemExec[1] == 1 || itemExec[2] == 1 || itemExec[3] == 1) { |
| | | |
| | | DEBUG("项目执行距离<%d %d %d %d> %f", itemExec[0], itemExec[1], itemExec[2], itemExec[3], ReadOdo() - odo); |
| | | |
| | | if (ReadOdo() - odo > 120) { |
| | | odo = ReadOdo(); |
| | | if (itemExec[0] == 1) { |
| | | itemExec[0] = 2; |
| | | } |
| | | if (itemExec[1] == 1) { |
| | | itemExec[1] = 2; |
| | | } |
| | | if (itemExec[2] == 1) { |
| | | itemExec[2] = 2; |
| | | } |
| | | if (itemExec[3] == 1) { |
| | | itemExec[3] = 2; |
| | | } |
| | | } |
| | | goto BIG_DOG; |
| | | } |
| | | |
| | | if (itemExec[0] == 2 || itemExec[1] == 2 || itemExec[2] == 2 || itemExec[3] == 2) { |
| | | DEBUG("项目休息距离<%d %d %d %d> %f", itemExec[0], itemExec[1], itemExec[2], itemExec[3], ReadOdo() - odo); |
| | | |
| | | if (ReadOdo() - odo > 100) { |
| | | if (itemExec[0] == 2) { |
| | | itemExec[0] = 3; |
| | | } |
| | | if (itemExec[1] == 2) { |
| | | itemExec[1] = 3; |
| | | } |
| | | if (itemExec[2] == 2) { |
| | | itemExec[2] = 3; |
| | | } |
| | | if (itemExec[3] == 2) { |
| | | itemExec[3] = 3; |
| | | } |
| | | } |
| | | goto BIG_DOG; |
| | | } |
| | | |
| | | |
| | | if (BigStraightRoad > 170 && ep.distance > 170) { |
| | | if (itemExec[0] == 0) { |
| | | PlayTTS("二狗直线行驶"); |
| | | itemExec[0] = 1; |
| | | odo = ReadOdo(); |
| | | } |
| | | } else if (BigStraightRoad > 150 && ep.distance > 150) { |
| | | if (itemExec[3] == 0) { |
| | | PlayTTS("二狗加减档"); |
| | | itemExec[3] = 1; |
| | | odo = ReadOdo(); |
| | | } |
| | | } else if (freeSepDis > 150) { |
| | | if (itemExec[2] == 0) { |
| | | PlayTTS("二狗变道"); |
| | | itemExec[2] = 1; |
| | | odo = ReadOdo(); |
| | | } else if (itemExec[1] == 0) { |
| | | PlayTTS("二狗超车"); |
| | | itemExec[1] = 1; |
| | | odo = ReadOdo(); |
| | | } |
| | | } |
| | | |
| | | BIG_DOG:; |
| | | } |
| | | DEBUG("直道剩余距离 %f, 车道剩余距离 %f", BigStraightRoadFree, RoadCrossingFree); |
| | | } |
| | | |
| | | // 检测压线状态 |
| | | TestRoadStartCar(car, speed, moveDirect, rtkTime); |
| | | |
| | | // 额外的转向检测 |
| | | DetectTurn(car, moveDirect, rtkTime); |
| | | |
| | | if (startCar != START_CAR_DONE) |
| | | return; |
| | | ItemExam(RoadMap, car, CarModelList, speed, moveDirect, rtkTime, BigStraightRoadFree, RoadCrossingFree); |
| | | |
| | | if (ReadOdo() > EXAM_RANGE && currRoadItem == NULL && AllCmp(RoadMap) && stopCar == STOP_CAR_NOT_DO) { |
| | | // 在合适条件下停车结束考试 |
| | |
| | | } |
| | | } |
| | | }*/ |
| | | } |
| | | |
| | | 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 double freeRunDistance; |
| | | static double totalRunDistance; |
| | | |
| | | if (RoadExamStatus == ROAD_EXAM_READY_NEXT) { |
| | | if (RoadExamItem[ROAD_EXAM_ITEM_CAR_START] == ROAD_EXAM_ITEM_NOT_EXEC) { |
| | | CarStartInit(); |
| | | 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) { |
| | | |
| | | } |
| | | } |
| | | if (RoadExamItem[ROAD_EXAM_ITEM_OP_GEAR] == ROAD_EXAM_ITEM_NOT_EXEC) { |
| | | if (straight > 150 && road_end > 150) { |
| | | StartOperateGearExam(); |
| | | RoadExamStatus = ROAD_EXAM_ITEM_OP_GEAR; |
| | | } |
| | | } |
| | | if (RoadExamItem[ROAD_EXAM_ITEM_CHANGE_LANE] == ROAD_EXAM_ITEM_NOT_EXEC) { |
| | | |
| | | } |
| | | if (RoadExamItem[ROAD_EXAM_ITEM_OVER_TAKE] == ROAD_EXAM_ITEM_NOT_EXEC) { |
| | | |
| | | } |
| | | |
| | | } |
| | | } else if (RoadExamStatus == ROAD_EXAM_FREE_RUN) { |
| | | if (ReadOdo() - freeRunDistance > 300) { |
| | | RoadExamStatus = ROAD_EXAM_READY_NEXT; |
| | | } |
| | | } else { |
| | | bool testing = false; |
| | | |
| | | switch (RoadExamStatus) { |
| | | case ROAD_EXAM_ITEM_CAR_START: |
| | | testing = TestCarStart(car, speed, moveDirect, rtkTime); |
| | | break; |
| | | case ROAD_EXAM_ITEM_OP_GEAR: |
| | | testing = TestOperateGear(rtkTime); |
| | | break; |
| | | default:break; |
| | | } |
| | | |
| | | if (!testing) { |
| | | RoadExamItem[RoadExamStatus] = ROAD_EXAM_ITEM_EXECED; |
| | | |
| | | RoadExamStatus = ROAD_EXAM_FREE_RUN; |
| | | freeRunDistance = ReadOdo(); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | void Rtk2DriveTimer(struct drive_timer &tm, const struct RtkTime *rtkTime) |
| | |
| | | turnTimeCnt += TimeGetDiff(rtkTime, &prevDetectTurnTime); |
| | | int wise = isTurn((int) car->yaw, startTurnYaw, TURN_THRESHOLD); |
| | | DEBUG("转动角度 %d", wise); |
| | | if (ABS(wise) > 60) { |
| | | if (ABS(wise) > CROSSING_TURN_THRESHOLD) { |
| | | // 确认转弯行为,检测开始刚转弯时转向灯情况 |
| | | turnCnt = -1; |
| | | |