//
|
// Created by YY on 2019/10/21.
|
// Units note: distance - metre
|
// speed - metre per second
|
// angle - DEGREES
|
//
|
|
#include <cstdlib>
|
#include <cmath>
|
#include <semaphore.h>
|
#include <mutex>
|
#include <cstring>
|
#include <vector>
|
#include <list>
|
#include <numeric>
|
#include <algorithm>
|
#include <string>
|
|
#include "driver_test.h"
|
#include "defs.h"
|
#include "test_common/Geometry.h"
|
#include "common/apptimer.h"
|
#include "jni_log.h"
|
#include "test_items/park_edge.h"
|
#include "native-lib.h"
|
#include "test_items/park_bottom.h"
|
#include "test_items/park_edge.h"
|
#include "test_items/error_list.h"
|
#include "test_items/turn_a90.h"
|
#include "test_items/driving_curve.h"
|
#include "test_items/stop_and_start.h"
|
#include "master/comm_if.h"
|
#include "utils/xconvert.h"
|
#include "utils/num.h"
|
#include "test_common/car_sensor.h"
|
#include "mcu/mcu_if.h"
|
#include "test_common/car_sensor.h"
|
#include "test_items/area_exam.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)
|
|
using namespace std;
|
|
#define RTK_INVALID 0
|
#define RTK_SINGLE_POINT 1
|
#define RTK_DIFF 2
|
#define RTK_FIX 3
|
#define RTK_FLOAT 4
|
|
#define CAR_MODEL_POINT_NUM 32
|
#define MAP_LIST_SIZE 32
|
|
enum {
|
TEST_TYPE_AREA = 2,
|
TEST_TYPE_ROAD_DUMMY_LIGHT,
|
TEST_TYPE_ROAD_TRUE_LIGHT,
|
TEST_TYPE_ROAD_CALIBRATE
|
};
|
|
static const int DEFAULT_START_KEY_HOLD_TIME = D_SEC(2);
|
static const int DEFAULT_CURVE_PAUSE_TIME = D_SEC(2);
|
static const int DEFAULT_PARK_BOTTOM_PAUSE_TIME = D_SEC(2);
|
static const int DEFAULT_PARK_BOTTOM_FINISH_TIME = D_SEC(210);
|
static const int DEFAULT_PART_EDGE_PAUSE_TIME = D_SEC(2);
|
static const int DEFAULT_PARK_EDGE_FINISH_TIME = D_SEC(90);
|
static const int DEFAULT_TURN_A90_PAUSE_TIME = D_SEC(2);
|
static const int DEFAULT_RAMP_FINISH_TIME = D_SEC(30);
|
static const double DEFAULT_RAMP_STOPPOINT_RED_DISTANCE = 0.5;
|
static const double DEFAULT_RAMP_EDGE_YELLOW_DISTANCE = 0.3;
|
static const double DEFAULT_RAMP_EDGE_RED_DISTANCE = 0.5;
|
static const double DEFAULT_RAMP_SLIDE_YELLOW_DISTANCE = 0.1;
|
static const double DEFAULT_RAMP_SLIDE_RED_DISTANCE = 0.3;
|
|
static const double DEFAULT_ROAD_SLIDE_YELLOW_DISTANCE = 0.1;
|
static const double DEFAULT_ROAD_SLIDE_RED_DISTANCE = 0.3;
|
static const int DEFAULT_ROAD_MAX_DISTANCE = 3000;
|
static const int DEFAULT_ROAD_MAX_SPEED = 60;
|
static const int DEFAULT_GEAR_N_TIME = D_SEC(5);
|
static const int DEFAULT_SAME_GEAR_HOLD_TIME = D_SEC(5);
|
static const int DEFAULT_GEAR_SPEED_ERROR_MAX_TIME = D_SEC(15);
|
static const int DEFAULT_ROAD_PAUSE_TIME = D_SEC(2);
|
static const int DEFAULT_CHANGE_LANE_MIN_TIME = D_SEC(10);
|
static const int DEFAULT_CRASH_DOTTED_LINE_MAX_TIME = D_SEC(10);
|
static const int DEFAULT_TURN_SIGNAL_MIN_ADVANCE = D_SEC(3);
|
static const int DEFAULT_START_CAR_MAX_RMP = 2500;
|
static const int DEFAULT_START_CAR_DISTANCE = 10;
|
static const double DEFAULT_START_CAR_OPEN_DOOR_DISTANCE = 1.0;
|
static const char DEFAULT_PREPARE_TTS[] = "请开始上车准备";
|
static const char DEFAULT_TOUCH_LEFT_FRONT[] = "学员通过左前方";
|
static const char DEFAULT_TOUCH_LEFT_REAR[] = "学员通过左后方";
|
static const char DEFAULT_TOUCH_RIGHT_FRONT[] = "学员通过右前方";
|
static const char DEFAULT_TOUCH_RIGHT_REAR[] = "学员通过右后方";
|
static const char DEFAULT_START_ENGINE[] = "请启动发动机";
|
static const char DEFAULT_START_CAR_BEGIN_TTS[] = "请起步,继续完成考试";
|
static const char DEFAULT_START_CAR_END_TTS[] = "起步完成";
|
static const int CHANGE_LANE_MAX_DISTANCE = 100;
|
static const char DEFAULT_CHANGE_LANE_BEGIN_TTS[] = "前方请变更车道";
|
static const char DEFAULT_CHANGE_LANE_END_TTS[] = "变道完成";
|
static const int DEFAULT_SHIFT_MAX_DISTANCE = 120;
|
static const int DEFAULT_SHIFT_HOLD_TIME = D_SEC(3);
|
static const char DEFAULT_SHIFT_BEGIN_TTS[] = "请进行加减挡位操作";
|
static const char DEFAULT_SHIFT_END_TTS[] = "加减挡位完成";
|
static const char DEFAULT_STRAIGHT_BEGIN_TTS[] = "请保持直线行驶";
|
static const char DEFAULT_STRAIGHT_END_TTS[] = "直线行驶完成";
|
static const int DEFAULT_STRAIGHT_MAX_DISTANCE = 100;
|
static const double DEFAULT_STRAIGHT_MAX_OFFSET = 0.3;
|
static const int DEFAULT_OVERTAKE_MAX_DISTANCE = 150;
|
static const char DEFAULT_OVERTAKE_BEGIN_TTS[] = "请超越前方车辆";
|
static const char DEFAULT_OVERTAKE_END_TTS[] = "超车完成";
|
static const int DEFAULT_STOP_CAR_MAX_DISTANCE = 150;
|
static const int DEFAULT_STOP_CAR_OPEN_DOOR_MAX_TIME = D_SEC(15);
|
static const double DEFAULT_STOP_CAR_EDGE_RED_DISTANCE = 0.5;
|
static const double DEFAULT_STOP_CAR_EDGE_YELLOW_DISTANCE = 0.5;
|
static const char DEFAULT_STOP_CAR_BEGIN_TTS[] = "请靠边停车";
|
static const char DEFAULT_STOP_CAR_END_TTS[] = "靠边停车完成";
|
static const double DEFAULT_CROSSING_STOP_VALID_DISTANCE = 3.0;
|
static const int DEFAULT_CROSS_SCHOOL_MAX_SPEED = 30;
|
static const int DEFAULT_CROSS_BREAK_VALID_DISTANCE = 30;
|
|
static const char DEFAULT_CROSSING_GO_STRAIGHT_TTS[] = "前方路口直行";
|
static const char DEFAULT_CROSSING_TURN_LEFT_TTS[] = "前方路口左转";
|
static const char DEFAULT_CROSSING_TURN_RIGHT_TTS[] = "前方路口右转";
|
static const char DEFAULT_CROSSING_TURN_BACK_TTS[] = "前方选择合适地点掉头";
|
static const char DEFAULT_CROSSING_TURN_UNKNOWN_TTS[] = "前方路口听从教练指示";
|
|
static bool ExamStart = false;
|
static int ExamType;
|
static bool reportSeatbeltEject;
|
|
vector<ExamFault> ExamFaultList;
|
static int examFaultIndex = 0;
|
|
//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_t CarModel;
|
|
//static LIST_CAR_MODEL CarModelList; // 一段时间的车辆轨迹集合
|
|
static struct dummy_light_exam *DummyLightContent;
|
static int DummyLightContentSize;
|
static bool engineRuning = false;
|
const int ENGINE_MIN_ROTATE = 200;
|
static bool engineStart = false;
|
|
exam_param_t examParam;
|
|
#define MOV_AVG_SIZE 1
|
#define RTK_BUFFER_SIZE 100
|
#define CAR_MODEL_CACHE_SIZE 10
|
|
static std::list<rtk_info_t> RtkInfoList;
|
|
// 存入前后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 motion_t CalcMotionState(std::list<rtk_info_t> &s);
|
static void ExecuteExam(prime_t &prime);
|
|
static void ReadDriverExamPrimerTimeout(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();
|
|
// CarModelList.clear();
|
|
// AreaMapList.clear();
|
|
RoadMap.roads.clear();
|
RoadMap.specialAreas.clear();
|
RoadMap.forbidLines.clear();
|
RoadMap.examScheme.clear();
|
|
CarSensorInit();
|
|
DummyLightContentSize = 0;
|
DummyLightContent = NULL;
|
|
std::thread(work_thread).detach();
|
}
|
|
static void SetExamParamDefault(void)
|
{
|
examParam.hold_start_key_limit_time = DEFAULT_START_KEY_HOLD_TIME;
|
examParam.curve_pause_criteria = DEFAULT_CURVE_PAUSE_TIME;
|
examParam.park_bottom_pause_criteria = DEFAULT_PARK_BOTTOM_PAUSE_TIME;
|
examParam.park_bottom_limit_time = DEFAULT_PARK_BOTTOM_FINISH_TIME;
|
examParam.park_edge_pause_criteria = DEFAULT_PART_EDGE_PAUSE_TIME;
|
examParam.park_edge_limit_time = DEFAULT_PARK_EDGE_FINISH_TIME;
|
examParam.turn_a90_pause_criteria = DEFAULT_TURN_A90_PAUSE_TIME;
|
|
examParam.ramp_stoppoint_red_distance = DEFAULT_RAMP_STOPPOINT_RED_DISTANCE;
|
examParam.ramp_edge_yellow_distance = DEFAULT_RAMP_EDGE_YELLOW_DISTANCE;
|
examParam.ramp_edge_red_distance = DEFAULT_RAMP_EDGE_RED_DISTANCE;
|
examParam.ramp_slide_yellow_distance = DEFAULT_RAMP_SLIDE_YELLOW_DISTANCE;
|
examParam.ramp_slide_red_distance = DEFAULT_RAMP_SLIDE_RED_DISTANCE;
|
examParam.ramp_start_car_limit_time = DEFAULT_RAMP_FINISH_TIME;
|
|
examParam.road_slide_yellow_distance = DEFAULT_ROAD_SLIDE_YELLOW_DISTANCE;
|
examParam.road_slide_red_distance = DEFAULT_ROAD_SLIDE_RED_DISTANCE;
|
examParam.road_total_distance = DEFAULT_ROAD_MAX_DISTANCE;
|
examParam.road_max_speed = DEFAULT_ROAD_MAX_SPEED;
|
|
examParam.gear_speed_table.resize(6);
|
for (int i = 0; i < examParam.gear_speed_table.size(); ++i) {
|
examParam.gear_speed_table[i].resize(2);
|
}
|
examParam.gear_speed_table[0][0] = 0;
|
examParam.gear_speed_table[0][1] = 20;
|
examParam.gear_speed_table[1][0] = 5;
|
examParam.gear_speed_table[1][1] = 30;
|
examParam.gear_speed_table[2][0] = 15;
|
examParam.gear_speed_table[2][1] = 40;
|
examParam.gear_speed_table[3][0] = 25;
|
examParam.gear_speed_table[3][1] = 10000;
|
examParam.gear_speed_table[4][0] = 35;
|
examParam.gear_speed_table[4][1] = 10000;
|
examParam.gear_speed_table[5][0] = 45;
|
examParam.gear_speed_table[5][1] = 10000;
|
|
examParam.gear_n_allow_time = DEFAULT_GEAR_N_TIME;
|
examParam.same_gear_min_time = DEFAULT_SAME_GEAR_HOLD_TIME; // x秒内,不允许N->X->N->X置同一挡位
|
examParam.gear_speed_error_cumulative_time = DEFAULT_GEAR_SPEED_ERROR_MAX_TIME;
|
examParam.road_pause_criteria = DEFAULT_ROAD_PAUSE_TIME;
|
examParam.continuous_change_lane_min_time = DEFAULT_CHANGE_LANE_MIN_TIME;
|
examParam.crash_dotted_line_cumulative_time = DEFAULT_CRASH_DOTTED_LINE_MAX_TIME;
|
examParam.turn_signal_min_advance = DEFAULT_TURN_SIGNAL_MIN_ADVANCE;
|
examParam.start_car_max_rpm = DEFAULT_START_CAR_MAX_RMP;
|
examParam.start_car_limit_distance = DEFAULT_START_CAR_DISTANCE;
|
examParam.open_door_drive_allow_distance = DEFAULT_START_CAR_OPEN_DOOR_DISTANCE;
|
|
examParam.prepare_tts = DEFAULT_PREPARE_TTS;
|
examParam.touch_leftfront_tts = DEFAULT_TOUCH_LEFT_FRONT;
|
examParam.touch_leftrear_tts = DEFAULT_TOUCH_LEFT_REAR;
|
examParam.touch_rightfront_tts = DEFAULT_TOUCH_RIGHT_FRONT;
|
examParam.touch_rightrear_tts = DEFAULT_TOUCH_RIGHT_REAR;
|
examParam.start_engine_tts = DEFAULT_START_ENGINE;
|
|
examParam.start_car_begin_tts = DEFAULT_START_CAR_BEGIN_TTS;
|
examParam.start_car_end_tts = DEFAULT_START_CAR_END_TTS;
|
examParam.change_lane_limit_distance = CHANGE_LANE_MAX_DISTANCE;
|
examParam.change_lane_begin_tts = DEFAULT_CHANGE_LANE_BEGIN_TTS;
|
examParam.change_lane_end_tts = DEFAULT_CHANGE_LANE_END_TTS;
|
examParam.shift_limit_distance = DEFAULT_SHIFT_MAX_DISTANCE;
|
examParam.shift_hold_time = DEFAULT_SHIFT_HOLD_TIME;
|
examParam.shift_begin_tts = DEFAULT_SHIFT_BEGIN_TTS;
|
examParam.shift_end_tts = DEFAULT_SHIFT_END_TTS;
|
examParam.shift_up_tts = "";
|
examParam.shift_down_tts = "";
|
|
examParam.straight_begin_tts = DEFAULT_STRAIGHT_BEGIN_TTS;
|
examParam.straight_end_tts = DEFAULT_STRAIGHT_END_TTS;
|
examParam.straight_limit_distance = DEFAULT_STRAIGHT_MAX_DISTANCE;
|
examParam.straight_max_offset = DEFAULT_STRAIGHT_MAX_OFFSET;
|
|
examParam.overtake_limit_distance = DEFAULT_OVERTAKE_MAX_DISTANCE;
|
examParam.overtake_begin_tts = DEFAULT_OVERTAKE_BEGIN_TTS;
|
examParam.overtake_end_tts = DEFAULT_OVERTAKE_END_TTS;
|
|
examParam.stop_car_limit_distance = DEFAULT_STOP_CAR_MAX_DISTANCE;
|
examParam.stop_car_open_door_allow_time = DEFAULT_STOP_CAR_OPEN_DOOR_MAX_TIME;
|
examParam.stop_car_edge_red_distance = DEFAULT_STOP_CAR_EDGE_RED_DISTANCE;
|
examParam.stop_car_edge_yellow_distance = DEFAULT_STOP_CAR_EDGE_YELLOW_DISTANCE;
|
examParam.stop_car_begin_tts = DEFAULT_STOP_CAR_BEGIN_TTS;
|
examParam.stop_car_end_tts = DEFAULT_STOP_CAR_END_TTS;
|
examParam.crossing_stop_valid_distance = DEFAULT_CROSSING_STOP_VALID_DISTANCE;
|
examParam.cross_school_max_speed = DEFAULT_CROSS_SCHOOL_MAX_SPEED;
|
examParam.crossing_break_valid_distance = DEFAULT_CROSS_BREAK_VALID_DISTANCE;
|
|
examParam.crossing_go_straight_tts = DEFAULT_CROSSING_GO_STRAIGHT_TTS;
|
examParam.crossing_turn_left_tts = DEFAULT_CROSSING_TURN_LEFT_TTS;
|
examParam.crossing_turn_right_tts = DEFAULT_CROSSING_TURN_RIGHT_TTS;
|
examParam.crossing_turn_back_tts = DEFAULT_CROSSING_TURN_BACK_TTS;
|
examParam.crossing_turn_unknown_tts = DEFAULT_CROSSING_TURN_UNKNOWN_TTS;
|
}
|
|
static void ReadDriverExamPrimerTimeout(apptimer_var_t val)
|
{
|
ReadDriverExamPrimer();
|
}
|
|
void ReadDriverExamPrimer(void)
|
{
|
MA_ReadMap();
|
MA_ReadCar();
|
MA_ReadSensor();
|
}
|
|
void ClearAreaMap(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);
|
// }
|
//
|
// 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)
|
{
|
if (map == NULL || pointNum == 0 || ExamStart)
|
return;
|
DEBUG("加入地图信息 id %d type %d pointNum %d point2Num %d", id, type, pointNum, pointNum2);
|
|
// 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);
|
}
|
|
void AddCurveMap(curve_map_t &map)
|
{
|
AreaMap.curve_map.push_back(map);
|
}
|
|
void AddParkButtonMap(park_button_map_t &map)
|
{
|
AreaMap.park_button_map.push_back(map);
|
}
|
|
void AddParkEdgeMap(park_edge_map_t &map)
|
{
|
AreaMap.park_edge_map.push_back(map);
|
}
|
|
void CleanRoadMap(void)
|
{
|
if (ExamStart) return;
|
|
DEBUG("清除旧的路考地图");
|
|
vector<road_t>().swap(RoadMap.roads);
|
vector<special_area_t>().swap(RoadMap.specialAreas);
|
vector<forbid_line_t>().swap(RoadMap.forbidLines);
|
// vector<scheme_t>().swap(RoadMap.examScheme);
|
}
|
|
void SetRoadMap(road_exam_map &map, vector<scheme_t> &scheme)
|
{
|
if (ExamStart) return;
|
|
RoadMap.roads.assign(map.roads.begin(), map.roads.end());
|
RoadMap.specialAreas.assign(map.specialAreas.begin(), map.specialAreas.end());
|
// RoadMap.triggerLines.assign(map.triggerLines.begin(), map.triggerLines.end());
|
RoadMap.forbidLines.assign(map.forbidLines.begin(), map.forbidLines.end());
|
|
// RoadMap.examScheme.assign(scheme.begin(), scheme.end());
|
|
DEBUG("得到新的路考地图 路数量 %d 特殊区域数量 %d 其他禁止线数量 %d 项目数量 %d", RoadMap.roads.size(), RoadMap.specialAreas.size(), RoadMap.forbidLines.size(), RoadMap.examScheme.size());
|
|
/*for (int i = 0; i < RoadMap.roads.size(); ++i) {
|
DEBUG("路 id = %d", RoadMap.roads[i].id);
|
DEBUG("左边线段数 %d", RoadMap.roads[i].leftEdge.size());
|
for (int j = 0; j < RoadMap.roads[i].leftEdge.size(); ++j) {
|
int n = RoadMap.roads[i].leftEdge[j].points.size();
|
|
DEBUG("\t当前左边线段 类型 %d 点数 %d", RoadMap.roads[i].leftEdge[j].character, n);
|
for (int k = 0; k < n; ++k) {
|
DEBUG("\t\t点坐标 %d: %f, %f", k, RoadMap.roads[i].leftEdge[j].points[k].X, RoadMap.roads[i].leftEdge[j].points[k].Y);
|
}
|
}
|
|
DEBUG("右边线段数 %d", RoadMap.roads[i].rightEdge.size());
|
for (int j = 0; j < RoadMap.roads[i].rightEdge.size(); ++j) {
|
int n = RoadMap.roads[i].rightEdge[j].points.size();
|
|
DEBUG("\t当前右边线段 类型 %d 点数 %d", RoadMap.roads[i].rightEdge[j].character, n);
|
for (int k = 0; k < n; ++k) {
|
DEBUG("\t\t点坐标 %d: %f, %f", k, RoadMap.roads[i].rightEdge[j].points[k].X, RoadMap.roads[i].rightEdge[j].points[k].Y);
|
}
|
}
|
}*/
|
}
|
|
void SetRoadExamScheme(vector<scheme_t> &scheme)
|
{
|
if (ExamStart) return;
|
|
vector<scheme_t>().swap(RoadMap.examScheme);
|
|
RoadMap.examScheme.assign(scheme.begin(), scheme.end());
|
|
DEBUG("得到路考项目方案 项目数量 %d", RoadMap.examScheme.size());
|
}
|
|
void SetCarMeasurePoint(double *basePoint, int *axial, int *left_front_tire,
|
int *right_front_tire, int *left_rear_tire, int *right_rear_tire,
|
int *body, int bodyNum, double (*point)[2], int pointNum, double antPitch, double antHeight, double groundHeight)
|
{
|
DEBUG("加入车辆信息 pointNum %d", pointNum);
|
|
if (point == NULL || pointNum == 0 || ExamStart) return;
|
|
vector<int>().swap(CarModel.body);
|
vector<car_desc_t>().swap(CarModel.carDesc);
|
|
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];
|
|
if (bodyNum == 0 || body == NULL) {
|
for (int i = 0; i < 6; ++i) {
|
CarModel.body.push_back(i);
|
}
|
} else {
|
for (int i = 0; i < bodyNum; ++i) {
|
CarModel.body.push_back(body[i]);
|
}
|
}
|
|
CarModel.antPitch = antPitch;
|
CarModel.antHeight = antHeight;
|
CarModel.groundHeight = groundHeight;
|
|
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;
|
|
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].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;
|
|
DEBUG("加入点<%d> 距离 %f 角度 %f", i, CarModel.carDesc[i].distance, CarModel.carDesc[i].angle);
|
}
|
|
// CarModel->carDesc[0].distance = 0.2465;
|
// CarModel->carDesc[0].angle = 0;
|
//
|
// CarModel->carDesc[1].distance = 0.2635;
|
// CarModel->carDesc[1].angle = 20.7;
|
//
|
// CarModel->carDesc[2].distance = 0.14;
|
// CarModel->carDesc[2].angle = 138.9;
|
//
|
// CarModel->carDesc[3].distance = 0.1055;
|
// CarModel->carDesc[3].angle = 180.0;
|
//
|
// CarModel->carDesc[4].distance = 0.14;
|
// CarModel->carDesc[4].angle = 221.1;
|
//
|
// CarModel->carDesc[5].distance = 0.2635;
|
// CarModel->carDesc[5].angle = 339.3;
|
|
DEBUG("SetCarMeasurePoint Calc Over");
|
}
|
|
|
void StartDriverExam(int start, int type)
|
{
|
bool err = false;
|
DEBUG("++++++++++++考试启动 start %d type %d+++++++++++++", start, type);
|
|
if (start == 0) {
|
DEBUG("结束考试");
|
|
TerminateAreaExam();
|
|
ExamStart = false;
|
MA_SendExamStatus(0, 0);
|
return;
|
}
|
|
// type = TEST_TYPE_ROAD_CALIBRATE;
|
|
/*if (AreaMapList.size() == 0 && type == TEST_TYPE_AREA) {
|
DEBUG("没有场考地图");
|
err = true;
|
MA_SendExamStatus(0, -1);
|
}*/
|
if (CarModel.carDesc.size() == 0) {
|
DEBUG("没有车模");
|
err = true;
|
MA_SendExamStatus(0, -2);
|
}
|
if (DummyLightContent == NULL && type == TEST_TYPE_ROAD_DUMMY_LIGHT) {
|
DEBUG("没有模拟灯光");
|
// err = true;
|
// MA_SendExamStatus(0, -3);
|
}
|
if (type != TEST_TYPE_AREA && RoadMap.roads.size() == 0) {
|
DEBUG("没有路考地图");
|
err = true;
|
MA_SendExamStatus(0, -1);
|
}
|
|
if ((type == TEST_TYPE_ROAD_DUMMY_LIGHT || type == TEST_TYPE_ROAD_TRUE_LIGHT) && RoadMap.examScheme.size() == 0) {
|
DEBUG("没有路考线路方案");
|
err = true;
|
MA_SendExamStatus(0, -3);
|
}
|
|
if (!err) {
|
if (!ExamStart) {
|
DEBUG("启动考试");
|
ExamFaultList.clear();
|
examFaultIndex = 0;
|
|
ExamStart = true;
|
ExamType = type;
|
reportSeatbeltEject = false;
|
|
if (type == TEST_TYPE_ROAD_DUMMY_LIGHT) {
|
exam_dummy_light = 0; //0
|
RoadMap.calibrate = 0;
|
}
|
if (type == TEST_TYPE_ROAD_TRUE_LIGHT) {
|
RoadMap.calibrate = 0;
|
}
|
if (type == TEST_TYPE_AREA) {
|
InitAreaExam();
|
}
|
if (type == TEST_TYPE_ROAD_CALIBRATE) {
|
RoadMap.calibrate = 1;
|
}
|
}
|
MA_SendExamStatus(1, 0);
|
}
|
}
|
|
/***************************************
|
* 触发考试评判
|
*/
|
static void work_thread(void)
|
{
|
while (true) {
|
sem.wait();
|
|
// 计算当前车速,前进后退或停止
|
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);
|
}
|
}
|
}
|
|
static motion_t CalcMotionState(std::list<rtk_info_t> &s)
|
{
|
motion_t motion;
|
|
double speed;
|
move_status_t move;
|
|
if (s.size() < 2) {
|
return motion;
|
}
|
|
auto curr = s.begin();
|
|
motion.timestamp = curr->utc_time;
|
|
// 查找1秒前的点,如果找不到则视为停车
|
auto prev = s.begin();
|
std::advance(prev, 1);
|
|
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;
|
}
|
}
|
|
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);
|
}
|
|
static void ExecuteExam(prime_t &prime)
|
{
|
static bool rec = false;
|
static bool handBreakActive = false, handBreakActive2 = false;
|
static double startCarMoveDistance;
|
static move_status_t prevMove = STOP;
|
|
if (prime.pMotion->move != STOP) {
|
if (ReadCarStatus(SEATBELT) == EJECT_SEATBELT && !reportSeatbeltEject) {
|
DEBUG("不系安全带");
|
reportSeatbeltEject = true;
|
AddExamFault(ExamType == TEST_TYPE_AREA? 10101: 30101);
|
}
|
if (rec) {
|
if (!handBreakActive2 && ReadOdo() - startCarMoveDistance >= examParam.start_car_limit_distance) {
|
handBreakActive2 = true;
|
|
if (ExamType == TEST_TYPE_ROAD_DUMMY_LIGHT || ExamType == TEST_TYPE_ROAD_TRUE_LIGHT) {
|
if (ReadCarStatus(HAND_BREAK) == BREAK_ACTIVE) {
|
DEBUG("Handbreak active move over 10m");
|
// 手刹拉起状态下,行驶了10米以上,不合格
|
AddExamFault(40205);
|
} else if (handBreakActive) {
|
// 手刹拉起状态下,行驶了1米以上,扣10分
|
DEBUG("Handbreak active move over 1M");
|
AddExamFault(40206);
|
}
|
}
|
} else if (!handBreakActive && ReadOdo() - startCarMoveDistance >= examParam.open_door_drive_allow_distance && ReadCarStatus(HAND_BREAK) == BREAK_ACTIVE) {
|
handBreakActive = true;
|
|
if (ExamType == TEST_TYPE_AREA) {
|
DEBUG("Handbreak active move over 1M");
|
AddExamFault(10107);
|
}
|
}
|
}
|
} else if (!rec || prevMove != STOP) { // 记录停车点
|
rec = true;
|
handBreakActive = handBreakActive2 = false;
|
startCarMoveDistance = ReadOdo();
|
}
|
|
prevMove = prime.pMotion->move;
|
|
AreaExam(prime);
|
}
|
|
static void EngineStartHold(apptimer_var_t val) {
|
DEBUG("点火超时");
|
if (ReadCarStatus(ENGINE_START) == ENGINE_START_ACTIVE) {
|
// 不及时松开启动开关,扣10分
|
if (ExamType == TEST_TYPE_AREA) {
|
AddExamFault(10201);
|
} else if (ExamType != TEST_TYPE_ROAD_CALIBRATE) {
|
AddExamFault(40207);
|
}
|
}
|
}
|
|
void AddExamFault(int wrong)
|
{
|
struct ExamFault fault;
|
|
if (!ExamStart)
|
return;
|
|
fault.sn = examFaultIndex++;
|
|
strcpy(fault.utc, StringUtil::FormatUTCTime(AppTimer_GetGmtTickCount()).c_str());
|
|
// if (ExamType != TEST_TYPE_AREA) {
|
// wrong += 1000;
|
// }
|
|
fault.wrong_id = wrong;
|
|
DEBUG("考试发生错误 code = %d %s", wrong, fault.utc);
|
|
ExamFaultList.push_back(fault);
|
|
MA_SendExamWrong(ExamFaultList);
|
|
ExamFaultList.clear();
|
}
|
|
/***************************************************************
|
* 车速判断需要1秒前后的对比,实测停车确认需要1.5秒左右,固减去这个时间
|
* @param src
|
* @return
|
*/
|
int CorrectPauseCriteria(int src)
|
{
|
return src;
|
// return (src > 500) ? src - 500 : 500;
|
}
|
|
/*******************************************************************
|
* @brief 由主天线坐标计算车身点坐标
|
* @param azimuth
|
* @param coord
|
*/
|
static void CalcBodyModeling(modeling_t &car, car_model_t &carModel, rtk_info_t &rtk)
|
{
|
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);
|
|
// 主天线投影修正
|
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));
|
|
// 首次计算
|
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) {
|
projectAngle = 360 - projectAngle;
|
}
|
|
// double tx = projectDistance*sin(toRadians(azimuth));
|
// double ty = projectDistance*cos(toRadians(azimuth));
|
|
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 SystemShutdown(int event, int timeout)
|
{
|
// 关机
|
if (event == 1) {
|
|
}
|
// 重启
|
if (event == 0) {
|
|
}
|
}
|
|
void SensorXChanged(uint16_t id, int value)
|
{
|
// handlePrepare(id, value);
|
// handleLigthExam(id, value);
|
}
|