| | |
| | | #include "test_common/car_sensor.h" |
| | | #include "mcu/mcu_if.h" |
| | | #include "test_common/car_sensor.h" |
| | | #include "test_items2/road_exam.h" |
| | | #include "test_items/area_exam.h" |
| | | #include "test_items2/prepare.h" |
| | | #include "test_common/odo_graph.h" |
| | | #include "map.h" |
| | | #include "common/semaphore.h" |
| | | #include "common/string_util.h" |
| | | |
| | | #define DEBUG(fmt, args...) LOGD("<driver_test> <%s>: " fmt, __func__, ##args) |
| | | |
| | |
| | | vector<ExamFault> ExamFaultList; |
| | | static int examFaultIndex = 0; |
| | | |
| | | static LIST_AREA_MAP AreaMapList; |
| | | //static LIST_AREA_MAP AreaMapList; |
| | | static area_map_t AreaMap; |
| | | |
| | | ilovers::semaphore sem(0); |
| | | |
| | | static road_exam_map RoadMap; |
| | | |
| | | static int exam_dummy_light; |
| | | |
| | | static car_model *CarModel = NULL; |
| | | static car_model_t CarModel; |
| | | |
| | | static LIST_CAR_MODEL CarModelList; // 一段时间的车辆轨迹集合 |
| | | //static LIST_CAR_MODEL CarModelList; // 一段时间的车辆轨迹集合 |
| | | |
| | | static struct dummy_light_exam *DummyLightContent; |
| | | static int DummyLightContentSize; |
| | |
| | | #define RTK_BUFFER_SIZE 100 |
| | | #define CAR_MODEL_CACHE_SIZE 10 |
| | | |
| | | static rtk_info *RtkBuffer = NULL; |
| | | static int RtkBufferNum = 0, RtkBufferIn = 0; |
| | | static std::list<rtk_info_t> RtkInfoList; |
| | | |
| | | static std::mutex clock_mutex; |
| | | static struct RtkTime rtkClock; |
| | | // 存入前后2组建模数据 |
| | | static modeling_t realtimeBodyModeling[2]; |
| | | static motion_t realtimeMotionStatus; |
| | | |
| | | static prime_t prime; |
| | | |
| | | static void SetExamParamDefault(void); |
| | | static void EngineStartHold(apptimer_var_t val); |
| | | static void ExecuteExam(const struct RtkTime* rtkTime); |
| | | static void ExecuteExam(double speed, int move, double azimuth, const struct RtkTime* rtkTime); |
| | | static uint32_t CalcTimeDiff(const rtk_info *a, const rtk_info *b); |
| | | static motion_t CalcMotionState(std::list<rtk_info_t> &s); |
| | | static void ExecuteExam(prime_t &prime); |
| | | |
| | | static void ReadDriverExamPrimerTimeout(apptimer_var_t val); |
| | | static void UpdateCarBodyCoord(struct RtkTime *rtkTime, double azimuth, double pitch, double roll, PointF main_ant, car_model *carModel); |
| | | static bool UpdateCarCoord(double &spd, int &mov, int &idx); |
| | | |
| | | static void PrintObdInfo(struct RtkTime *rtkTime, double speed); |
| | | |
| | | |
| | | static void ClockGener(apptimer_var_t val); |
| | | static void CalcBodyModeling(modeling_t &car, car_model_t &carModel, rtk_info_t &rtk); |
| | | static void work_thread(void); |
| | | static void UploadModeling(motion_t &motion, modeling_t &modeling); |
| | | |
| | | void DriverTestInit(void) |
| | | { |
| | | ExamStart = false; |
| | | SetExamParamDefault(); |
| | | |
| | | CarModel = NULL; |
| | | CarModelList.clear(); |
| | | // CarModelList.clear(); |
| | | |
| | | AreaMapList.clear(); |
| | | // AreaMapList.clear(); |
| | | |
| | | RoadMap.roads.clear(); |
| | | RoadMap.specialAreas.clear(); |
| | |
| | | DummyLightContentSize = 0; |
| | | DummyLightContent = NULL; |
| | | |
| | | RtkBuffer = (rtk_info *) malloc(RTK_BUFFER_SIZE * sizeof(rtk_info)); |
| | | RtkBufferNum = RtkBufferIn = 0; |
| | | |
| | | // AppTimer_add(ClockGener, 200); // App自己产生定时节拍 |
| | | std::thread(work_thread).detach(); |
| | | } |
| | | |
| | | static void SetExamParamDefault(void) |
| | |
| | | if (ExamStart) |
| | | return; |
| | | |
| | | for (int i = 0; i < AreaMapList.size(); ++i) { |
| | | if (AreaMapList[i].map.point != NULL) |
| | | free(AreaMapList[i].map.point); |
| | | if (AreaMapList[i].map2.point != NULL) |
| | | free(AreaMapList[i].map2.point); |
| | | } |
| | | // for (int i = 0; i < AreaMapList.size(); ++i) { |
| | | // if (AreaMapList[i].map.point != NULL) |
| | | // free(AreaMapList[i].map.point); |
| | | // if (AreaMapList[i].map2.point != NULL) |
| | | // free(AreaMapList[i].map2.point); |
| | | // } |
| | | // |
| | | // LIST_AREA_MAP().swap(AreaMapList); |
| | | |
| | | LIST_AREA_MAP().swap(AreaMapList); |
| | | |
| | | vector<curve_map_t>().swap(AreaMap.curve_map); |
| | | vector<park_button_map_t>().swap(AreaMap.park_button_map); |
| | | vector<park_edge_map_t>().swap(AreaMap.park_edge_map); |
| | | vector<turn_a90_map_t>().swap(AreaMap.turn_a90_map); |
| | | vector<uphill_map_t>().swap(AreaMap.uphill_map); |
| | | } |
| | | |
| | | void AddAreaMap(int id, int type, const double (*map)[2], int pointNum, const double (*map2)[2], int pointNum2) |
| | |
| | | return; |
| | | DEBUG("加入地图信息 id %d type %d pointNum %d point2Num %d", id, type, pointNum, pointNum2); |
| | | |
| | | struct area_exam_map newMap; |
| | | // struct area_exam_map newMap; |
| | | // |
| | | // newMap.id = id; |
| | | // newMap.type = type; |
| | | // newMap.map.num = pointNum; |
| | | // newMap.map2.num = 0; |
| | | // newMap.map.point = NULL; |
| | | // newMap.map2.point = NULL; |
| | | // |
| | | // if (pointNum > 0) { |
| | | // newMap.map.point = (PointF *) malloc(pointNum * sizeof(PointF)); |
| | | // for (int i = 0; i < pointNum; ++i) { |
| | | // newMap.map.point[i].X = map[i][0]; |
| | | // newMap.map.point[i].Y = map[i][1]; |
| | | // } |
| | | // } |
| | | // |
| | | // if (pointNum2 > 0 && map2 != NULL) { |
| | | // newMap.map2.num = pointNum2; |
| | | // newMap.map2.point = (PointF *) malloc(pointNum2 * sizeof(PointF)); |
| | | // for (int i = 0; i < pointNum2; ++i) { |
| | | // newMap.map2.point[i].X = map2[i][0]; |
| | | // newMap.map2.point[i].Y = map2[i][1]; |
| | | // } |
| | | // } |
| | | // |
| | | // AreaMapList.push_back(newMap); |
| | | } |
| | | |
| | | newMap.id = id; |
| | | newMap.type = type; |
| | | newMap.map.num = pointNum; |
| | | newMap.map2.num = 0; |
| | | newMap.map.point = NULL; |
| | | newMap.map2.point = NULL; |
| | | void AddCurveMap(curve_map_t &map) |
| | | { |
| | | AreaMap.curve_map.push_back(map); |
| | | } |
| | | |
| | | if (pointNum > 0) { |
| | | newMap.map.point = (PointF *) malloc(pointNum * sizeof(PointF)); |
| | | for (int i = 0; i < pointNum; ++i) { |
| | | newMap.map.point[i].X = map[i][0]; |
| | | newMap.map.point[i].Y = map[i][1]; |
| | | } |
| | | } |
| | | void AddParkButtonMap(park_button_map_t &map) |
| | | { |
| | | AreaMap.park_button_map.push_back(map); |
| | | } |
| | | |
| | | if (pointNum2 > 0 && map2 != NULL) { |
| | | newMap.map2.num = pointNum2; |
| | | newMap.map2.point = (PointF *) malloc(pointNum2 * sizeof(PointF)); |
| | | for (int i = 0; i < pointNum2; ++i) { |
| | | newMap.map2.point[i].X = map2[i][0]; |
| | | newMap.map2.point[i].Y = map2[i][1]; |
| | | } |
| | | } |
| | | |
| | | AreaMapList.push_back(newMap); |
| | | void AddParkEdgeMap(park_edge_map_t &map) |
| | | { |
| | | AreaMap.park_edge_map.push_back(map); |
| | | } |
| | | |
| | | void CleanRoadMap(void) |
| | |
| | | |
| | | if (point == NULL || pointNum == 0 || ExamStart) return; |
| | | |
| | | if (CarModel != NULL) { |
| | | if (CarModel->body != NULL) |
| | | free(CarModel->body); |
| | | if (CarModel->carDesc != NULL) |
| | | free(CarModel->carDesc); |
| | | if (CarModel->carXY != NULL) |
| | | free(CarModel->carXY); |
| | | free(CarModel); |
| | | CarModel = NULL; |
| | | } |
| | | vector<int>().swap(CarModel.body); |
| | | vector<car_desc_t>().swap(CarModel.carDesc); |
| | | |
| | | CarModel = (car_model *)malloc(sizeof(car_model)); |
| | | CarModel->basePoint.X = basePoint[0]; |
| | | CarModel->basePoint.Y = basePoint[1]; |
| | | CarModel->axial[0] = axial[0]; |
| | | CarModel->axial[1] = axial[1]; |
| | | CarModel->left_front_tire[0] = left_front_tire[0]; |
| | | CarModel->left_front_tire[1] = left_front_tire[1]; |
| | | CarModel->right_front_tire[0] = right_front_tire[0]; |
| | | CarModel->right_front_tire[1] = right_front_tire[1]; |
| | | CarModel->left_rear_tire[0] = left_rear_tire[0]; |
| | | CarModel->left_rear_tire[1] = left_rear_tire[1]; |
| | | CarModel->right_rear_tire[0] = right_rear_tire[0]; |
| | | CarModel->right_rear_tire[1] = right_rear_tire[1]; |
| | | CarModel.basePoint.X = basePoint[0]; |
| | | CarModel.basePoint.Y = basePoint[1]; |
| | | CarModel.axial[0] = axial[0]; |
| | | CarModel.axial[1] = axial[1]; |
| | | CarModel.left_front_tire[0] = left_front_tire[0]; |
| | | CarModel.left_front_tire[1] = left_front_tire[1]; |
| | | CarModel.right_front_tire[0] = right_front_tire[0]; |
| | | CarModel.right_front_tire[1] = right_front_tire[1]; |
| | | CarModel.left_rear_tire[0] = left_rear_tire[0]; |
| | | CarModel.left_rear_tire[1] = left_rear_tire[1]; |
| | | CarModel.right_rear_tire[0] = right_rear_tire[0]; |
| | | CarModel.right_rear_tire[1] = right_rear_tire[1]; |
| | | |
| | | CarModel->bodyNum = bodyNum; |
| | | if (bodyNum == 0 || body == NULL) { |
| | | CarModel->bodyNum = 6; |
| | | CarModel->body = (int *) malloc(sizeof(int) * 6); |
| | | for (int i = 0; i < 6; ++i) { |
| | | CarModel->body[i] = i; |
| | | CarModel.body.push_back(i); |
| | | } |
| | | } else { |
| | | CarModel->body = (int *) malloc(sizeof(int) * CarModel->bodyNum); |
| | | for (int i = 0; i < CarModel->bodyNum; ++i) { |
| | | CarModel->body[i] = body[i]; |
| | | for (int i = 0; i < bodyNum; ++i) { |
| | | CarModel.body.push_back(body[i]); |
| | | } |
| | | } |
| | | |
| | | CarModel->antPitch = antPitch; |
| | | CarModel->antHeight = antHeight; |
| | | CarModel->groundHeight = groundHeight; |
| | | CarModel.antPitch = antPitch; |
| | | CarModel.antHeight = antHeight; |
| | | CarModel.groundHeight = groundHeight; |
| | | |
| | | CarModel->pointNum = pointNum; |
| | | CarModel->carDesc = (struct car_desc_ *)malloc(sizeof(struct car_desc_) * pointNum); |
| | | CarModel->carXY = (PointF *) malloc(sizeof(PointF) * pointNum); |
| | | |
| | | CarModel.carDesc.resize(pointNum); |
| | | // 测量坐标转换为距离-角度形式 |
| | | double C02 = (point[0][0]-basePoint[0])*(point[0][0]-basePoint[0]) + |
| | | (point[0][1]-basePoint[1])*(point[0][1]-basePoint[1]); |
| | | double C0 = sqrt(C02); |
| | | |
| | | CarModel->carDesc[0].distance = sqrt(C02); |
| | | CarModel->carDesc[0].angle = 0.0; |
| | | CarModel.carDesc[0].distance = sqrt(C02); |
| | | CarModel.carDesc[0].angle = 0.0; |
| | | |
| | | for (int i = 1; i < pointNum; ++i) { |
| | | double dis2 = (point[i][0]-basePoint[0])*(point[i][0]-basePoint[0]) + |
| | | (point[i][1]-basePoint[1])*(point[i][1]-basePoint[1]); |
| | | double dis = sqrt(dis2); |
| | | |
| | | CarModel->carDesc[i].distance = dis; |
| | | CarModel.carDesc[i].distance = dis; |
| | | |
| | | CarModel->carDesc[i].angle = 180 * acos((dis2 + C02 - ((point[i][0]-point[0][0])*(point[i][0]-point[0][0]) + |
| | | CarModel.carDesc[i].angle = 180 * acos((dis2 + C02 - ((point[i][0]-point[0][0])*(point[i][0]-point[0][0]) + |
| | | (point[i][1]-point[0][1])*(point[i][1]-point[0][1])))/(2*C0*dis)) / M_PI; |
| | | |
| | | if (i > axial[1]) |
| | | CarModel->carDesc[i].angle = 360.0 - CarModel->carDesc[i].angle; |
| | | CarModel.carDesc[i].angle = 360.0 - CarModel.carDesc[i].angle; |
| | | |
| | | DEBUG("加入点<%d> 距离 %f 角度 %f", i, CarModel->carDesc[i].distance, CarModel->carDesc[i].angle); |
| | | DEBUG("加入点<%d> 距离 %f 角度 %f", i, CarModel.carDesc[i].distance, CarModel.carDesc[i].angle); |
| | | } |
| | | |
| | | // CarModel->carDesc[0].distance = 0.2465; |
| | |
| | | DEBUG("SetCarMeasurePoint Calc Over"); |
| | | } |
| | | |
| | | /*********************************************** |
| | | * TIME1 - TIME2: millisecond |
| | | * @param rtkTime1 |
| | | * @param rtkTime2 |
| | | * @return |
| | | */ |
| | | uint32_t TimeGetDiff(const struct RtkTime *rtkTime1, const struct RtkTime *rtkTime2) |
| | | { |
| | | char tm1[64], tm2[64]; |
| | | |
| | | sprintf(tm1, "%02d%02d%02d%02d%02d%02d%03d", rtkTime1->YY, rtkTime1->MM, rtkTime1->DD, rtkTime1->hh, rtkTime1->mm, rtkTime1->ss, rtkTime1->mss*10); |
| | | sprintf(tm2, "%02d%02d%02d%02d%02d%02d%03d", rtkTime2->YY, rtkTime2->MM, rtkTime2->DD, rtkTime2->hh, rtkTime2->mm, rtkTime2->ss, rtkTime2->mss*10); |
| | | |
| | | if (strcmp(tm1, tm2) < 0) { |
| | | return (uint32_t)(-1); |
| | | } |
| | | |
| | | if (rtkTime1->YY == rtkTime2->YY && rtkTime1->MM == rtkTime2->MM && rtkTime1->DD == rtkTime2->DD) { |
| | | return TimeGetDiff(rtkTime1->hh, rtkTime1->mm, rtkTime1->ss, rtkTime1->mss*10, |
| | | rtkTime2->hh, rtkTime2->mm, rtkTime2->ss, rtkTime2->mss*10); |
| | | } else { |
| | | return (TimeMakeComposite(2000 + rtkTime1->YY, rtkTime1->MM, rtkTime1->DD, rtkTime1->hh, rtkTime1->mm, rtkTime1->ss) - |
| | | TimeMakeComposite(2000 + rtkTime2->YY, rtkTime2->MM, rtkTime2->DD, rtkTime2->hh, rtkTime2->mm, rtkTime2->ss)) * 1000 |
| | | + (1000 + rtkTime1->mss*10 - rtkTime2->mss*10) % 1000; |
| | | } |
| | | } |
| | | |
| | | void SetDummyLightExam(int n, struct dummy_light_exam *cfg) |
| | | { |
| | | DEBUG("获取模拟路考灯光测试项目 N = %d %d", n, ExamStart); |
| | | |
| | | static const int CONV_TABLE[] = {(FLASH_BEAM_LAMP<<8)+OFF_LIGHT, |
| | | (TURN_SIGNAL_LAMP<<8)+OFF_LIGHT, |
| | | (TURN_SIGNAL_LAMP<<8)+OFF_LIGHT, |
| | | (TURN_SIGNAL_LAMP<<8)+OFF_LIGHT, |
| | | (FOG_LAMP<<8)+OFF_LIGHT, |
| | | (CLEARANCE_LAMP<<8)+OFF_LIGHT, |
| | | (MAIN_BEAM_LAMP<<8)+OFF_LIGHT, |
| | | (DIPPED_BEAM_LAMP<<8)+OFF_LIGHT, |
| | | 0, |
| | | (DIPPED_BEAM_LAMP<<8)+DIPPED_BEAM_LIGHT, |
| | | (MAIN_BEAM_LAMP<<8)+MAIN_BEAM_LIGHT, |
| | | (CLEARANCE_LAMP<<8)+CLEARANCE_LIGHT, |
| | | (FOG_LAMP<<8)+FOG_LIGHT, |
| | | (TURN_SIGNAL_LAMP<<8)+LEFT_TURN_LIGHT, |
| | | (TURN_SIGNAL_LAMP<<8)+RIGHT_TURN_LIGHT, |
| | | (TURN_SIGNAL_LAMP<<8)+HAZARD_LIGHTS, |
| | | (FLASH_BEAM_LAMP<<8)+FLASH_BEAM_LIGHT}; |
| | | |
| | | const int *cov = CONV_TABLE + 8; |
| | | |
| | | if (ExamStart) return; |
| | | |
| | | if (DummyLightContent != NULL) { |
| | | delete []DummyLightContent; |
| | | DummyLightContent = NULL; |
| | | DummyLightContentSize = 0; |
| | | } |
| | | |
| | | DummyLightContent = new struct dummy_light_exam[n]; |
| | | DummyLightContentSize = n; |
| | | |
| | | for (int i = 0; i < n; i++) { |
| | | DummyLightContent[i].item = cfg[i].item; |
| | | DummyLightContent[i].tts = cfg[i].tts; |
| | | DummyLightContent[i].wrongCode = cfg[i].wrongCode; |
| | | // Sensor Name<<8 + Sensor Status |
| | | for (int j = 0; j < cfg[i].process.size(); ++j) { |
| | | DummyLightContent[i].process.push_back(cov[cfg[i].process[j]]); |
| | | } |
| | | for (int j = 0; j < cfg[i].solution.size(); ++j) { |
| | | DummyLightContent[i].solution.push_back(cov[cfg[i].solution[j]]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | void StartDriverExam(int start, int type) |
| | | { |
| | |
| | | if (start == 0) { |
| | | DEBUG("结束考试"); |
| | | |
| | | TerminateRoadExam(); |
| | | TerminateAreaExam(); |
| | | |
| | | |
| | | ExamStart = false; |
| | | MA_SendExamStatus(0, 0); |
| | |
| | | |
| | | // type = TEST_TYPE_ROAD_CALIBRATE; |
| | | |
| | | if (AreaMapList.size() == 0 && type == TEST_TYPE_AREA) { |
| | | /*if (AreaMapList.size() == 0 && type == TEST_TYPE_AREA) { |
| | | DEBUG("没有场考地图"); |
| | | err = true; |
| | | MA_SendExamStatus(0, -1); |
| | | } |
| | | if (CarModel == NULL) { |
| | | }*/ |
| | | if (CarModel.carDesc.size() == 0) { |
| | | DEBUG("没有车模"); |
| | | err = true; |
| | | MA_SendExamStatus(0, -2); |
| | |
| | | } |
| | | if (type == TEST_TYPE_ROAD_TRUE_LIGHT) { |
| | | RoadMap.calibrate = 0; |
| | | InitRoadExam(RoadMap); |
| | | } |
| | | if (type == TEST_TYPE_AREA) { |
| | | InitAreaExam(); |
| | | } |
| | | if (type == TEST_TYPE_ROAD_CALIBRATE) { |
| | | RoadMap.calibrate = 1; |
| | | InitRoadExam(RoadMap); |
| | | } |
| | | } |
| | | MA_SendExamStatus(1, 0); |
| | | } |
| | | } |
| | | |
| | | static void ClockGener(apptimer_var_t val) |
| | | /*************************************** |
| | | * 触发考试评判 |
| | | */ |
| | | static void work_thread(void) |
| | | { |
| | | rtk_info rtk; |
| | | while (true) { |
| | | sem.wait(); |
| | | |
| | | rtk.qf = 3; |
| | | rtk.heading = 0; |
| | | rtk.pitch = 0; |
| | | rtk.roll = 0; |
| | | rtk.x = 0; |
| | | rtk.y = 0; |
| | | |
| | | struct timeval tv; |
| | | struct timezone tz; |
| | | |
| | | gettimeofday(&tv, &tz); |
| | | |
| | | struct tm *pTime = localtime(&tv.tv_sec); |
| | | |
| | | rtk.YY = (pTime->tm_year + 1900) % 100; |
| | | rtk.MM = pTime->tm_mon + 1; |
| | | rtk.DD = pTime->tm_mday; |
| | | rtk.hh = pTime->tm_hour; |
| | | rtk.mm = pTime->tm_min; |
| | | rtk.ss = pTime->tm_sec; |
| | | rtk.dss = tv.tv_usec / 1000; |
| | | |
| | | // DEBUG("模拟时间 :%d-%d-%d %d:%d:%d.%d", rtk.YY, 1+pTime->tm_mon, pTime->tm_mday, pTime->tm_hour, pTime->tm_min, pTime->tm_sec, rtk.dss); |
| | | |
| | | UpdateRTKInfo(&rtk); |
| | | |
| | | AppTimer_add(ClockGener, 200); |
| | | // 计算当前车速,前进后退或停止 |
| | | realtimeMotionStatus = CalcMotionState(RtkInfoList); |
| | | // 累加里程 |
| | | UpdataOdo(realtimeMotionStatus); |
| | | // 计算当前车辆点坐标值 |
| | | prime.prev_modeling_index = prime.curr_modeling_index; |
| | | prime.curr_modeling_index = (prime.curr_modeling_index+1) % (sizeof (realtimeBodyModeling) / sizeof (realtimeBodyModeling[0])); |
| | | CalcBodyModeling(realtimeBodyModeling[prime.curr_modeling_index], CarModel, RtkInfoList.front()); |
| | | // 向UI上报车辆点坐标 |
| | | UploadModeling(realtimeMotionStatus, realtimeBodyModeling[prime.curr_modeling_index]); |
| | | // 触发考试项目 |
| | | if (ExamStart) { |
| | | ExecuteExam(prime); |
| | | } |
| | | } |
| | | } |
| | | |
| | | void UpdateRTKInfo(const rtk_info *s) |
| | | static motion_t CalcMotionState(std::list<rtk_info_t> &s) |
| | | { |
| | | std::unique_lock<std::mutex> lk(clock_mutex); |
| | | rtkClock.YY = s->YY; |
| | | rtkClock.MM = s->MM; |
| | | rtkClock.DD = s->DD; |
| | | rtkClock.hh = s->hh; |
| | | rtkClock.mm = s->mm; |
| | | rtkClock.ss = s->ss; |
| | | rtkClock.mss = s->dss; |
| | | lk.unlock(); |
| | | |
| | | if (ExamStart) { |
| | | ExecuteExam(&rtkClock); // 执行无需车辆定位的项目 |
| | | } |
| | | |
| | | if (s->qf == 3) { |
| | | RtkBuffer[RtkBufferIn] = *s; |
| | | RtkBufferIn = (RtkBufferIn + 1) % RTK_BUFFER_SIZE; |
| | | if (RtkBufferNum < RTK_BUFFER_SIZE) |
| | | RtkBufferNum++; |
| | | } else { |
| | | return; |
| | | } |
| | | motion_t motion; |
| | | |
| | | double speed; |
| | | int move; |
| | | int index; |
| | | move_status_t move; |
| | | |
| | | if (UpdateCarCoord(speed, move, index)) { |
| | | struct carBrief brief; |
| | | if (s.size() < 2) { |
| | | return motion; |
| | | } |
| | | |
| | | sprintf(brief.utc, "%04d%02d%02d%02d%02d%02d.%02d", 2000 + RtkBuffer[index].YY, |
| | | RtkBuffer[index].MM, RtkBuffer[index].DD, RtkBuffer[index].hh, |
| | | RtkBuffer[index].mm, RtkBuffer[index].ss, RtkBuffer[index].dss); |
| | | auto curr = s.begin(); |
| | | |
| | | brief.qf = RtkBuffer[index].qf; |
| | | brief.map_id = -1;//GetMapId(CurrExamMapIndex, MapList, MapNum); |
| | | brief.move = move; |
| | | brief.speed = speed * 3.6; |
| | | brief.heading = RtkBuffer[index].heading; |
| | | brief.main_ant[0] = RtkBuffer[index].x; |
| | | brief.main_ant[1] = RtkBuffer[index].y; |
| | | motion.timestamp = curr->utc_time; |
| | | |
| | | brief.axial[0] = CarModel->axial[0]; |
| | | brief.axial[1] = CarModel->axial[1]; |
| | | brief.left_front_tire[0] = CarModel->left_front_tire[0]; |
| | | brief.left_front_tire[1] = CarModel->left_front_tire[1]; |
| | | brief.right_front_tire[0] = CarModel->right_front_tire[0]; |
| | | brief.right_front_tire[1] = CarModel->right_front_tire[1]; |
| | | brief.left_rear_tire[0] = CarModel->left_rear_tire[0]; |
| | | brief.left_rear_tire[1] = CarModel->left_rear_tire[1]; |
| | | brief.right_rear_tire[0] = CarModel->right_rear_tire[0]; |
| | | brief.right_rear_tire[1] = CarModel->right_rear_tire[1]; |
| | | // 查找1秒前的点,如果找不到则视为停车 |
| | | auto prev = s.begin(); |
| | | std::advance(prev, 1); |
| | | |
| | | brief.bodyNum = CarModel->bodyNum; |
| | | brief.body = (int *) malloc(sizeof(int) * CarModel->bodyNum); |
| | | for (int i = 0; i < CarModel->bodyNum; ++i) { |
| | | brief.body[i] = CarModel->body[i]; |
| | | for (; prev != s.end(); ++prev) { |
| | | if (prev->utc_time - curr->utc_time > 3000) { |
| | | return motion; |
| | | } |
| | | if (prev->utc_time - curr->utc_time >= 1000) { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (prev == s.end()) { |
| | | return motion; |
| | | } |
| | | |
| | | // 计算速度(米/秒)、前进后退 |
| | | speed = sqrt(pow(curr->x - prev->x, 2) + pow(curr->y - prev->y, 2)) * 1000 / |
| | | static_cast<double>(curr->utc_time - prev->utc_time); |
| | | |
| | | double deg = 0.0; |
| | | |
| | | if (speed < 0.05) { |
| | | // 停车 |
| | | move = STOP; |
| | | } else { |
| | | // 判断前进还是后退 |
| | | if (fabs(curr->y - prev->y) <= GLB_EPSILON) { |
| | | if (curr->x > prev->x) { |
| | | deg = 90; |
| | | } else { |
| | | deg = 270; |
| | | } |
| | | } else if (fabs(curr->x - prev->x) <= GLB_EPSILON) { |
| | | if (curr->y > prev->y) { |
| | | deg = 0; |
| | | } else { |
| | | deg = 180; |
| | | } |
| | | } else { |
| | | deg = toDegree(atan(fabs(curr->x - prev->x) / |
| | | fabs(curr->y - prev->y))); |
| | | |
| | | if (curr->x > prev->x && |
| | | curr->y > prev->y) { |
| | | |
| | | } else if (curr->x < prev->x && |
| | | curr->y > prev->y) { |
| | | deg = 360 - deg; |
| | | } else if (curr->x < prev->x && |
| | | curr->y < prev->y) { |
| | | deg = 180 + deg; |
| | | } else if (curr->x > prev->x && |
| | | curr->y < prev->y) { |
| | | deg = 180 - deg; |
| | | } |
| | | } |
| | | |
| | | brief.pointNum = CarModel->pointNum; |
| | | brief.point = (double *) malloc(CarModel->pointNum * 2 * sizeof(double)); |
| | | for (int i = 0, j = 0; i < CarModel->pointNum; ++i) { |
| | | brief.point[j++] = round(CarModel->carXY[i].X, 4); |
| | | brief.point[j++] = round(CarModel->carXY[i].Y, 4); |
| | | deg = fabs(curr->heading - deg); |
| | | if (deg > 180) { |
| | | deg = 360 - deg; |
| | | } |
| | | if (deg < 90) { |
| | | // 前进 |
| | | move = FORWARD; |
| | | } else { |
| | | // 后退 |
| | | move = BACKWARD; |
| | | } |
| | | } |
| | | |
| | | motion.speed = speed; |
| | | motion.move = move; |
| | | |
| | | return motion; |
| | | } |
| | | |
| | | void UpdateRTKInfo(const rtk_info_t *s) |
| | | { |
| | | RtkInfoList.push_front(*s); |
| | | |
| | | while (RtkInfoList.size() > 100) { |
| | | RtkInfoList.pop_back(); |
| | | } |
| | | sem.signal(); |
| | | } |
| | | |
| | | static void UploadModeling(motion_t &motion, modeling_t &modeling) |
| | | { |
| | | struct carBrief brief; |
| | | |
| | | struct TimeStructure ts; |
| | | |
| | | TimeBreakdown(modeling.utc_time / 1000, &ts); |
| | | |
| | | sprintf(brief.utc, "%04d%02d%02d%02d%02d%02d.%02d", ts.Year, ts.Month, ts.Day, |
| | | ts.Hour, ts.Minute, ts.Second, (modeling.utc_time % 1000) / 10); |
| | | |
| | | brief.qf = 3; |
| | | brief.map_id = -1;//GetMapId(CurrExamMapIndex, MapList, MapNum); |
| | | brief.move = motion.move; |
| | | brief.speed = ConvertMs2KMh(motion.speed); |
| | | brief.heading = modeling.yaw; |
| | | brief.main_ant[0] = modeling.base_point.X; |
| | | brief.main_ant[1] = modeling.base_point.Y; |
| | | |
| | | brief.axial[0] = CarModel.axial[0]; |
| | | brief.axial[1] = CarModel.axial[1]; |
| | | brief.left_front_tire[0] = CarModel.left_front_tire[0]; |
| | | brief.left_front_tire[1] = CarModel.left_front_tire[1]; |
| | | brief.right_front_tire[0] = CarModel.right_front_tire[0]; |
| | | brief.right_front_tire[1] = CarModel.right_front_tire[1]; |
| | | brief.left_rear_tire[0] = CarModel.left_rear_tire[0]; |
| | | brief.left_rear_tire[1] = CarModel.left_rear_tire[1]; |
| | | brief.right_rear_tire[0] = CarModel.right_rear_tire[0]; |
| | | brief.right_rear_tire[1] = CarModel.right_rear_tire[1]; |
| | | |
| | | brief.body.assign(CarModel.body.begin(), CarModel.body.end()); |
| | | |
| | | for (auto po: modeling.points) { |
| | | brief.point.push_back({round(po.X, 4), round(po.Y, 4)}); |
| | | } |
| | | |
| | | MA_SendCarPosition(&brief); |
| | | |
| | | free(brief.body); |
| | | free(brief.point); |
| | | |
| | | struct RtkTime rtkTime; |
| | | double azimuth = RtkBuffer[index].heading; |
| | | |
| | | rtkTime.YY = RtkBuffer[index].YY; |
| | | rtkTime.MM = RtkBuffer[index].MM; |
| | | rtkTime.DD = RtkBuffer[index].DD; |
| | | rtkTime.hh = RtkBuffer[index].hh; |
| | | rtkTime.mm = RtkBuffer[index].mm; |
| | | rtkTime.ss = RtkBuffer[index].ss; |
| | | rtkTime.mss = RtkBuffer[index].dss; |
| | | |
| | | if (ExamStart) { |
| | | ExecuteExam(speed, move, azimuth, &rtkTime); |
| | | } |
| | | |
| | | // PrintObdInfo(&rtkTime, speed); |
| | | } |
| | | } |
| | | |
| | | static void PrintObdInfo(struct RtkTime *rtkTime, double speed) { |
| | | static struct RtkTime cTime = *rtkTime; |
| | | |
| | | if (TimeGetDiff(rtkTime, &cTime) >= D_SEC(3)) { |
| | | cTime = *rtkTime; |
| | | DEBUG("GEAR %d RPM %d OBD_SPEED %f SPEED %f", |
| | | ReadCarStatus(GEAR) - GEAR_N, |
| | | ReadCarStatus(ENGINE_RPM), |
| | | ((double)ReadCarStatus(OBD_SPEED)) / 10.0, |
| | | speed * 3.6); |
| | | } |
| | | } |
| | | |
| | | static void ExecuteExam(const struct RtkTime* rtkTime) |
| | | { |
| | | { |
| | | static const char *NAME[] = {"OBD_SPEED", |
| | | "ENGINE_RPM", |
| | | "挡位", |
| | | "转向灯", |
| | | "近光灯", |
| | | "雾灯", |
| | | "示廓灯", |
| | | "闪灯提示", |
| | | "远光灯", |
| | | "安全带", |
| | | "启动引擎", |
| | | "刹车", |
| | | "手刹", |
| | | "副刹车", |
| | | "车门", |
| | | "绕车一", |
| | | "绕车二", |
| | | "绕车三", |
| | | "绕车四", |
| | | "CAR_STATUS_END"}; |
| | | |
| | | static const char *VALUE[] = { |
| | | "关闭", |
| | | "告警灯", |
| | | "左转信号", |
| | | "右转信号", |
| | | "示廓灯亮", |
| | | "近光灯亮", |
| | | "远光灯亮", |
| | | "远近切换", |
| | | "雾灯亮", |
| | | "插入", |
| | | "在启动位", |
| | | "空档", |
| | | "一档", |
| | | "二档", |
| | | "三档", |
| | | "四档", |
| | | "五档", |
| | | "倒挡", |
| | | "踩下", |
| | | "门关闭", |
| | | "绕车发生" |
| | | }; |
| | | |
| | | |
| | | |
| | | static int cs[CAR_STATUS_END] = {0}; |
| | | |
| | | int cs_temp[CAR_STATUS_END]; |
| | | |
| | | for (int i = 0; i < CAR_STATUS_END; ++i) { |
| | | // DEBUG("读取......"); |
| | | cs_temp[i] = ReadCarStatus(i); |
| | | |
| | | // DEBUG("读取 %d <---- %d", i, cs_temp[i]); |
| | | } |
| | | |
| | | for (int i = 0; i < 2; ++i) { |
| | | if (cs_temp[i] != cs[i]) { |
| | | // DEBUG("车辆状态 %s = %d", NAME[i], cs_temp[i]); |
| | | |
| | | cs[i] = cs_temp[i]; |
| | | } |
| | | } |
| | | |
| | | for (int i = 2; i < CAR_STATUS_END; ++i) { |
| | | if (cs_temp[i] != cs[i]) { |
| | | DEBUG("车辆状态 %s = %s", NAME[i], VALUE[ cs_temp[i] ]); |
| | | |
| | | cs[i] = cs_temp[i]; |
| | | |
| | | // char buff[128]; |
| | | // sprintf(buff, "%s,%s", NAME[i], VALUE[ cs_temp[i] ]); |
| | | // PlayTTS(buff, NULL); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | if (ReadCarStatus(ENGINE_RPM) < ENGINE_MIN_ROTATE) { |
| | | if (engineRuning) { |
| | | engineRuning = false; |
| | | if (ExamType == TEST_TYPE_AREA) { |
| | | // 熄火1次,扣10分 |
| | | AddExamFault(10210, rtkTime); |
| | | } else { |
| | | AddExamFault(30208, rtkTime); |
| | | } |
| | | } |
| | | } else { |
| | | engineRuning = true; |
| | | } |
| | | |
| | | if (ReadCarStatus(ENGINE_START) == ENGINE_START_ACTIVE) { |
| | | if (!engineStart) { |
| | | DEBUG("检测到点火"); |
| | | engineStart = true; |
| | | if (ReadCarStatus(GEAR) != GEAR_N) { |
| | | DEBUG("不在空挡点火"); |
| | | // 不是空挡点火,不合格 |
| | | if (ExamType == TEST_TYPE_AREA) |
| | | AddExamFault(10105, rtkTime); |
| | | else |
| | | AddExamFault(30105, rtkTime); |
| | | } |
| | | AppTimer_delete(EngineStartHold); |
| | | AppTimer_add(EngineStartHold, examParam.hold_start_key_limit_time); |
| | | } |
| | | } else if (engineStart) { |
| | | DEBUG("检测到关闭点火"); |
| | | engineStart = false; |
| | | AppTimer_delete(EngineStartHold); |
| | | } |
| | | |
| | | if (ExamType == TEST_TYPE_ROAD_DUMMY_LIGHT) { |
| | | if (exam_dummy_light == 0) { |
| | | // StartPrepare(); |
| | | //// StartDummyLightExam(DummyLightContent, DummyLightContentSize, rtkTime); |
| | | // exam_dummy_light = 1; |
| | | // DEBUG("开始上车准备"); |
| | | |
| | | exam_dummy_light = 2; // 频闭上车准备 |
| | | } else if (exam_dummy_light == 2) { |
| | | DEBUG("开始灯光考试"); |
| | | StartDummyLightExam(DummyLightContent, DummyLightContentSize, rtkTime); |
| | | exam_dummy_light = 3; |
| | | } else if (exam_dummy_light == 3) { |
| | | if (!ExecuteDummyLightExam(rtkTime)) { |
| | | exam_dummy_light = 4; |
| | | // 汇报灯光考试结束 |
| | | DEBUG("灯光考试结束"); |
| | | InitRoadExam(RoadMap); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | static void ExecuteExam(double speed, int move, double azimuth, const struct RtkTime* rtkTime) |
| | | static void ExecuteExam(prime_t &prime) |
| | | { |
| | | static bool rec = false; |
| | | static bool handBreakActive = false, handBreakActive2 = false; |
| | | static double startCarMoveDistance; |
| | | static int prevMove = 0; |
| | | static move_status_t prevMove = STOP; |
| | | |
| | | if (move != 0) { |
| | | if (prime.pMotion->move != STOP) { |
| | | if (ReadCarStatus(SEATBELT) == EJECT_SEATBELT && !reportSeatbeltEject) { |
| | | DEBUG("不系安全带"); |
| | | reportSeatbeltEject = true; |
| | | AddExamFault(ExamType == TEST_TYPE_AREA? 10101: 30101, rtkTime); |
| | | AddExamFault(ExamType == TEST_TYPE_AREA? 10101: 30101); |
| | | } |
| | | if (rec) { |
| | | if (!handBreakActive2 && ReadOdo() - startCarMoveDistance >= examParam.start_car_limit_distance) { |
| | |
| | | if (ReadCarStatus(HAND_BREAK) == BREAK_ACTIVE) { |
| | | DEBUG("Handbreak active move over 10m"); |
| | | // 手刹拉起状态下,行驶了10米以上,不合格 |
| | | AddExamFault(40205, rtkTime); |
| | | AddExamFault(40205); |
| | | } else if (handBreakActive) { |
| | | // 手刹拉起状态下,行驶了1米以上,扣10分 |
| | | DEBUG("Handbreak active move over 1M"); |
| | | AddExamFault(40206, rtkTime); |
| | | AddExamFault(40206); |
| | | } |
| | | } |
| | | } else if (!handBreakActive && ReadOdo() - startCarMoveDistance >= examParam.open_door_drive_allow_distance && ReadCarStatus(HAND_BREAK) == BREAK_ACTIVE) { |
| | |
| | | |
| | | if (ExamType == TEST_TYPE_AREA) { |
| | | DEBUG("Handbreak active move over 1M"); |
| | | AddExamFault(10107, rtkTime); |
| | | AddExamFault(10107); |
| | | } |
| | | } |
| | | } |
| | | } else if (!rec || prevMove != 0) { // 记录停车点 |
| | | } else if (!rec || prevMove != STOP) { // 记录停车点 |
| | | rec = true; |
| | | handBreakActive = handBreakActive2 = false; |
| | | startCarMoveDistance = ReadOdo(); |
| | | } |
| | | |
| | | prevMove = move; |
| | | prevMove = prime.pMotion->move; |
| | | |
| | | if (ExamType != TEST_TYPE_AREA) { |
| | | if (exam_dummy_light == 4 || ExamType == TEST_TYPE_ROAD_TRUE_LIGHT || ExamType == TEST_TYPE_ROAD_CALIBRATE) { |
| | | TestRoadGeneral(RoadMap, CarModel, CarModelList, speed, move, rtkTime); |
| | | } |
| | | } else { |
| | | TestAreaGeneral(AreaMapList, CarModel, CarModelList, speed, move, azimuth, rtkTime); |
| | | } |
| | | AreaExam(prime); |
| | | } |
| | | |
| | | static void EngineStartHold(apptimer_var_t val) { |
| | | DEBUG("点火超时"); |
| | | if (ReadCarStatus(ENGINE_START) == ENGINE_START_ACTIVE) { |
| | | struct RtkTime rtkTime; |
| | | |
| | | std::unique_lock<std::mutex> lk(clock_mutex); |
| | | rtkTime = rtkClock; |
| | | lk.unlock(); |
| | | |
| | | // 不及时松开启动开关,扣10分 |
| | | if (ExamType == TEST_TYPE_AREA) { |
| | | AddExamFault(10201, &rtkTime); |
| | | AddExamFault(10201); |
| | | } else if (ExamType != TEST_TYPE_ROAD_CALIBRATE) { |
| | | AddExamFault(40207, &rtkTime); |
| | | AddExamFault(40207); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /************************************************* |
| | | * 2次采样相差的时间, a 最近的,b 先前的 |
| | | * @param a |
| | | * @param b |
| | | * @return ms |
| | | */ |
| | | static uint32_t CalcTimeDiff(const rtk_info *a, const rtk_info *b) |
| | | { |
| | | return TimeGetDiff(a->hh, a->mm, a->ss, a->dss*10, b->hh, b->mm, b->ss, b->dss*10); |
| | | } |
| | | |
| | | static bool UpdateCarCoord(double &spd, int &mov, int &idx) |
| | | { |
| | | long tmDiff; |
| | | |
| | | if (CarModel == NULL) |
| | | return false; |
| | | |
| | | if (RtkBufferNum < 2) |
| | | return false; |
| | | |
| | | int p1 = ((RtkBufferIn-1)+RTK_BUFFER_SIZE)%RTK_BUFFER_SIZE; // 最近采样值 |
| | | int p2 = ((RtkBufferIn-2)+RTK_BUFFER_SIZE)%RTK_BUFFER_SIZE; // 找到1秒前的采样值 |
| | | int pn = 0; |
| | | |
| | | for (pn = 1; pn < RtkBufferNum; ++pn) { |
| | | p2 = ((RtkBufferIn-1-pn)+RTK_BUFFER_SIZE)%RTK_BUFFER_SIZE; |
| | | if ((tmDiff = CalcTimeDiff(&RtkBuffer[p1], &RtkBuffer[p2])) >= D_SEC(1)) break; |
| | | } |
| | | |
| | | if (pn == RtkBufferNum) |
| | | return false; |
| | | |
| | | // 如果一定的时间都没有有效定位,删除之前的值 |
| | | /*tmDiff = CalcTimeDiff(&RtkBuffer[p1], &RtkBuffer[p2]); |
| | | |
| | | DEBUG("tmDiff = %ld, p1 = %d p2 = %d dss = %d dss2 = %d", tmDiff, p1, p2, RtkBuffer[p1].dss, RtkBuffer[p2].dss); |
| | | |
| | | if (tmDiff > D_SEC(5)) { |
| | | if (p1 != 0) |
| | | RtkBuffer[0] = RtkBuffer[p1]; |
| | | RtkBufferIn = RtkBufferNum = 1; |
| | | return false; |
| | | }*/ |
| | | |
| | | // 计算车辆轮廓点 |
| | | PointF main_ant_coord; |
| | | main_ant_coord.X = RtkBuffer[p1].x; |
| | | main_ant_coord.Y = RtkBuffer[p1].y; |
| | | |
| | | struct RtkTime tm; |
| | | |
| | | tm.YY = RtkBuffer[p1].YY; |
| | | tm.MM = RtkBuffer[p1].MM; |
| | | tm.DD = RtkBuffer[p1].DD; |
| | | tm.hh = RtkBuffer[p1].hh; |
| | | tm.mm = RtkBuffer[p1].mm; |
| | | tm.ss = RtkBuffer[p1].ss; |
| | | tm.mss = RtkBuffer[p1].dss; |
| | | |
| | | UpdateCarBodyCoord(&tm, RtkBuffer[p1].heading, RtkBuffer[p1].pitch, RtkBuffer[p1].roll, main_ant_coord, CarModel); |
| | | |
| | | car_model *newModel = (car_model *)malloc(sizeof(car_model)); |
| | | |
| | | newModel->tm = CarModel->tm; |
| | | newModel->basePoint = CarModel->basePoint; |
| | | newModel->axial[0] = CarModel->axial[0]; |
| | | newModel->axial[1] = CarModel->axial[1]; |
| | | newModel->left_front_tire[0] = CarModel->left_front_tire[0]; |
| | | newModel->left_front_tire[1] = CarModel->left_front_tire[1]; |
| | | newModel->right_front_tire[0] = CarModel->right_front_tire[0]; |
| | | newModel->right_front_tire[1] = CarModel->right_front_tire[1]; |
| | | newModel->left_rear_tire[0] = CarModel->left_rear_tire[0]; |
| | | newModel->left_rear_tire[1] = CarModel->left_rear_tire[1]; |
| | | newModel->right_rear_tire[0] = CarModel->right_rear_tire[0]; |
| | | newModel->right_rear_tire[1] = CarModel->right_rear_tire[1]; |
| | | newModel->bodyNum = CarModel->bodyNum; |
| | | newModel->body = (int *) malloc(sizeof(int) * newModel->bodyNum); |
| | | for (int i = 0; i < newModel->bodyNum; ++i) { |
| | | newModel->body[i] = CarModel->body[i]; |
| | | } |
| | | newModel->pointNum = CarModel->pointNum; |
| | | newModel->carXY = (PointF *) malloc(sizeof(PointF) * newModel->pointNum); |
| | | for (int i = 0; i < newModel->pointNum; ++i) { |
| | | newModel->carXY[i] = CarModel->carXY[i]; |
| | | } |
| | | newModel->carDesc = NULL; |
| | | newModel->antPitch = CarModel->antPitch; |
| | | newModel->yaw = CarModel->yaw; |
| | | newModel->pitch = CarModel->pitch; |
| | | |
| | | CarModelList.push_front(newModel); |
| | | |
| | | while (CarModelList.size() > 100) { |
| | | car_model *ptr = CarModelList.back(); |
| | | |
| | | if (ptr->body != NULL) |
| | | free(ptr->body); |
| | | if (ptr->carXY != NULL) |
| | | free(ptr->carXY); |
| | | if (ptr->carDesc != NULL) |
| | | free(ptr->carDesc); |
| | | |
| | | free(ptr); |
| | | |
| | | CarModelList.pop_back(); |
| | | } |
| | | |
| | | // 计算速度(米/秒)、前进后退 |
| | | double speed = sqrt(pow(RtkBuffer[p1].x - RtkBuffer[p2].x, 2) + pow(RtkBuffer[p1].y - RtkBuffer[p2].y, 2)) * 1000 / |
| | | (double)(tmDiff); |
| | | |
| | | // DEBUG("位移 %f 时间 %ld 速度 %f", sqrt(pow(RtkBuffer[p1].x - RtkBuffer[p2].x, 2) + pow(RtkBuffer[p1].y - RtkBuffer[p2].y, 2)), tmDiff, speed); |
| | | // DEBUG("%d %d %f, %f - %d %d %f, %f", RtkBuffer[p1].ss, RtkBuffer[p1].dss, RtkBuffer[p1].x, RtkBuffer[p1].y, RtkBuffer[p2].ss, RtkBuffer[p2].dss, RtkBuffer[p2].x, RtkBuffer[p2].y); |
| | | |
| | | int move = 0; |
| | | double deg = 0.0; |
| | | |
| | | if (speed < 0.05) { |
| | | // 停车 |
| | | move = 0; |
| | | } else { |
| | | // 判断前进还是后退 |
| | | if (fabs(RtkBuffer[p1].y - RtkBuffer[p2].y) <= GLB_EPSILON) { |
| | | if (RtkBuffer[p1].x > RtkBuffer[p2].x) { |
| | | deg = 90; |
| | | } else { |
| | | deg = 270; |
| | | } |
| | | } else if (fabs(RtkBuffer[p1].x - RtkBuffer[p2].x) <= GLB_EPSILON) { |
| | | if (RtkBuffer[p1].y > RtkBuffer[p2].y) { |
| | | deg = 0; |
| | | } else { |
| | | deg = 180; |
| | | } |
| | | } else { |
| | | deg = atan(fabs(RtkBuffer[p1].x - RtkBuffer[p2].x) / |
| | | fabs(RtkBuffer[p1].y - RtkBuffer[p2].y)); |
| | | |
| | | deg = toDegree(deg); |
| | | |
| | | if (RtkBuffer[p1].x > RtkBuffer[p2].x && |
| | | RtkBuffer[p1].y > RtkBuffer[p2].y) { |
| | | |
| | | } else if (RtkBuffer[p1].x < RtkBuffer[p2].x && |
| | | RtkBuffer[p1].y > RtkBuffer[p2].y) { |
| | | deg = 360 - deg; |
| | | } else if (RtkBuffer[p1].x < RtkBuffer[p2].x && |
| | | RtkBuffer[p1].y < RtkBuffer[p2].y) { |
| | | deg = 180 + deg; |
| | | } else if (RtkBuffer[p1].x > RtkBuffer[p2].x && |
| | | RtkBuffer[p1].y < RtkBuffer[p2].y) { |
| | | deg = 180 - deg; |
| | | } |
| | | } |
| | | |
| | | deg = fabs(RtkBuffer[p1].heading - deg); |
| | | if (deg > 180) { |
| | | deg = 360 - deg; |
| | | } |
| | | if (deg < 90) { |
| | | // 前进 |
| | | move = 1; |
| | | } else { |
| | | // 后退 |
| | | move = -1; |
| | | } |
| | | } |
| | | |
| | | spd = speed; |
| | | mov = move; |
| | | idx = p1; |
| | | // DEBUG("tmDiff = %ld speed = %f m/Sec move = %d", tmDiff, speed, move); |
| | | |
| | | return true; |
| | | } |
| | | |
| | | static int currRoad = -1, currCrossing = -1; |
| | | |
| | | void RoadChange(int road, int status) |
| | | { |
| | | struct roadStatusBrief brief; |
| | | |
| | | brief.road_id = road; |
| | | brief.status = status; |
| | | |
| | | MA_SendRoadStatus(&brief); |
| | | |
| | | currRoad = (status == 1? road : -1); |
| | | |
| | | DEBUG("报告长官 进出路段 road %d status %d", road, status); |
| | | } |
| | | |
| | | void CrossingChange(int road, int crossing, int status) |
| | | { |
| | | struct crossingStatusBrief brief; |
| | | |
| | | brief.road_id = road; |
| | | brief.crossing_index = crossing; |
| | | brief.status = status; |
| | | |
| | | MA_SendCrossingStatus(&brief); |
| | | |
| | | currCrossing = (status == 1? crossing : -1); |
| | | |
| | | DEBUG("报告长官 进出路口 road %d crossing %d status %d", road, crossing, status); |
| | | } |
| | | |
| | | void AddExamFault(int wrong, const struct RtkTime *rtkTime) |
| | | void AddExamFault(int wrong) |
| | | { |
| | | struct ExamFault fault; |
| | | |
| | |
| | | return; |
| | | |
| | | fault.sn = examFaultIndex++; |
| | | sprintf(fault.utc, "%04d%02d%02d%02d%02d%02d.%02d", 2000 + rtkTime->YY, |
| | | rtkTime->MM, rtkTime->DD, rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss); |
| | | |
| | | strcpy(fault.utc, StringUtil::FormatUTCTime(AppTimer_GetGmtTickCount()).c_str()); |
| | | |
| | | // if (ExamType != TEST_TYPE_AREA) { |
| | | // wrong += 1000; |
| | |
| | | MA_SendExamWrong(ExamFaultList); |
| | | |
| | | ExamFaultList.clear(); |
| | | } |
| | | |
| | | void MasterInqRoadStatus(void) |
| | | { |
| | | struct roadStatusBrief brief; |
| | | struct crossingStatusBrief brief2; |
| | | |
| | | brief2.road_id = brief.road_id = currRoad; |
| | | |
| | | if (currRoad >= 0) { |
| | | brief.status = 1; |
| | | |
| | | if (currCrossing >= 0) { |
| | | brief2.crossing_index = currCrossing; |
| | | brief2.status = 1; |
| | | } else { |
| | | brief2.crossing_index = -1; |
| | | brief2.status = 0; |
| | | } |
| | | } |
| | | else { |
| | | brief.status = 0; |
| | | brief2.crossing_index = -1; |
| | | brief2.status = 0; |
| | | } |
| | | |
| | | MA_SendRoadStatus(&brief); |
| | | |
| | | MA_SendCrossingStatus(&brief2); |
| | | } |
| | | |
| | | /*************************************************************** |
| | |
| | | * @param azimuth |
| | | * @param coord |
| | | */ |
| | | static void UpdateCarBodyCoord(struct RtkTime *rtkTime, double azimuth, double pitch, double roll, PointF main_ant, car_model *carModel) |
| | | static void CalcBodyModeling(modeling_t &car, car_model_t &carModel, rtk_info_t &rtk) |
| | | { |
| | | // 俯仰角修正 |
| | | // DEBUG("俯仰角 %f", pitch); |
| | | carModel->yaw = azimuth; |
| | | carModel->pitch = pitch; |
| | | carModel->tm = *rtkTime; |
| | | |
| | | pitch = pitch - carModel->antPitch; |
| | | car.utc_time = rtk.utc_time; |
| | | car.yaw = rtk.heading; |
| | | car.pitch = rtk.pitch; |
| | | car.roll = rtk.roll; |
| | | // 俯仰角修正 |
| | | double pitch = rtk.pitch - carModel.antPitch; |
| | | double azimuth = rtk.heading; |
| | | // DEBUG("yaw = %f 修正俯仰角 %f", azimuth, pitch); |
| | | |
| | | // 主天线投影修正 |
| | | carModel->basePoint.X = main_ant.X + fabs(carModel->antHeight - carModel->groundHeight) * sin(toRadians(pitch)) * sin(toRadians(azimuth)); |
| | | carModel->basePoint.Y = main_ant.Y + fabs(carModel->antHeight - carModel->groundHeight) * sin(toRadians(pitch)) * cos(toRadians(azimuth)); |
| | | car.base_point.X = rtk.x + fabs(carModel.antHeight - carModel.groundHeight) * sin(toRadians(pitch)) * sin(toRadians(azimuth)); |
| | | car.base_point.Y = rtk.y + fabs(carModel.antHeight - carModel.groundHeight) * sin(toRadians(pitch)) * cos(toRadians(azimuth)); |
| | | |
| | | for (int i = 0; i < carModel->pointNum; ++i) { |
| | | double qrx = carModel->carDesc[i].distance * sin(toRadians(carModel->carDesc[i].angle)); |
| | | double qry = |
| | | carModel->carDesc[i].distance * cos(toRadians(carModel->carDesc[i].angle)) * |
| | | // 首次计算 |
| | | if (car.points.size() != carModel.carDesc.size()) { |
| | | car.points.resize(carModel.carDesc.size()); |
| | | } |
| | | |
| | | for (int i = 0; i < carModel.carDesc.size(); ++i) { |
| | | double qrx = carModel.carDesc[i].distance * sin(toRadians(carModel.carDesc[i].angle)); |
| | | double qry = carModel.carDesc[i].distance * cos(toRadians(carModel.carDesc[i].angle)) * |
| | | cos(toRadians(pitch)); |
| | | |
| | | double projectDistance = sqrt(pow(qrx, 2) + pow(qry, 2)); |
| | | double projectAngle = toDegree(acos(qry / projectDistance)); |
| | | |
| | | if (carModel->carDesc[i].angle > 180) { |
| | | if (carModel.carDesc[i].angle > 180) { |
| | | projectAngle = 360 - projectAngle; |
| | | } |
| | | |
| | | // double tx = projectDistance*sin(toRadians(azimuth)); |
| | | // double ty = projectDistance*cos(toRadians(azimuth)); |
| | | |
| | | carModel->carXY[i].X = |
| | | projectDistance * sin(toRadians(azimuth)) * cos(toRadians(projectAngle)) - |
| | | projectDistance * cos(toRadians(azimuth)) * sin(toRadians(projectAngle)) + |
| | | carModel->basePoint.X; |
| | | carModel->carXY[i].Y = |
| | | projectDistance * sin(toRadians(azimuth)) * sin(toRadians(projectAngle)) + |
| | | projectDistance * cos(toRadians(azimuth)) * cos(toRadians(projectAngle)) + |
| | | carModel->basePoint.Y; |
| | | |
| | | car.points[i].X = projectDistance * sin(toRadians(azimuth)) * cos(toRadians(projectAngle)) - |
| | | projectDistance * cos(toRadians(azimuth)) * sin(toRadians(projectAngle)) + |
| | | car.base_point.X; |
| | | car.points[i].Y = projectDistance * sin(toRadians(azimuth)) * sin(toRadians(projectAngle)) + |
| | | projectDistance * cos(toRadians(azimuth)) * cos(toRadians(projectAngle)) + |
| | | car.base_point.Y; |
| | | // DEBUG("<%d>. 标距 %f 标角 %f X = %f Y = %f", i, carModel->carDesc[i].distance, carModel->carDesc[i].angle, |
| | | // carModel->carXY[i].X, carModel->carXY[i].Y); |
| | | } |
| | |
| | | |
| | | void SensorXChanged(uint16_t id, int value) |
| | | { |
| | | handlePrepare(id, value); |
| | | handleLigthExam(id, value); |
| | | // handlePrepare(id, value); |
| | | // handleLigthExam(id, value); |
| | | } |
| | | |
| | | void PrepareOver(int res) |
| | | { |
| | | DEBUG("上车准备结束 %d", res); |
| | | |
| | | if (res != 0) { |
| | | struct RtkTime rtkTime; |
| | | |
| | | std::unique_lock<std::mutex> lk(clock_mutex); |
| | | rtkTime = rtkClock; |
| | | lk.unlock(); |
| | | AddExamFault(40101, &rtkTime); |
| | | } |
| | | exam_dummy_light = 2; |
| | | } |