适应河南测试反馈,倒库,侧方,判定由挡位改变触发,坡起增加上方点。
7个文件已修改
469 ■■■■ 已修改文件
app/src/main/java/safeluck/drive/evaluation/fragment/MapFragment.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/driver_test.cpp 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/native-lib.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items/area_exam.cpp 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items/park_bottom.cpp 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items/park_edge.cpp 134 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items/stop_and_start.cpp 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/safeluck/drive/evaluation/fragment/MapFragment.java
@@ -672,7 +672,7 @@
                    path.lineTo((float) (base_x + (map[k][i][0]) * scale_x), (float) (base_y + (map[k][i][1]) * scale_y));
                }
                path.close();
            } else if (map[k].length == 9) {
            } else if (map[k].length == 9 || map[k].length == 10) {
                path.moveTo((float) (base_x + (map[k][0][0] - min_x) * scale_x), (float) (base_y + (map[k][0][1] - min_y) * scale_y));
                path.lineTo((float) (base_x + (map[k][8][0] - min_x) * scale_x), (float) (base_y + (map[k][8][1] - min_y) * scale_y));
@@ -687,6 +687,11 @@
                path.moveTo((float) (base_x + (map[k][7][0] - min_x) * scale_x), (float) (base_y + (map[k][7][1] - min_y) * scale_y));
                path.lineTo((float) (base_x + (map[k][8][0] - min_x) * scale_x), (float) (base_y + (map[k][8][1] - min_y) * scale_y));
                if (map[k].length == 10) {
                    path.moveTo((float) (base_x + (map[k][8][0] - min_x) * scale_x), (float) (base_y + (map[k][8][1] - min_y) * scale_y));
                    path.lineTo((float) (base_x + (map[k][9][0] - min_x) * scale_x), (float) (base_y + (map[k][9][1] - min_y) * scale_y));
                }
            } else {
                path.moveTo((float) (base_x + (map[k][0][0] - min_x) * scale_x), (float) (base_y + (map[k][0][1] - min_y) * scale_y));
                for (int i = 1; i < map[k].length; i++) {
lib/src/main/cpp/driver_test.cpp
@@ -871,10 +871,12 @@
    if (ExamType == TEST_TYPE_ROAD_DUMMY_LIGHT) {
        if (exam_dummy_light == 0) {
            StartPrepare();
//            StartDummyLightExam(DummyLightContent, DummyLightContentSize, rtkTime);
            exam_dummy_light = 1;
            DEBUG("开始上车准备");
//            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);
lib/src/main/cpp/native-lib.cpp
@@ -28,7 +28,7 @@
const int RTK_PLATFORM_PORT = 12125;
const uint8_t phone[] = {0x20,0x19,0x10,0x15,0x00,0x00,0x00,0x01};
const char *VIRTUAL_RTK_IP = "192.168.16.212";
const char *VIRTUAL_RTK_IP = "192.168.43.76";
const int VIRTUAL_RTK_PORT = 9002;
static pthread_mutex_t tts_mutex = PTHREAD_MUTEX_INITIALIZER;
lib/src/main/cpp/test_items/area_exam.cpp
@@ -226,48 +226,66 @@
                return i;
        }
        if (mapList[i].type == MAP_TYPE_PARK_BUTTOM) {
            // 车头顶点在场地内
            if (IntersectionOf(car->carXY[ car->axial[AXIAL_FRONT] ], &mapList[i].map) == GM_Containment) {
                Line enterLine1, enterLine2;
            Line triggerLine;
                MakeLine(&enterLine1, &(mapList[i].map.point[0]), &(mapList[i].map.point[1]));
                MakeLine(&enterLine2, &(mapList[i].map.point[6]), &(mapList[i].map.point[7]));
            MakeLine(&triggerLine, &(mapList[i].map.point[1]), &(mapList[i].map.point[0]));
                if (DistanceOf(car->carXY[car->axial[AXIAL_FRONT]], enterLine1) > 0.1 &&
                    DistanceOf(car->carXY[car->axial[AXIAL_FRONT]], enterLine2) > 0.1)
                    score[i]++;
            }
            // 车尾顶点在场地内
            if (IntersectionOf(car->carXY[ car->axial[AXIAL_REAR] ], &mapList[i].map) == GM_Containment) {
                Line enterLine1, enterLine2;
            if (CrashTriggerLine(triggerLine, car, CarModelList))
                return i;
                MakeLine(&enterLine1, &(mapList[i].map.point[0]), &(mapList[i].map.point[1]));
                MakeLine(&enterLine2, &(mapList[i].map.point[6]), &(mapList[i].map.point[7]));
            MakeLine(&triggerLine, &(mapList[i].map.point[7]), &(mapList[i].map.point[6]));
                if (DistanceOf(car->carXY[car->axial[AXIAL_REAR]], enterLine1) > 0.1 &&
                    DistanceOf(car->carXY[car->axial[AXIAL_REAR]], enterLine2) > 0.1)
                    score[i]++;
            }
            if (CrashTriggerLine(triggerLine, car, CarModelList))
                return i;
//            // 车头顶点在场地内
//            if (IntersectionOf(car->carXY[ car->axial[AXIAL_FRONT] ], &mapList[i].map) == GM_Containment) {
//                Line enterLine1, enterLine2;
//
//                MakeLine(&enterLine1, &(mapList[i].map.point[0]), &(mapList[i].map.point[1]));
//                MakeLine(&enterLine2, &(mapList[i].map.point[6]), &(mapList[i].map.point[7]));
//
//                if (DistanceOf(car->carXY[car->axial[AXIAL_FRONT]], enterLine1) > 0.1 &&
//                    DistanceOf(car->carXY[car->axial[AXIAL_FRONT]], enterLine2) > 0.1)
//                    score[i]++;
//            }
//            // 车尾顶点在场地内
//            if (IntersectionOf(car->carXY[ car->axial[AXIAL_REAR] ], &mapList[i].map) == GM_Containment) {
//                Line enterLine1, enterLine2;
//
//                MakeLine(&enterLine1, &(mapList[i].map.point[0]), &(mapList[i].map.point[1]));
//                MakeLine(&enterLine2, &(mapList[i].map.point[6]), &(mapList[i].map.point[7]));
//
//                if (DistanceOf(car->carXY[car->axial[AXIAL_REAR]], enterLine1) > 0.1 &&
//                    DistanceOf(car->carXY[car->axial[AXIAL_REAR]], enterLine2) > 0.1)
//                    score[i]++;
//            }
        }
        if (mapList[i].type == MAP_TYPE_PART_EDGE) {
            // 车头顶点在场地内
            if (IntersectionOf(car->carXY[ car->axial[AXIAL_FRONT] ], &mapList[i].map) == GM_Containment) {
                Line enterLine;
            Line triggerLine;
                MakeLine(&enterLine, &(mapList[i].map.point[0]), &(mapList[i].map.point[1]));
            MakeLine(&triggerLine, &(mapList[i].map.point[1]), &(mapList[i].map.point[0]));
                if (DistanceOf(car->carXY[car->axial[AXIAL_FRONT]], enterLine) > 0.1)
                    score[i]++;
            }
            // 车尾顶点在场地内
            if (IntersectionOf(car->carXY[ car->axial[AXIAL_REAR] ], &mapList[i].map) == GM_Containment) {
                Line enterLine;
                MakeLine(&enterLine, &(mapList[i].map.point[0]), &(mapList[i].map.point[1]));
                if (DistanceOf(car->carXY[car->axial[AXIAL_REAR]], enterLine) > 0.1)
                    score[i]++;
            }
            if (CrashTriggerLine(triggerLine, car, CarModelList))
                return i;
//            // 车头顶点在场地内
//            if (IntersectionOf(car->carXY[ car->axial[AXIAL_FRONT] ], &mapList[i].map) == GM_Containment) {
//                Line enterLine;
//
//                MakeLine(&enterLine, &(mapList[i].map.point[0]), &(mapList[i].map.point[1]));
//
//                if (DistanceOf(car->carXY[car->axial[AXIAL_FRONT]], enterLine) > 0.1)
//                    score[i]++;
//            }
//            // 车尾顶点在场地内
//            if (IntersectionOf(car->carXY[ car->axial[AXIAL_REAR] ], &mapList[i].map) == GM_Containment) {
//                Line enterLine;
//
//                MakeLine(&enterLine, &(mapList[i].map.point[0]), &(mapList[i].map.point[1]));
//
//                if (DistanceOf(car->carXY[car->axial[AXIAL_REAR]], enterLine) > 0.1)
//                    score[i]++;
//            }
        }
        if (mapList[i].type == MAP_TYPE_TURN_90) {
            // 车前轮或后轮轨迹越过触发线
@@ -328,7 +346,7 @@
    }
    if (mapList[index].type == MAP_TYPE_STOP_START) {
        // 构造虚拟的左上角点
        double x9, y9, xo, yo;
        double x10, y10, x9, y9, xo, yo;
        bool enter = false;
@@ -338,17 +356,33 @@
        x9 = 2*xo - mapList[index].map.point[8].X;
        y9 = 2*yo - mapList[index].map.point[8].Y;
        if (mapList[index].map.num > 9) {
            // 构造虚拟的右上角点
            xo = (mapList[index].map.point[9].X + mapList[index].map.point[7].X) / 2;
            yo = (mapList[index].map.point[9].Y + mapList[index].map.point[7].Y) / 2;
            x10 = 2*xo - mapList[index].map.point[8].X;
            y10 = 2*yo - mapList[index].map.point[8].Y;
        }
        Polygon map;
        map.num = 4;
        map.point = (PointF *) malloc(map.num * sizeof(PointF));
        map.point[0] = mapList[index].map.point[0];
        map.point[1] = mapList[index].map.point[8];
        map.point[2] = mapList[index].map.point[7];
        map.point[3].X = x9;
        map.point[3].Y = y9;
        if (mapList[index].map.num <= 9) {
            map.point[0] = mapList[index].map.point[0];
            map.point[1] = mapList[index].map.point[8];
            map.point[2] = mapList[index].map.point[7];
            map.point[3].X = x9;
            map.point[3].Y = y9;
        } else {
            map.point[0] = mapList[index].map.point[0];
            map.point[1] = mapList[index].map.point[9];
            map.point[2].X = x10;
            map.point[2].Y = y10;
            map.point[3].X = x9;
            map.point[3].Y = y9;
        }
        // 全车都需不在地图中
        Polygon carBody;
@@ -422,9 +456,12 @@
        MakeLine(&trace_line, &trace.point[pp], &trace.point[p]);
        MakeLine(&trace2_line, &trace2.point[pp], &trace2.point[p]);
        if ((IntersectionOf(trace_line, triggerLine) == GM_Intersection || IntersectionOf(trace2_line, triggerLine) == GM_Intersection) &&
        if ((IntersectionOf(trace_line, triggerLine) == GM_Intersection &&
            IntersectionOfLine(p1, p2, car->carXY[car->left_front_tire[TIRE_OUTSIDE]]) == -1 &&
            DistanceOf(car->carXY[car->left_front_tire[TIRE_OUTSIDE]], triggerLine) > 0.1) {
            DistanceOf(car->carXY[car->left_front_tire[TIRE_OUTSIDE]], triggerLine) > 0.1) ||
                (IntersectionOf(trace2_line, triggerLine) == GM_Intersection &&
                        IntersectionOfLine(p1, p2, car->carXY[car->left_rear_tire[TIRE_OUTSIDE]]) == -1 &&
                        DistanceOf(car->carXY[car->left_rear_tire[TIRE_OUTSIDE]], triggerLine) > 0.1) ) {
            // 碰到触发线
            DEBUG("碰撞触发线 引发地图");
            trigger = true;
lib/src/main/cpp/test_items/park_bottom.cpp
@@ -11,6 +11,7 @@
#include "../utils/xconvert.h"
#include "../master/comm_if.h"
#include "area_exam.h"
#include "../test_common/car_sensor.h"
#include <vector>
#include <cstdlib>
@@ -27,7 +28,14 @@
    THIRD_TOUCH_CTRL_LINE
};
static bool testing = false, reverseCar = false;
enum {
    TESTING,
    TEST_FAIL,          // 因触发某些规则,在车身未完全立场情况下,提前终止部分测试
    TEST_FINISH
};
static int testStatus;
static bool reverseCar = false;
static int mapIndex = 0;
const uint32_t CHECK_PARK_DELAY = 400;
@@ -44,15 +52,21 @@
static int darray[3];
static int parkStatus[3];
static int gearAtStop;
static int currGear;
static char prevCrossedCtrlLine;
static char CrossCtrlLine(const Polygon *map, const car_model *car, const car_model *prev_car);
static bool EnterParking(const Polygon *map, const car_model *car);
static bool CrashRedLine(const Polygon *map, const car_model *car, int &who);
static bool ExitParkArea(const Polygon *map, const car_model *car);
static bool AllTireExitParkArea(const Polygon *map, const car_model *car);
void StartParkBottom(int index, int moveDirect, const struct RtkTime *rtkTime)
{
    DEBUG("StartParkBottom");
    testing = true;
    testStatus = TESTING;
    reverseCar = false;
    mapIndex = index;
    memset(carray, 0, sizeof(carray));
@@ -67,6 +81,11 @@
    crossCtrlLineSw = false;
    reportParkFail = false;
    occurCrashRedLine = false;
    currGear = ReadCarStatus(GEAR);
    prevCrossedCtrlLine = 0;
    PlayTTS("您已进入倒车入库区域", NULL);
}
int TestParkBottom(const Polygon *map, const car_model *car, const car_model *carPrev, double speed, int moveDirect, const struct RtkTime *rtkTime)
@@ -78,16 +97,83 @@
    vector<Line> line_set;
    Line distance_line;
    bool gear_change = false;
    int gear = ReadCarStatus(GEAR);
    if (gear == GEAR_R) {
        if (currGear != GEAR_R) {
            gear_change = true;
            currGear = GEAR_R;
        }
    } else if (currGear == GEAR_R) {
        gear_change = true;
        currGear = gear;
    }
    if (testStatus == TESTING && gear_change) {
        if (currGear == GEAR_R) {
            // 挂倒挡,检测是否过控制线
            DEBUG("开始挂倒挡");
            if (!reverseCar) {
                DEBUG("开始首轮入库");
                reverseCar = true;
                MA_EnterMap(mapIndex, MAP_TYPE_PARK_BUTTOM, 1);
                firstReverseTimepoint = tp;             // 开始210秒计时
            }
            crossCtrlLine = CrossCtrlLine(map, car, carPrev);
            if (parkCount >= 2) {
                DEBUG("开始次轮入库");
                parkCount = 0;
                MA_EnterMap(mapIndex, MAP_TYPE_PARK_BUTTOM, 1);
                firstReverseTimepoint = tp;             // 开始210秒计时
            }
            if (crossCtrlLine == 0) {
                // 倒车前,前轮未驶过控制线
                AddExamFault(20104, rtkTime);
                DEBUG("倒车前,前轮未驶过控制线");
            } else if (crossCtrlLine == prevCrossedCtrlLine) {
                // 重复跨越同一控制线,不按规定线路,顺序形式,不合格
                AddExamFault(20101, rtkTime);
                DEBUG("不按规定线路,顺序形式, 同 %c 侧", prevCrossedCtrlLine);
            } else {
                prevCrossedCtrlLine = crossCtrlLine;
                DEBUG("开始 %c 侧 倒库", prevCrossedCtrlLine);
            }
        } else {
            // 从倒挡移出,检测是否入库
            DEBUG("从倒挡移出");
            parkCount++;
            DEBUG("库位检查次数 = %d", parkCount);
            if (EnterParking(map, car)) {
                DEBUG("倒库成功");
            } else {
                AddExamFault(20103, rtkTime);
                DEBUG("倒库不入");
            }
        }
    }
    if (testStatus == TESTING && parkCount < 2 && AllTireExitParkArea(map, car)) {
        testStatus = TEST_FAIL;
        AddExamFault(10103, rtkTime);
        DEBUG("直接驶离测试区,不按考试员指令驾驶");
    }
    if (ExitParkArea(map, car)) {
        DEBUG("离开场地");
        // 离开场地
        testing = false;
        if ((parkStatus[0] != 1 || parkStatus[1] != 1) && !reportParkFail && reverseCar) {
        testStatus = TEST_FINISH;
        /*if ((parkStatus[0] != 1 || parkStatus[1] != 1) && !reportParkFail && reverseCar) {
            // 倒库不入,不合格
            reportParkFail = true;
            AddExamFault(20103, rtkTime);
            DEBUG("倒库不入");
        }
        }*/
        goto TEST_END;
    }
@@ -108,22 +194,45 @@
    MA_SendDistance(dtox[0], dtox[1]);
    if (CrashRedLine(map, car, who)) {
        if (!occurCrashRedLine && reverseCar) {
        if (!occurCrashRedLine /*&& reverseCar*/) {
            occurCrashRedLine = true;
            // 车身出线,不合格
            AddExamFault(10116, rtkTime);
            DEBUG("车轮压线");
            if (who == 1) {
            /*if (who == 1) {
                PlayTTS("压左库位线", NULL);
            } else if (who == 2) {
                PlayTTS("压右库位线", NULL);
            }
            }*/
        }
    } else {
        occurCrashRedLine = false;
    }
    crossCtrlLine = CrossCtrlLine(map, car, carPrev);
    if (moveDirect != prevMoveDirect) {
        if (moveDirect == 0) {
            stopTimepoint = tp;
            gearAtStop = (currGear == GEAR_R ? 1 : 0);
            DEBUG("停车了 %d %d %d %d %d %d %d", rtkTime->YY, rtkTime->MM, rtkTime->DD, rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss);
            DEBUG("停车时挡位 = %d", gearAtStop);
        } else if (prevMoveDirect == 0) {
            DEBUG("继续行驶 %d %d %d %d %d %d %d", rtkTime->YY, rtkTime->MM, rtkTime->DD, rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss);
            DEBUG("停车时间 %ld", tp - stopTimepoint);
            DEBUG("再次移动时挡位 = %d", currGear == GEAR_R ? 1 : 0);
            if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.park_bottom_pause_criteria)
                && gearAtStop == (currGear == GEAR_R ? 1 : 0)) {
                // 停车超2秒,每次扣5分
                AddExamFault(20106, rtkTime);
                DEBUG("中途停车");
            }
        }
        prevMoveDirect = moveDirect;
    }
/*    crossCtrlLine = CrossCtrlLine(map, car, carPrev);
    if (crossCtrlLine > 0 && !crossCtrlLineSw) {
        crossCtrlLineSw = true;
        if (parkCount == 0) {
@@ -143,14 +252,14 @@
            } else {
                // 离开测试区,停止计时
                DEBUG("离开测试区,停止计时");
                testing = false;
                testStatus = false;
                goto TEST_END;
            }
            carray[2] = crossCtrlLine;
        }
    }
    if (testing && darray[0] > 0 && tp - firstReverseTimepoint >= examParam.park_bottom_limit_time) {
    if (testStatus && darray[0] > 0 && tp - firstReverseTimepoint >= examParam.park_bottom_limit_time) {
        // 完成超时,不合格
        if (!reportExamTimeout) {
            reportExamTimeout = true;
@@ -235,13 +344,15 @@
            }
            checkPartStatus = false;
        }
    }
    }*/
TEST_END:
    if (!testing && reverseCar) {
    if (testStatus == TEST_FINISH) {
        DEBUG("倒库结束");
        MA_EnterMap(mapIndex, MAP_TYPE_PARK_BUTTOM, 0);
        return 0;
    }
    return testing ? 1 : 0;
    return 1;
}
// 检测2前轮是否正向越过左右控制线
@@ -344,3 +455,30 @@
    return ret;
}
// 双前轮和任一后轮不在区域
static bool AllTireExitParkArea(const Polygon *map, const car_model *car)
{
    int tireExitNum = 0;
    if (IntersectionOf(car->carXY[ car->left_front_tire[TIRE_OUTSIDE] ], map) == GM_None) {
        tireExitNum++;
    }
    if (IntersectionOf(car->carXY[ car->right_front_tire[TIRE_OUTSIDE] ], map) == GM_None) {
        tireExitNum++;
    }
    if (IntersectionOf(car->carXY[ car->left_rear_tire[TIRE_OUTSIDE] ], map) == GM_None) {
        tireExitNum++;
    }
    if (IntersectionOf(car->carXY[ car->right_rear_tire[TIRE_OUTSIDE] ], map) == GM_None) {
        tireExitNum++;
    }
    if (tireExitNum >= 3) {
        return true;
    }
    return false;
}
lib/src/main/cpp/test_items/park_edge.cpp
@@ -20,6 +20,12 @@
using namespace std;
enum {
    TESTING,
    TEST_FAIL,          // 因触发某些规则,在车身未完全立场情况下,提前终止部分测试
    TEST_FINISH
};
const uint32_t CHECK_PARK_DELAY = 400;
static int mapIndex = 0;
@@ -30,9 +36,10 @@
static bool occurCrashRedLine1, occurCrashRedLine2;
static int prevMoveStatus, storeMoveStatusBeforeStop;
static int parkStatus;
static bool occurMoveBack, parkSuccess;
static int gearAtStop;
static bool occurMoveBack, checkPark, parkSuccess, checkLight;
static uint32_t moveBackTimePoint;
static bool testing = false;
static int testStatus;
static bool CrashRedLine1(const Polygon *map, const car_model *car);
static bool CrashRedLine2(const Polygon *map, const car_model *car);
@@ -44,7 +51,7 @@
{
    DEBUG("进入侧方停车场地");
    testing = true;
    testStatus = TESTING;
    mapIndex = index;
    occurCrashRedLine1 = occurCrashRedLine2 = false;        // 这个科目规定特殊点,发生一次扣10分,而不直接淘汰
@@ -54,12 +61,16 @@
    parkSuccess = false;
    parkStatus = 0;
    occurMoveBack = false;
    checkPark = false;
    checkLight = false;
    gearAtStop = -1;
    PlayTTS("您已进入侧方停车区域", NULL);
    // 仅当发生倒车,才意味着项目开始
    if (moveStatus == -1) {
    /*if (moveStatus == -1) {
        occurMoveBack = true;
        moveBackTimePoint = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
    }
    }*/
}
int TestParkEdge(const Polygon *map, const car_model *car, const car_model *carPrev, double speed, int moveStatus, const struct RtkTime *rtkTime)
@@ -67,9 +78,39 @@
    vector<double> dtox;
    vector<Line> line_set;
    Line distance_line;
    bool is_gear_r = false;
    // 首次挂倒挡, 才意味着项目开始
    if (testStatus == TESTING) {
        if (ReadCarStatus(GEAR) == GEAR_R) {
            is_gear_r = true;
            if (!occurMoveBack) {
                occurMoveBack = true;
                moveBackTimePoint = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss,
                                                      rtkTime->mss * 10);      // 开始计时
                MA_EnterMap(mapIndex, MAP_TYPE_PART_EDGE, 1);
            }
        } else {
            is_gear_r = false;
            if (occurMoveBack && !checkPark) {
                // 检查车身入库情况
                DEBUG("检查车身入库情况");
                checkPark = true;
                if (EnterParking(map, car)) {
                    parkStatus = 1;
                    parkSuccess = true;
                } else {
                    // 停止后,车身出线,不合格
                    AddExamFault(20401, rtkTime);
                    parkSuccess = false;
                    DEBUG("移库不入");
                }
            }
        }
    }
    if (CrashRedLine1(map, car)) {
        if (!occurCrashRedLine1 && occurMoveBack) {
        if (!occurCrashRedLine1 /*&& occurMoveBack*/) {
            // 车轮压边线,每次扣10分
            AddExamFault(20403, rtkTime);
            DEBUG("车轮压边线");
@@ -80,7 +121,7 @@
    }
    if (CrashRedLine2(map, car)) {
        if (!occurCrashRedLine2 && occurMoveBack) {
        if (!occurCrashRedLine2 /*&& occurMoveBack*/) {
            // 车身压库位线,每次扣10分
            AddExamFault(20404, rtkTime);
            DEBUG("车身压库位线");
@@ -90,14 +131,20 @@
        occurCrashRedLine2 = false;
    }
    if (ExitParkArea(map, car) || ExitParkArea2(map, car)) {
        if (!parkSuccess && occurMoveBack && !reportParkFail) {
    if (ExitParkArea2(map, car)) {
        /*if (!parkSuccess && occurMoveBack && !reportParkFail) {
            // 直接驶离测试区,认为移库不入
            AddExamFault(10103, rtkTime);
            reportParkFail = true;
            DEBUG("直接驶离测试区,不按考试员指令驾驶");
        }*/
        if (occurMoveBack && !checkPark) {
            // 倒车直接驶离测试区
            AddExamFault(10103, rtkTime);
            DEBUG("直接驶离测试区,不按考试员指令驾驶");
        }
        testing = false;
        testStatus = TEST_FINISH;
        goto TEST_END;
    }
@@ -117,6 +164,13 @@
    DistanceOfTire2X(dtox, car, line_set);
    MA_SendDistance(dtox[0], dtox[1]);
    if (testStatus == TESTING && !occurMoveBack && ExitParkArea(map, car)) {
        // 入库后一直前进,车头移出驶离线
        AddExamFault(10103, rtkTime);
        DEBUG("直接驶离测试区,不按考试员指令驾驶");
        testStatus = TEST_FAIL;
    }
    if (occurMoveBack) {
        uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
@@ -133,15 +187,33 @@
            parkStatus = 0;
            stopTimepoint = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
            storeMoveStatusBeforeStop = prevMoveStatus;
            gearAtStop = is_gear_r ? 1 : 0;
            DEBUG("停车了 %d %d %d %d %d %d %d", rtkTime->YY, rtkTime->MM, rtkTime->DD, rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss);
        } else {
        } else if (prevMoveStatus == 0) {
            DEBUG("继续行驶 %d %d %d %d %d %d %d", rtkTime->YY, rtkTime->MM, rtkTime->DD, rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss);
            uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
            DEBUG("停车时间 %ld", tp - stopTimepoint);
            if (moveStatus == storeMoveStatusBeforeStop) {
            if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.park_edge_pause_criteria)
            && occurMoveBack
            && gearAtStop == (is_gear_r ? 1 : 0)) {
                // 停车超2秒,每次扣5分
                AddExamFault(20406, rtkTime);
                DEBUG("停车超时");
            }
            if (moveStatus == 1 && checkPark && !checkLight) {
                // 在这里检查转向灯状态
                checkLight = true;
                if (ReadCarStatus(TURN_SIGNAL_LAMP) != LEFT_TURN_LIGHT) {
                    // 不开转向灯,扣10分
                    AddExamFault(20405, rtkTime);
                    DEBUG("未开启转向灯");
                }
            }
            /*if (moveStatus == storeMoveStatusBeforeStop) {
                // 同方向再启动,继续判断是否停车超时
                if (tp - stopTimepoint >= CorrectPauseCriteria(examParam.park_edge_pause_criteria) && occurMoveBack) {
                    // 停车超2秒,每次扣5分
@@ -172,18 +244,18 @@
                        DEBUG("未开启转向灯");
                    }
                }
            }
            }*/
            if (moveStatus == -1 && !occurMoveBack) {
           /* if (moveStatus == -1 && !occurMoveBack) {
                DEBUG("开始倒车");
                occurMoveBack = true;
                moveBackTimePoint = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
                MA_EnterMap(mapIndex, MAP_TYPE_PART_EDGE, 1);
            }
            }*/
        }
        prevMoveStatus = moveStatus;
    } else if (moveStatus == 0 && parkStatus == 0) {
    } /*else if (moveStatus == 0 && parkStatus == 0) {
        uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
        if (tp - stopTimepoint >= CHECK_PARK_DELAY) {
@@ -194,13 +266,15 @@
                parkStatus = -1;
            }
        }
    }
    }*/
TEST_END:
    if (!testing && occurMoveBack) {
    if (testStatus == TEST_FINISH) {
        DEBUG("侧方停车结束");
        MA_EnterMap(mapIndex, MAP_TYPE_PART_EDGE, 0);
        return 0;
    }
    return testing ? 1 : 0;
    return 1;
}
// 车轮是否压道路边线
@@ -234,7 +308,7 @@
    bool ret = false;
    Line red_line;
    const int red_lines[][2] = {{2, 3}, {3, 4}, {4, 5}};
    const int red_lines[][2] = {{0, 7}, {2, 3}, {3, 4}, {4, 5}};
    Polygon car_body;
@@ -249,6 +323,14 @@
        if (IntersectionOf(red_line, &car_body) != GM_None) {
            ret = true;
            break;
        }
    }
    if (!occurMoveBack) {
        // 倒车前,车身不得压库位虚线
        MakeLine(&red_line, &map->point[2], &map->point[5]);
        if (IntersectionOf(red_line, &car_body) != GM_None) {
            ret = true;
        }
    }
@@ -282,14 +364,12 @@
    return succ;
}
// 整个车辆都要驶过前库位线
// 车头要驶过前库位线
static bool ExitParkArea(const Polygon *map, const car_model *car)
{
    for (int i = 0; i < car->bodyNum; ++i) {
        if (IntersectionOfLine(map->point[6], map->point[7], car->carXY[car->body[i]]) != -1)
            return false;
    }
    return true;
    if (IntersectionOfLine(map->point[6], map->point[7], car->carXY[ car->axial[AXIAL_FRONT] ]) == -1)
            return true;
    return false;
}
static bool ExitParkArea2(const Polygon *map, const car_model *car)
lib/src/main/cpp/test_items/stop_and_start.cpp
@@ -216,14 +216,27 @@
    bool ret = false;
    Line red_line;
    const int red_lines[][2] = {{0, 8}};
    int red_lines[2][2];
    int red_line_num = 0;
    if (map->num == 10) {
        red_lines[0][0] = 0;
        red_lines[0][1] = 8;
        red_lines[1][0] = 8;
        red_lines[1][1] = 9;
        red_line_num = 2;
    } else {
        red_lines[0][0] = 0;
        red_lines[0][1] = 8;
        red_line_num = 1;
    }
    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 < sizeof(red_lines) / sizeof(red_lines[0]); ++i) {
    for (int i = 0; i < red_line_num; ++i) {
        MakeLine(&red_line, &map->point[red_lines[i][0]], &map->point[red_lines[i][1]]);
        if (IntersectionOf(red_line, frontAxle) == GM_Intersection ||
                IntersectionOf(red_line, rearAxle) == GM_Intersection) {
@@ -285,11 +298,19 @@
    Polygon carBody, map2;
    PointF vPoint = Calc3Point(map->point[8], map->point[0], DistanceOf(map->point[8], map->point[7]), 'R');
    PointF vPoint2;
    if (map->num == 10) {
        vPoint2 = Calc3Point(map->point[8], map->point[9], DistanceOf(map->point[8], map->point[7]), 'L');
    }
    map2.num = 4;
    map2.point = (PointF *)malloc(map2.num * sizeof(PointF));
    MakePolygon(&map2, {vPoint, map->point[0], map->point[7], map->point[8]});
    if (map->num == 9)
        MakePolygon(&map2, {vPoint, map->point[0], map->point[8], map->point[7]});
    else
        MakePolygon(&map2, {vPoint, map->point[0], map->point[9], vPoint2});
    carBody.num = car->bodyNum;
    carBody.point = (PointF *)malloc(carBody.num * sizeof(PointF));