// // Created by YY on 2020/3/24. // #include "stop_car.h" #include "../driver_test.h" #include "../native-lib.h" #include "../jni_log.h" #include "road_exam.h" #include "../utils/xconvert.h" #include "../common/apptimer.h" #include "../test_common/car_sensor.h" #include "../defs.h" #define DEBUG(fmt, args...) LOGD(" <%s>: " fmt, __func__, ##args) static bool inactiveBreakHandbreakTogether, notCloseEngine, inactiveHandBreakAfterOpenDoor, occurOpenDoor, doorNotClose, checkRoadDistance; static int examTtsSeq = 0; static int ttsPlayEnd; static double moveDistance; static double prevSpeed; static struct drive_timer prevPointTime; static int prevMoveDirect; static uint32_t stopTimepoint = 0; static uint32_t openDoorTimepoint; const int ENGINE_MIN_ROTATE = 200; static const uint32_t STOP_CAR_TIME = D_SEC(2); static const uint32_t OPEN_DOOR_TIMEOUT = D_SEC(15); static const double DISTANCE_TO_ROAD_EDGE_1 = 0.5; static const double DISTANCE_TO_ROAD_EDGE_2 = 0.3; static void PlayTTSTimeout(union sigval sig); void StartStopCarExam(int index, LIST_ROAD_MAP &RoadMapList) { if (index == -1) return; DEBUG("进入靠边停车地图 index = %d id = %d item = %d", index, RoadMapList[index].id, RoadMapList[index].type); ttsPlayEnd = 0; moveDistance = 0; prevMoveDirect = 0; inactiveBreakHandbreakTogether = false; notCloseEngine = false; inactiveHandBreakAfterOpenDoor = false; occurOpenDoor = false; doorNotClose = false; checkRoadDistance = false; if (!RoadMapList[index].tts.empty()) { examTtsSeq = PlayTTS(RoadMapList[index].tts.c_str()); } else { examTtsSeq = PlayTTS("请靠边停车"); } AppTimer_delete(PlayTTSTimeout); AppTimer_add(PlayTTSTimeout, D_SEC(8)); } void StopCarTTSDone(int id) { DEBUG("DummyLightTTSDone %d", id); // 等语音播报完毕后计时 if (id == examTtsSeq) { ttsPlayEnd = 1; } } int ExecuteStopCarExam(int index, LIST_ROAD_MAP &RoadMapList, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime) { if (ttsPlayEnd == 1) { ttsPlayEnd = 2; prevSpeed = speed; Rtk2DriveTimer(prevPointTime, rtkTime); } if (ttsPlayEnd != 2) return index; uint32_t diff = TimeGetDiff(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss * 10, prevPointTime.hour, prevPointTime.min, prevPointTime.sec, prevPointTime.msec * 10); moveDistance += (double)diff * (speed + prevSpeed) / 2; prevSpeed = speed; Rtk2DriveTimer(prevPointTime, rtkTime); if (moveDistance > 150) { // 150米内未停车,不合格 DEBUG("停车距离超标"); AddExamFault(33, rtkTime); return -1; } if (moveDirect != prevMoveDirect) { if (moveDirect == 0) { stopTimepoint = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10); DEBUG("停车了 %d %d %d %d %d %d %d", rtkTime->YY, rtkTime->MM, rtkTime->DD, rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss); } prevMoveDirect = moveDirect; } else if (moveDirect == 0) { uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10); if (tp - stopTimepoint >= STOP_CAR_TIME && !checkRoadDistance) { // 停车超2秒,开始判断 DEBUG("检测和路边的距离"); PointF pc; checkRoadDistance = true; pc.X = (car->carXY[car->right_front_tire[TIRE_OUTSIDE]].X + car->carXY[car->right_rear_tire[TIRE_OUTSIDE]].X) / 2; pc.Y = (car->carXY[car->right_front_tire[TIRE_OUTSIDE]].Y + car->carXY[car->right_rear_tire[TIRE_OUTSIDE]].Y) / 2; // 检测道路边缘线 for (int i = 0; i < RoadMapList[index].roadEdgeLineNum; ++i) { PointF p1, p2, pv; p1 = RoadMapList[index].roadEdgeLine[i].point[0]; for (int j = 1; j < RoadMapList[index].roadEdgeLine[i].num; ++j) { p2 = RoadMapList[index].roadEdgeLine[i].point[j]; pv = GetVerticalPoint(p1, p2, pc); if (isEqual2(pv.X, MIN(p1.X, p2.X)) || isEqual2(pv.X, MAX(p1.X, p2.X)) || (pv.X > MIN(p1.X, p2.X) && pv.X < MAX(p1.X, p2.X))) { double dis2roadEdge = DistanceOf(pc, pv); DEBUG("停车距路边距离 %f", dis2roadEdge); if (dis2roadEdge > DISTANCE_TO_ROAD_EDGE_1) { DEBUG("停车超出路边0.5米"); // 停车距离超过50厘米,不合格 AddExamFault(36, rtkTime); } else if (dis2roadEdge > DISTANCE_TO_ROAD_EDGE_2) { DEBUG("停车超出路边0.3米"); // 停车距离超过30厘米,扣10分 AddExamFault(37, rtkTime); } } p1 = p2; } } } } if (!inactiveBreakHandbreakTogether && ReadCarStatus(BREAK) == BREAK_INACTIVE && ReadCarStatus(HAND_BREAK) == BREAK_INACTIVE) { // 拉手刹前,松脚刹,扣10分 DEBUG("拉手刹前,松脚刹"); AddExamFault(39, rtkTime); inactiveBreakHandbreakTogether = true; } if (!notCloseEngine && ReadCarStatus(ENGINE_RPM) < ENGINE_MIN_ROTATE && ReadCarStatus(DOOR) == DOOR_OPEN) { // 下车前,不熄火,扣5分 DEBUG("下车前,不熄火"); AddExamFault(40, rtkTime); notCloseEngine = true; } if (!inactiveHandBreakAfterOpenDoor && ReadCarStatus(DOOR) == DOOR_OPEN && ReadCarStatus(HAND_BREAK) == BREAK_INACTIVE) { // 开门前,未拉手刹, 扣10分 DEBUG("开门前,未拉手刹"); AddExamFault(38, rtkTime); inactiveHandBreakAfterOpenDoor = true; } if (ReadCarStatus(DOOR) == DOOR_OPEN) { if (!occurOpenDoor) { occurOpenDoor = true; openDoorTimepoint = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10); } else { uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10); if (!doorNotClose && tp - openDoorTimepoint >= OPEN_DOOR_TIMEOUT) { // 开门时间超过15秒,不合格 DEBUG("开门时间超过15秒"); AddExamFault(35, rtkTime); doorNotClose = true; } } } else if (occurOpenDoor) { return -1; } if (occurOpenDoor) { uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10); if (tp - openDoorTimepoint >= OPEN_DOOR_TIMEOUT + D_SEC(5)) { return -1; } } return index; } static void PlayTTSTimeout(union sigval sig) { AppTimer_delete(PlayTTSTimeout); ttsPlayEnd = 1; }