| | |
| | | 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 double OVERTAKE_HOLD_RANGE = 30.0; // 在超车道行驶的一段距离 |
| | | |
| | | static const double LASTEST_BREAK_POINT = 30.0; |
| | | static const double NEXT_ROAD_TIP = 100.0; // 到达路口前提示下一个怎么走 |
| | | static const double DISTANCE_STOP_CAR_TO_STOP_LINE = 5.0; |
| | | static const double PASS_SCHOOL_MAX_SPEED = 30.0; // kmh |
| | | |
| | | static const int FIND_POSITION = -2; |
| | | static const int INVALID_POSITION = -1; |
| | |
| | | |
| | | static int startCar; |
| | | static int currExamMapIndex; |
| | | static trigger_line_t *currRoadItem; |
| | | static int nextRoadId; |
| | | static PointF roadItemStartPoint; |
| | | static struct drive_timer roadItemStartTime; |
| | | static bool overtake = false; |
| | | |
| | | static bool checkDoor = false; |
| | | static bool handBreakActive = false; |
| | | static bool reportRPMOver = false; |
| | | |
| | | static int currCarOnRoadIndex; |
| | | |
| | | static const uint32_t TURN_ERROR_COLD_TIME = D_SEC(10); |
| | | |
| | |
| | | int road; |
| | | int separate; |
| | | int lane; |
| | | int direct; // 车道方向限制 |
| | | int type; // 实线,虚线 |
| | | } CurrentLane; |
| | | static bool laneChanging; |
| | | |
| | |
| | | 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 NEXT_ROAD_TIP = 100.0; // 到达路口前提示下一个怎么走 |
| | | |
| | | static const int CRL_NONE = 0; |
| | | static const int CRL_SEP_DOTTED = 1; |
| | |
| | | |
| | | static char isTurn(int currYaw, int prevYaw, int &ang); |
| | | 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); |
| | | |
| | | static void TurnSignalError13ColdTimer(union sigval sig); |
| | | static void TurnSignalError14ColdTimer(union sigval sig); |
| | |
| | | static bool LaneIsSame(struct car_on_lane lane1, struct car_on_lane lane2); |
| | | static bool LaneIsValid(struct car_on_lane lane); |
| | | static void ArrivedRoadEnd(road_t &road, const car_model *car, LIST_CAR_MODEL &CarModelList); |
| | | static trigger_line_t * EntryItem(int index, road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList); |
| | | static void ClearAll(road_exam_map &map); |
| | | static void CheckBreakActive(road_exam_map &map, const car_model *car, LIST_CAR_MODEL &CarModelList, |
| | | double speed, int moveDirect, const struct RtkTime *rtkTime); |
| | | |
| | | void InitRoadExam(road_exam_map &RoadMap) |
| | | { |
| | |
| | | occurCrashRedLine = false; |
| | | occurCrashGreenLine = false; |
| | | occurOverSpeed = false; |
| | | |
| | | occurSecondBreak = false; |
| | | checkCrashGreenTimeout = 0; |
| | | carIntersectionOfGreenLine = 0; |
| | |
| | | currExamMapIndex = FIND_POSITION; |
| | | |
| | | startCar = START_CAR_NOT_DO; |
| | | currRoadItem = NULL; |
| | | |
| | | checkDoor = false; |
| | | handBreakActive = false; |
| | |
| | | |
| | | turnError13Cold = turnError14Cold = true; |
| | | |
| | | currCarOnRoadIndex = FIND_POSITION; |
| | | |
| | | CurrentLane.road = CurrentLane.separate = CurrentLane.lane = -1; |
| | | laneChanging = false; |
| | | |
| | | InitThroughSomething(RoadMap); |
| | | nextRoadId = -1; |
| | | ClearAll(RoadMap); |
| | | } |
| | | |
| | | void TerminateRoadExam(void) |
| | |
| | | |
| | | void TestRoadGeneral(road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime) |
| | | { |
| | | // 起步检测 |
| | | TestRoadStartCar(car, speed, moveDirect, rtkTime); |
| | | |
| | | // 超速检测 |
| | | if (moveDirect != 0 && speed > MAX_SPEED) { |
| | | if (!occurOverSpeed) { |
| | | occurOverSpeed = true; |
| | | // 超速,不合格 |
| | | DEBUG("超速 %f", speed); |
| | | AddExamFault(10, rtkTime); |
| | | } |
| | | } else { |
| | |
| | | } |
| | | |
| | | // 检测通过路口、人行道等区域时,释放刹车或减速 |
| | | CheckBreakActive(RoadMap, car, CarModelList); |
| | | CheckBreakActive(RoadMap, car, CarModelList, |
| | | speed, moveDirect, rtkTime); |
| | | |
| | | // 检测离开此路段,全车需不在范围内 |
| | | if (currExamMapIndex >= 0) { |
| | |
| | | if (IntersectionOf(car->carXY[car->axial[AXIAL_FRONT]], &area) == GM_Containment) { |
| | | currExamMapIndex = i; |
| | | DEBUG("进入道路 id = %d", RoadMap.roads[i].id); |
| | | if (nextRoadId >= 0 && RoadMap.roads[i].id != nextRoadId) { |
| | | DEBUG("不按规矩行驶,进入错误路段"); |
| | | AddExamFault(3, rtkTime); |
| | | } |
| | | nextRoadId = -1; |
| | | break; |
| | | } |
| | | |
| | |
| | | if (crl == CRL_NONE) { |
| | | // DEBUG("什么都没压"); |
| | | } else if (crl == CRL_SEP_DOTTED) { |
| | | // DEBUG("压分道虚线"); |
| | | DEBUG("压分道虚线"); |
| | | crashGreenLineNow = true; |
| | | } else if (crl == CRL_SEP_SOLID) { |
| | | // DEBUG("压分道实线"); |
| | | DEBUG("压分道实线"); |
| | | crashRedLineNow = true; |
| | | } else if (crl == CRL_EDGE_DOTTED) { |
| | | // DEBUG("压边沿虚线"); |
| | | DEBUG("压边沿虚线"); |
| | | crashGreenLineNow = true; |
| | | } else if (crl == CRL_EDGE_SOLID) { |
| | | // DEBUG("压边沿实线"); |
| | | DEBUG("压边沿实线"); |
| | | crashRedLineNow = true; |
| | | } |
| | | |
| | |
| | | } else { |
| | | // 变道完成 |
| | | DEBUG("变道完成"); |
| | | |
| | | if (currRoadItem != NULL && currRoadItem->active == ROAD_ITEM_CHANGE_LANE) { |
| | | DEBUG("变更车道项目完成"); |
| | | currRoadItem = NULL; |
| | | } else if (currRoadItem != NULL && currRoadItem->active == ROAD_ITEM_OVERTAKE) { |
| | | if (CurrentLane.lane > lane.lane) { |
| | | DEBUG("超车变道完成"); |
| | | |
| | | } else { |
| | | DEBUG("右道超车,错误"); |
| | | AddExamFault(3, rtkTime); |
| | | currRoadItem = NULL; |
| | | } |
| | | } |
| | | |
| | | CurrentLane = lane; |
| | | laneChanging = false; |
| | | |
| | | // 记录本次变道时间点 |
| | | Rtk2DriveTimer(crashGreenCmpTime, rtkTime); |
| | | } |
| | |
| | | |
| | | if (lane.road != CurrentLane.road || lane.separate != CurrentLane.separate) { |
| | | // 路或段变更,撤销变道跟踪 |
| | | DEBUG("============== 路或段变更 CURR %d, %d NEW %d, %d", CurrentLane.road, |
| | | CurrentLane.separate, |
| | | lane.road, lane.separate); |
| | | DEBUG("============== 路或段变更 CURR %d, %d dir %d NEW %d, %d, dir %d", CurrentLane.road, |
| | | CurrentLane.separate, CurrentLane.direct, |
| | | lane.road, lane.separate, lane.direct); |
| | | |
| | | CurrentLane = lane; |
| | | laneChanging = false; |
| | | } |
| | | |
| | | if (CurrentLane.direct != 0 && !(CurrentLane.direct & RoadMap.roads[currExamMapIndex].active)) { |
| | | if (!RoadMap.roads[currExamMapIndex].errorLane) { |
| | | RoadMap.roads[currExamMapIndex].errorLane = true; |
| | | DEBUG("不按规定车道标线方向行驶 %d", CurrentLane.direct); |
| | | AddExamFault(9, rtkTime); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | // 不再压虚线 |
| | | occurCrashGreenLine = false; |
| | | checkCrashGreenTimeout = 0; |
| | | } |
| | | |
| | | TestRoadStartCar(car, speed, moveDirect, rtkTime); |
| | | |
| | | if (startCar != START_CAR_DONE) |
| | | return; |
| | | |
| | | // 检测由触发线控制的项目 |
| | | 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 && DistanceOf(car->basePoint, roadItemStartPoint) > OVERTAKE_HOLD_RANGE) { |
| | | DEBUG("回原车道"); |
| | | PlayTTS("请返回原车道"); |
| | | currRoadItem = NULL; |
| | | } |
| | | } else if (currRoadItem->active == ROAD_ITEM_OPERATE_GEAR) { |
| | | ExecuteOperateGearExam(rtkTime); |
| | | } |
| | | } else if (currExamMapIndex >= 0) { |
| | | currRoadItem = EntryItem(currExamMapIndex, RoadMap, car, CarModelList); |
| | | if (currRoadItem != NULL) { |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | PointF p1, p2; |
| | | Line sep; |
| | | |
| | | map<int, int> orthogonal; |
| | | map<int, vector<int>> orthogonal; |
| | | |
| | | // 一段分道组内,有一条正交,就必须保证同组的全都正交,否则直接退出 |
| | | for (int j = 0; j < road.separate[i].lines.size(); ++j) { // 线组 |
| | |
| | | MakeLine(&sep, &p1, &p2); |
| | | |
| | | if (IntersectionOf(leftExtLine, sep) == GM_Intersection) { |
| | | orthogonal.insert(pair<int, int>(j, 1)); |
| | | vector<int> stor(4); |
| | | |
| | | stor[0] = 1; |
| | | stor[1] = road.separate[i].lines[j][k].character; |
| | | stor[2] = road.separate[i].lines[j][k].left_lane_direct; |
| | | stor[3] = road.separate[i].lines[j][k].right_lane_direct; |
| | | |
| | | orthogonal.insert(pair<int, vector<int>>(j, stor)); |
| | | orthogonalInSegment = true; |
| | | intersection = true; |
| | | |
| | | // DEBUG("分道线 %d 左正交", j); |
| | | break; |
| | | } else if (IntersectionOf(rightExtLine, sep) == GM_Intersection) { |
| | | orthogonal.insert(pair<int, int>(j, 2)); |
| | | vector<int> stor(4); |
| | | |
| | | stor[0] = 2; |
| | | stor[1] = road.separate[i].lines[j][k].character; |
| | | stor[2] = road.separate[i].lines[j][k].left_lane_direct; |
| | | stor[3] = road.separate[i].lines[j][k].right_lane_direct; |
| | | |
| | | orthogonal.insert(pair<int, vector<int>>(j, stor)); |
| | | orthogonalInSegment = true; |
| | | intersection = true; |
| | | |
| | | // DEBUG("分道线 %d 右正交", j); |
| | | break; |
| | | } |
| | |
| | | if (orthogonal.size() == road.separate[i].lines.size()) { |
| | | // 得到当前在第几个车道 |
| | | int x = 0; |
| | | int left_char = LINE_SOLID; // 道路左边线 |
| | | int right_direct = 0; |
| | | |
| | | for (x = 0; x < orthogonal.size(); ++x) { |
| | | auto itx = orthogonal.find(x); |
| | | if (itx != orthogonal.end()) { |
| | | if (itx->second != 1) { |
| | | if (itx->second[0] != 1) { // 在车辆右侧 |
| | | lane.road = road.id; |
| | | lane.separate = i; |
| | | lane.lane = itx->first; |
| | | |
| | | if ((left_char == LINE_SOLID || left_char == LINE_HALF_SOLID_RIGHT) && |
| | | (itx->second[1] == LINE_SOLID || itx->second[1] == LINE_HALF_SOLID_LEFT)) // 车道左右均是实线 |
| | | lane.direct = itx->second[2]; |
| | | else |
| | | lane.direct = 0; |
| | | // DEBUG("路 %d 段 %d 车道 %d", lane.road, lane.separate, lane.lane); |
| | | break; |
| | | } else { |
| | | right_direct = itx->second[3]; |
| | | left_char = itx->second[2]; |
| | | } |
| | | } |
| | | } |
| | |
| | | lane.road = road.id; |
| | | lane.separate = i; |
| | | lane.lane = orthogonal.size(); |
| | | |
| | | // 最后车道的右侧限定 |
| | | if (left_char == LINE_SOLID || left_char == LINE_HALF_SOLID_RIGHT) |
| | | lane.direct = right_direct; |
| | | else |
| | | lane.direct = 0; |
| | | // DEBUG("路 %d 段 %d 车道 %d", lane.road, lane.separate, lane.lane); |
| | | } |
| | | out = lane; |
| | |
| | | return false; |
| | | } |
| | | |
| | | #if 0 |
| | | void TestRoadGeneral(LIST_ROAD_MAP &RoadMapList, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime) |
| | | { |
| | | // 起步检测 |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | bool ExitSonArea(int index, LIST_ROAD_MAP &RoadMapList, const car_model *car) |
| | | { |
| | | bool ret = false; |
| | |
| | | |
| | | return ret; |
| | | } |
| | | #endif |
| | | |
| | | void Rtk2DriveTimer(struct drive_timer &tm, const struct RtkTime *rtkTime) |
| | | { |
| | |
| | | return 0; |
| | | } |
| | | |
| | | /***************************************************** |
| | | * CrashRedLine 整个考试区域的道路边缘线,实线等。 |
| | | * 按车轮碰触计算,车身不计 |
| | | */ |
| | | static bool CrashRedLine(LIST_ROAD_MAP &RoadMapList, const car_model *car) |
| | | { |
| | | Line frontAxle, rearAxle; |
| | | |
| | | MakeLine(&frontAxle, &car->carXY[car->left_front_tire[TIRE_OUTSIDE]], &car->carXY[car->right_front_tire[TIRE_OUTSIDE]]); |
| | | MakeLine(&rearAxle, &car->carXY[car->left_rear_tire[TIRE_OUTSIDE]], &car->carXY[car->right_rear_tire[TIRE_OUTSIDE]]); |
| | | |
| | | for (int i = 0; i < RoadMapList.size(); ++i) { |
| | | if (RoadMapList[i].type == GENERAL_MAP) { |
| | | |
| | | // 每条线都检测 |
| | | for (int j = 0; j < RoadMapList[i].redLineNum; ++j) { |
| | | Line red_line; |
| | | int kp = 0; |
| | | |
| | | for (int k = 1; k < RoadMapList[i].redLine[j].num; ++k) { |
| | | MakeLine(&red_line, &RoadMapList[i].redLine[j].point[kp], &RoadMapList[i].redLine[j].point[k]); |
| | | |
| | | if (IntersectionOf(red_line, frontAxle) == GM_Intersection || |
| | | IntersectionOf(red_line, rearAxle) == GM_Intersection) { |
| | | return true; |
| | | } |
| | | kp = k; |
| | | } |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /********************************************************** |
| | | * 按整个车身是否覆盖计算 |
| | | * @param RoadMapList |
| | | * @param car |
| | | * @return |
| | | */ |
| | | static bool CrashRedArea(LIST_ROAD_MAP &RoadMapList, const car_model *car) |
| | | /*static bool CrashRedArea(LIST_ROAD_MAP &RoadMapList, const car_model *car) |
| | | { |
| | | bool ret = false; |
| | | |
| | |
| | | free(carBody.point); |
| | | |
| | | return ret; |
| | | } |
| | | |
| | | /************************************************** |
| | | * 车轮触碰道路虚线。检测行驶时间超长;变道情况; |
| | | * @param RoadMapList |
| | | * @param car |
| | | */ |
| | | static bool CrashGreenLine(LIST_ROAD_MAP &RoadMapList, const car_model *car, PointF &p1, PointF &p2) |
| | | { |
| | | Line frontAxle, rearAxle; |
| | | |
| | | MakeLine(&frontAxle, &car->carXY[car->left_front_tire[TIRE_OUTSIDE]], &car->carXY[car->right_front_tire[TIRE_OUTSIDE]]); |
| | | MakeLine(&rearAxle, &car->carXY[car->left_rear_tire[TIRE_OUTSIDE]], &car->carXY[car->right_rear_tire[TIRE_OUTSIDE]]); |
| | | |
| | | for (int i = 0; i < RoadMapList.size(); ++i) { |
| | | if (RoadMapList[i].type == GENERAL_MAP) { |
| | | |
| | | // 每条线都检测 |
| | | for (int j = 0; j < RoadMapList[i].greenLineNum; ++j) { |
| | | Line green_line; |
| | | int kp = 0; |
| | | |
| | | for (int k = 1; k < RoadMapList[i].greenLine[j].num; ++k) { |
| | | MakeLine(&green_line, &RoadMapList[i].greenLine[j].point[kp], &RoadMapList[i].greenLine[j].point[k]); |
| | | |
| | | if (IntersectionOf(green_line, frontAxle) == GM_Intersection || |
| | | IntersectionOf(green_line, rearAxle) == GM_Intersection) { |
| | | |
| | | p1 = RoadMapList[i].greenLine[j].point[kp]; |
| | | p2 = RoadMapList[i].greenLine[j].point[k]; |
| | | |
| | | return true; |
| | | } |
| | | kp = k; |
| | | } |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | 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 == GENERAL_MAP) { |
| | | |
| | | // 每条线都检测 |
| | | 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 = 0; |
| | | for (int p = 1; p < pn; ++p) { |
| | | Line trace_line; |
| | | MakeLine(&trace_line, &trace.point[pp], &trace.point[p]); |
| | | |
| | | if (IntersectionOf(trace_line, trigger_line) == GM_Intersection && |
| | | IntersectionOfLine(RoadMapList[i].triggerLine[j].line.point[kp], |
| | | RoadMapList[i].triggerLine[j].line.point[k], |
| | | car->carXY[car->left_front_tire[TIRE_OUTSIDE]]) == -1 && |
| | | DistanceOf(car->carXY[car->left_front_tire[TIRE_OUTSIDE]], trigger_line) > 0.1) { |
| | | // 碰到触发线 |
| | | DEBUG("碰撞触发线 引发地图 id = %d", RoadMapList[i].triggerLine[j].triggerMapId); |
| | | 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; |
| | | } |
| | | }*/ |
| | | |
| | | bool CrashTheLine(Line line, const car_model *car, LIST_CAR_MODEL &CarModelList) |
| | | { |
| | |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | /********************************************************************* |
| | |
| | | return px; |
| | | } |
| | | |
| | | /*************************************************** |
| | | * 接近路口时,提示下一步怎么走 |
| | | * @param road |
| | | * @param car |
| | | * @param CarModelList |
| | | */ |
| | | static void ArrivedRoadEnd(road_t &road, const car_model *car, LIST_CAR_MODEL &CarModelList) |
| | | { |
| | | // 计算车前进轨迹延长线 |
| | |
| | | IntersectionOfLine(extPoint, road.stopLine) == -1) { |
| | | if (DistanceOf(extPoint, road.stopLine) > 1.0 && !road.arrivedTail) { |
| | | // 接近路口后,要检查车辆是否进入错误车道 |
| | | DEBUG("接近路口"); |
| | | road.arrivedTail = true; |
| | | if (!road.tts.empty()) |
| | | PlayTTS(road.tts.c_str()); |
| | |
| | | } |
| | | } |
| | | |
| | | static trigger_line_t * EntryItem(int index, road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList) |
| | | { |
| | | for (int i = 0; i < RoadMap.triggerLines.size(); ++i) { |
| | | if (RoadMap.triggerLines[i].road == RoadMap.roads[index].id) { |
| | | Line triggerLine; |
| | | |
| | | if (RoadMap.triggerLines[i].leftPoints.size() != RoadMap.triggerLines[i].points.size()) { |
| | | RoadMap.triggerLines[i].leftPoints.clear(); |
| | | |
| | | for (int j = 0; j < RoadMap.triggerLines[i].points.size(); ++j) { |
| | | RoadMap.triggerLines[i].leftPoints.push_back(GetSELine(RoadMap.roads[index].leftEdge, RoadMap.triggerLines[i].points[j])); |
| | | } |
| | | } |
| | | |
| | | MakeLine(&triggerLine, &RoadMap.triggerLines[i].points[0], &RoadMap.triggerLines[i].leftPoints[0]); |
| | | |
| | | if (CrashTheLine(triggerLine, car, CarModelList)) { |
| | | return &RoadMap.triggerLines[i]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return NULL; |
| | | } |
| | | |
| | | /************************************************************************ |
| | | * 开始新的考试后,清除地图所有的刹车、停车记录 |
| | | * @param map |
| | | */ |
| | | static void ClearAll(road_exam_map &map) |
| | | { |
| | | for (int i = 0; i < map.roads.size(); ++i) { |
| | | map.roads[i].activeStop = map.roads[i].activeBreak = false; |
| | | map.roads[i].arrivedTail = false; |
| | | map.roads[i].errorLane = false; |
| | | } |
| | | for (int i = 0; i < map.specialAreas.size(); i++) { |
| | | map.specialAreas[i].overSpeed = map.specialAreas[i].activeBreak = false; |
| | | } |
| | | } |
| | | |
| | | static void CheckBreakActive(road_exam_map &map, const car_model *car, LIST_CAR_MODEL &CarModelList, |
| | | double speed, int moveDirect, const struct RtkTime *rtkTime) |
| | | { |
| | | int BreakDone = ReadCarStatus(BREAK); |
| | | |
| | | // 计算车前进轨迹延长线 |
| | | double yaw = YawOf(car->carXY[ car->axial[AXIAL_FRONT] ], car->carXY[ car->axial[AXIAL_REAR] ]); |
| | | PointF extPoint = PointExtend(car->carXY[ car->axial[AXIAL_FRONT] ], LASTEST_BREAK_POINT, yaw); |
| | | |
| | | Line extLine; |
| | | MakeLine(&extLine, &car->carXY[ car->axial[AXIAL_FRONT] ], &extPoint); |
| | | |
| | | // 路口刹车点 |
| | | for (int i = 0; i < map.roads.size(); ++i) { |
| | | // 车头和路口距离不足30米 |
| | | if (IntersectionOf(extLine, map.roads[i].stopLine) == GM_Intersection && |
| | | IntersectionOfLine(car->carXY[ car->axial[AXIAL_FRONT] ], map.roads[i].stopLine) == 1 ) { |
| | | DEBUG("进入减速区"); |
| | | if (BreakDone == BREAK_ACTIVE) { |
| | | map.roads[i].activeBreak = true; |
| | | } |
| | | if (DistanceOf(car->carXY[car->axial[AXIAL_FRONT]], |
| | | map.roads[i].stopLine) < DISTANCE_STOP_CAR_TO_STOP_LINE && moveDirect == 0) { |
| | | map.roads[i].activeStop = true; |
| | | } |
| | | } |
| | | // 跨线后,检查刹车动作 |
| | | if (CrashTheLine(map.roads[i].stopLine, car, CarModelList)) { |
| | | if (map.roads[i].stopFlag != 0 && !map.roads[i].activeStop) { |
| | | // 不停车瞭望,不合格 |
| | | DEBUG("不停车瞭望"); |
| | | if (map.roads[i].active == ROAD_ACTIVE_FORWARD) { |
| | | AddExamFault(42, rtkTime); |
| | | } else if (map.roads[i].active == ROAD_ACTIVE_TURN_LEFT) { |
| | | AddExamFault(44, rtkTime); |
| | | } else if (map.roads[i].active == ROAD_ACTIVE_TURN_RIGHT) { |
| | | AddExamFault(47, rtkTime); |
| | | } |
| | | } |
| | | if (!map.roads[i].activeBreak) { |
| | | // 不按规定减速,不合格 |
| | | DEBUG("不按规定减速"); |
| | | if (map.roads[i].active == ROAD_ACTIVE_FORWARD) { |
| | | AddExamFault(41, rtkTime); |
| | | } else if (map.roads[i].active == ROAD_ACTIVE_TURN_LEFT) { |
| | | AddExamFault(43, rtkTime); |
| | | } else if (map.roads[i].active == ROAD_ACTIVE_TURN_RIGHT) { |
| | | AddExamFault(46, rtkTime); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // 人行道、公交站刹车点;学校限速区 |
| | | for (int i = 0; i < map.specialAreas.size(); i++) { |
| | | if (map.specialAreas[i].type == GRID_AREA) |
| | | continue; |
| | | |
| | | if (map.specialAreas[i].area.size() == 2 && map.specialAreas[i].leftPoints.size() != 2) { |
| | | // 计算点到左侧路边线的垂点 |
| | | int road = 0; |
| | | for (road = 0; road < map.roads.size(); ++road) { |
| | | if (map.roads[road].id == map.specialAreas[i].road) |
| | | break; |
| | | } |
| | | |
| | | PointF vPoint = GetSELine(map.roads[road].leftEdge, map.specialAreas[i].area[0]); |
| | | DEBUG("计算垂点1 (%f, %f)", vPoint.X, vPoint.Y); |
| | | |
| | | map.specialAreas[i].leftPoints.push_back(vPoint); |
| | | |
| | | vPoint = GetSELine(map.roads[road].leftEdge, map.specialAreas[i].area[0]); |
| | | DEBUG("计算垂点2 (%f, %f)", vPoint.X, vPoint.Y); |
| | | map.specialAreas[i].leftPoints.push_back(vPoint); |
| | | } |
| | | |
| | | if (map.specialAreas[i].type == ZEBRA_CROSSING || map.specialAreas[i].type == BUS_STATION_AREA) { |
| | | Line startLine; |
| | | |
| | | MakeLine(&startLine, &map.specialAreas[i].area[0], &map.specialAreas[i].leftPoints[0]); |
| | | |
| | | // 车头和斑马线距离不足30米 |
| | | if (IntersectionOf(extLine, startLine) == GM_Intersection && |
| | | IntersectionOfLine(car->carXY[ car->axial[AXIAL_FRONT] ], startLine) == 1 ) { |
| | | DEBUG("进入减速区 %d", map.specialAreas[i].type); |
| | | if (BreakDone == BREAK_ACTIVE) { |
| | | map.specialAreas[i].activeBreak = true; |
| | | } |
| | | } |
| | | |
| | | // 跨线后,检查刹车动作 |
| | | if (CrashTheLine(startLine, car, CarModelList)) { |
| | | if (!map.specialAreas[i].activeBreak) { |
| | | // 不按规定减速,不合格 |
| | | DEBUG("不按规定减速"); |
| | | if (map.specialAreas[i].type == ZEBRA_CROSSING) { |
| | | AddExamFault(48, rtkTime); |
| | | } else { |
| | | AddExamFault(50, rtkTime); |
| | | } |
| | | } else { |
| | | DEBUG("按规定减速"); |
| | | } |
| | | |
| | | } |
| | | } else if (map.specialAreas[i].type == SCHOOL_AREA) { |
| | | Polygon school; |
| | | |
| | | school.num = 4; |
| | | school.point = (PointF *) malloc(school.num * sizeof(PointF)); |
| | | |
| | | school.point[0] = map.specialAreas[i].area[0]; |
| | | school.point[1] = map.specialAreas[i].area[1]; |
| | | school.point[2] = map.specialAreas[i].leftPoints[1]; |
| | | school.point[3] = map.specialAreas[i].leftPoints[0]; |
| | | |
| | | if (IntersectionOf(car->carXY[ car->axial[AXIAL_FRONT] ], &school) == GM_Containment) { |
| | | if (ConvertMs2KMh(speed) > PASS_SCHOOL_MAX_SPEED) { |
| | | if (!map.specialAreas[i].overSpeed) { |
| | | DEBUG("通过学校区域超速"); |
| | | AddExamFault(49, rtkTime); |
| | | map.specialAreas[i].overSpeed = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | free(school.point); |
| | | } |
| | | } |
| | | } |
| | | |
| | | #if 0 |
| | | |
| | | typedef struct { |