yy1717
2020-08-14 576d819c4d9aabd1a8d102ae9c3bc13c9165ee1f
坐标
9个文件已修改
951 ■■■■ 已修改文件
lib/src/main/cpp/driver_test.cpp 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/driver_test.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items2/road_exam.cpp 596 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items2/road_exam.h 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items2/through_something.cpp 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/test_items2/through_something.h 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/java/com/anyun/exam/lib/RemoteService.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/java/com/anyun/exam/lib/SvrManager.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/java/com/anyun/exam/lib/crash/CrashHandler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lib/src/main/cpp/driver_test.cpp
@@ -312,12 +312,21 @@
 */
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(rtkTime1->YY, rtkTime1->MM, rtkTime1->DD, rtkTime1->hh, rtkTime1->mm, rtkTime1->ss) -
                TimeMakeComposite(rtkTime2->YY, rtkTime2->MM, rtkTime2->DD, rtkTime2->hh, rtkTime2->mm, rtkTime2->ss)) * 1000
        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;
    }
}
lib/src/main/cpp/driver_test.h
@@ -37,7 +37,7 @@
};
struct RtkTime {
    int YY;
    int YY;             // 2位数
    int MM;
    int DD;
    int hh;
lib/src/main/cpp/test_items2/road_exam.cpp
@@ -83,13 +83,8 @@
const int OVERTAKE_HOLD_TIME = D_SEC(3);                // 在超车道行驶的一段时间
const double EXAM_RANGE = 3000.0;                       // 至少驾驶距离
static const double LASTEST_BREAK_POINT = 30.0;
static const double NEXT_ROAD_TIP = 100.0;                  // 到达路口前提示下一个怎么走
static const double DISTANCE_STOP_CAR_TO_STOP_LINE = 5.0;
static const double PASS_SCHOOL_MAX_SPEED = 30.0;           // kmh
static const int FIND_POSITION = -2;
static const int INVALID_POSITION = -1;
static bool occurCrashRedLine;
static bool occurCrashGreenLine;
@@ -125,7 +120,6 @@
static int startCar, stopCar;
static int currExamMapIndex;
static trigger_line_t *currRoadItem;
static int nextRoadId;
static PointF roadItemStartPoint;
static struct drive_timer roadItemStartTime;
static bool overtake = false;
@@ -168,12 +162,9 @@
static trigger_line_t * EntryItem(int index, road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList);
static void ClearAll(road_exam_map &map);
static bool AllCmp(road_exam_map &map);
static void CheckBreakActive(road_exam_map &map, const car_model *car, LIST_CAR_MODEL &CarModelList,
                             double speed, int moveDirect, const struct RtkTime *rtkTime);
static PointF CalcProjectionWithRoadEdge(vector<edge_t> &edge, PointF point);
static bool AllCmp(road_exam_map &map);
static int CalcRoadIndex(int currRoadIndex, road_exam_map &RoadMap, const car_model *car);
void InitRoadExam(road_exam_map &RoadMap)
@@ -215,15 +206,14 @@
    checkStartCarSignal = startCarLeftTurnSignal = false;
    Lane.road = Lane.sep = Lane.no = -1;
    Lane.guide = 0;
    nextRoadId = -1;
    checkTurn = false;
    ClearAll(RoadMap);
    CrashLineType = -1;
    ResetOdo();
    ResetTarget(RoadMap);
    // 初始化考项
}
@@ -242,7 +232,7 @@
 * @param point
 * @return
 */
static PointF CalcProjectionWithRoadEdge(vector<edge_t> &edge, PointF point)
PointF CalcProjectionWithRoadEdge(vector<edge_t> &edge, PointF point)
{
    PointF p1, p2;
    PointF proj;
@@ -346,7 +336,7 @@
    return theProj;
}
static double CalcDistanceReference(PointF point, PointF refPoint, vector<edge_t> &edge)
double CalcDistanceReference(PointF point, PointF refPoint, vector<edge_t> &edge)
{
    double distance = 0;
@@ -657,7 +647,7 @@
    for (int i = 0; i < RoadMap.roads[roadIndex].separate[sepIndex].lane_direct.size(); ++i) {
        double d1 = CalcDistanceReference(point, RoadMap.roads[roadIndex].separate[sepIndex].lane_direct[i].start, RoadMap.roads[roadIndex].rightEdge);
        double d2 = CalcDistanceReference(point, RoadMap.roads[roadIndex].separate[sepIndex].lane_direct[i].end, RoadMap.roads[roadIndex].rightEdge);
        if (fabs(d1) < 1e-6 && d1 < 0.0 && d2 > 1e-6 && laneNo < RoadMap.roads[roadIndex].separate[sepIndex].lane_direct[i].direct.size()) {
        if (d1 < -1e-3 && d2 > 1e-3 && laneNo < RoadMap.roads[roadIndex].separate[sepIndex].lane_direct[i].direct.size()) {
            return RoadMap.roads[roadIndex].separate[sepIndex].lane_direct[i].direct[laneNo];
        }
    }
@@ -1063,144 +1053,51 @@
    }
}
static map <int, int> TargetReduceRec;
enum {
    NOT_REDUCE_SPEED,
    REDUCE_SPEED,
    STOP_CAR,
    OVER_SPEED
};
static void ChangeTargetReduceRec(int roadIndex, int index, int status)
static int NearbyCrossingGuide(int roadIndex, road_t &road, const car_model *car, LIST_CAR_MODEL &CarModelList)
{
    int key = roadIndex * 100 + index;
    int guide = 0;
    double distance;
    auto it = CrossingHint.find(key);
    if (it != CrossingHint.end()) {
        CrossingHint.erase(it);
    }
    CrossingHint.insert(pair<int, int>(key, status));
}
static int GetTargetReduceRec(int roadIndex, int index)
{
    int key = roadIndex * 100 + index;
    auto it = CrossingHint.find(key);
    if (it != CrossingHint.end()) {
        return it->second;
    }
    return -1;
}
void ApproachTarget(road_exam_map &RoadMap, const car_model *car, int roadIndex, double speed, int moveDirect)
{
    car_sensor_value_t brk = ReadCarSensorValue(BREAK);
    if (roadIndex < 0 || roadIndex >= RoadMap.roads.size())
        return;
    for (int n = 0; n < RoadMap.roads[roadIndex].stopLine.size(); ++n) {
        PointF point;
    struct nearby_crossing {
        int guide;
        double distance;
    };
    vector<struct nearby_crossing> set;
    for (int i = 0; i < road.stopLine.size(); ++i) {
        PointF point;
        point.X = road.stopLine[i].line.X1;
        point.Y = road.stopLine[i].line.Y1;
        distance = CalcDistanceReference(car->carXY[car->axial[AXIAL_FRONT]], point, RoadMap.roads[roadIndex].rightEdge);
        distance = CalcDistanceReference(car->carXY[car->axial[AXIAL_FRONT]], point,
                                         road.rightEdge);
        if (distance > 1e-3 && distance < LASTEST_BREAK_POINT) {
            // 记录刹车,停车
            if (brk.value == BREAK_ACTIVE) {
        if (distance > 1e-3) {
            struct nearby_crossing temp;
            }
        } else if (distance > LASTEST_BREAK_POINT + 5) {
            temp.guide = road.stopLine[i].active;
            temp.distance = distance;
            set.push_back(temp);
        }
    }
    for (int i = 0; i < RoadMap.specialAreas.size(); i++) {
        if (RoadMap.specialAreas[i].type == GRID_AREA || RoadMap.specialAreas[i].road != RoadMap.roads[roadIndex].id)
            continue;
    if (set.size() > 0) {
        distance = set[0].distance;
        guide = set[0].guide;
        if (map.specialAreas[i].area.size() == 2 && map.specialAreas[i].leftPoints.size() != 2) {
            // 计算点到左侧路边线的垂点
            int road = 0;
            for (road = 0; road < map.roads.size(); ++road) {
                if (map.roads[road].id == map.specialAreas[i].road)
                    break;
        for (int i = 1; i < set.size(); ++i) {
            if (distance > set[i].distance) {
                distance = set[i].distance;
                guide = set[i].guide;
            }
            PointF vPoint = CalcProjectionWithRoadEdge(map.roads[road].leftEdge, map.specialAreas[i].area[0]);
//            DEBUG("计算垂点1 (%f, %f)", vPoint.X, vPoint.Y);
            map.specialAreas[i].leftPoints.push_back(vPoint);
            vPoint = CalcProjectionWithRoadEdge(map.roads[road].leftEdge, map.specialAreas[i].area[1]);
//            DEBUG("计算垂点2 (%f, %f)", vPoint.X, vPoint.Y);
            map.specialAreas[i].leftPoints.push_back(vPoint);
        }
        if (map.specialAreas[i].type == ZEBRA_CROSSING || map.specialAreas[i].type == BUS_STATION_AREA) {
//            DEBUG("斑马线");
            Line startLine;
            MakeLine(&startLine, &map.specialAreas[i].area[0], &map.specialAreas[i].leftPoints[0]);
            // 车头和斑马线距离不足30米
            if (IntersectionOf(extLine, startLine) == GM_Intersection &&
                IntersectionOfLine(car->carXY[ car->axial[AXIAL_FRONT] ], startLine) == 1 ) {
                DEBUG("进入减速区 %d", map.specialAreas[i].type);
                if (BreakDone == BREAK_ACTIVE) {
                    map.specialAreas[i].activeBreak = true;
                }
            }
            // 跨线后,检查刹车动作
            if (CrashTheLine(startLine, car, CarModelList)) {
                if (!map.specialAreas[i].activeBreak) {
                    // 不按规定减速,不合格
                    DEBUG("不按规定减速");
                    if (map.specialAreas[i].type == ZEBRA_CROSSING) {
                        AddExamFault(48, rtkTime);
                    } else {
                        AddExamFault(50, rtkTime);
                    }
                } else {
                    DEBUG("按规定减速");
                }
            }
        } else if (map.specialAreas[i].type == SCHOOL_AREA) {
            Polygon school;
//            DEBUG("学校");
            school.num = 4;
            school.point = (PointF *) malloc(school.num * sizeof(PointF));
            school.point[0] = map.specialAreas[i].area[0];
            school.point[1] = map.specialAreas[i].area[1];
            school.point[2] = map.specialAreas[i].leftPoints[1];
            school.point[3] = map.specialAreas[i].leftPoints[0];
            if (IntersectionOf(car->carXY[ car->axial[AXIAL_FRONT] ], &school) == GM_Containment) {
                if (ConvertMs2KMh(speed) > PASS_SCHOOL_MAX_SPEED) {
                    if (!map.specialAreas[i].overSpeed) {
                        DEBUG("通过学校区域超速");
                        AddExamFault(49, rtkTime);
                        map.specialAreas[i].overSpeed = true;
                    }
                }
            }
            free(school.point);
        }
    }
    return guide;
}
void TestRoadGeneral(road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime)
{
@@ -1384,20 +1281,19 @@
        }
    } else {
        // 前进
    }
    // 检测通过路口、人行道等区域时,释放刹车或减速
    CheckBreakActive(RoadMap, car, CarModelList,
                                 speed, moveDirect, rtkTime);
    // 检测离开此路段,全车需不在范围内
    int oldid = currExamMapIndex;
    currExamMapIndex = CalcRoadIndex(currExamMapIndex, RoadMap, car);
    if (currExamMapIndex >= 0) {
        car_sensor_value_t brk = ReadCarSensorValue(BREAK);
        HintCrossing(currExamMapIndex, RoadMap.roads[currExamMapIndex], car, CarModelList);
        // 检测通过路口、人行道等区域时,释放刹车或减速
        ApproachTarget(RoadMap, car, currExamMapIndex, (brk.value == BREAK_ACTIVE), speed, moveDirect, rtkTime);
    }
    ExitTarget(RoadMap, car, CarModelList, rtkTime);
    if (oldid != currExamMapIndex) {
        DEBUG("道路ID切换 %d", currExamMapIndex);
@@ -1411,7 +1307,19 @@
        DEBUG("压线类型切换 %d", CrashLineType);
    }
    oldid = Lane.guide;
    DetectLane(RoadMap, car, currExamMapIndex, rtkTime);
    if (Lane.guide > 0 && currExamMapIndex >= 0) {
        if (!(NearbyCrossingGuide(currExamMapIndex, RoadMap.roads[currExamMapIndex], car, CarModelList) & Lane.guide)) {
            DEBUG("不按规定车道标向行驶");
            AddExamFault(9, rtkTime);
        }
    }
    if (Lane.guide != oldid) {
        DEBUG("导向类型切换 %d", Lane.guide);
    }
    // 检测压线状态
    TestRoadStartCar(car, speed, moveDirect, rtkTime);
@@ -1702,405 +1610,3 @@
    }
    return true;
}
/************************************************************************
 * 开始新的考试后,清除地图所有的刹车、停车记录
 * @param map
 */
static void ClearAll(road_exam_map &map)
{
//    for (int i = 0; i < map.roads.size(); ++i) {
//        map.roads[i].activeStop = map.roads[i].activeBreak = false;
//        map.roads[i].arrivedTail = false;
//        map.roads[i].errorLane = false;
//    }
//    for (int i = 0; i < map.specialAreas.size(); i++) {
//        map.specialAreas[i].overSpeed = map.specialAreas[i].activeBreak = false;
//    }
//    for (int i = 0; i < map.triggerLines.size(); ++i) {
//        map.triggerLines[i].cmp = false;
//    }
}
static void CheckBreakActive(road_exam_map &map, const car_model *car, LIST_CAR_MODEL &CarModelList,
                             double speed, int moveDirect, const struct RtkTime *rtkTime)
{
    int BreakDone = ReadCarStatus(BREAK);
    // 计算车前进轨迹延长线
    double yaw = YawOf(car->carXY[ car->axial[AXIAL_FRONT] ], car->carXY[ car->axial[AXIAL_REAR] ]);
    PointF extPoint = PointExtend(car->carXY[ car->axial[AXIAL_FRONT] ], LASTEST_BREAK_POINT, yaw);
    Line extLine;
    MakeLine(&extLine, &car->carXY[ car->axial[AXIAL_FRONT] ], &extPoint);
    // 路口刹车点
/*    for (int i = 0; i < map.roads.size(); ++i) {
        // 车头和路口距离不足30米
        if (IntersectionOf(extLine, map.roads[i].stopLine) == GM_Intersection &&
            IntersectionOfLine(car->carXY[ car->axial[AXIAL_FRONT] ], map.roads[i].stopLine) == 1 ) {
            DEBUG("进入减速区");
            if (BreakDone == BREAK_ACTIVE) {
                map.roads[i].activeBreak = true;
            }
            if (DistanceOf(car->carXY[car->axial[AXIAL_FRONT]],
                           map.roads[i].stopLine) < DISTANCE_STOP_CAR_TO_STOP_LINE && moveDirect == 0) {
                map.roads[i].activeStop = true;
            }
        }
        // 跨线后,检查刹车动作
        if (CrashTheLine(map.roads[i].stopLine, car, CarModelList)) {
            if (map.roads[i].stopFlag != 0 && !map.roads[i].activeStop) {
                // 不停车瞭望,不合格
                DEBUG("不停车瞭望");
                if (map.roads[i].active == ROAD_ACTIVE_FORWARD) {
                    AddExamFault(42, rtkTime);
                } else if (map.roads[i].active == ROAD_ACTIVE_TURN_LEFT) {
                    AddExamFault(44, rtkTime);
                } else if (map.roads[i].active == ROAD_ACTIVE_TURN_RIGHT) {
                    AddExamFault(47, rtkTime);
                }
            }
            if (!map.roads[i].activeBreak) {
                // 不按规定减速,不合格
                DEBUG("不按规定减速");
                if (map.roads[i].active == ROAD_ACTIVE_FORWARD) {
                    AddExamFault(41, rtkTime);
                } else if (map.roads[i].active == ROAD_ACTIVE_TURN_LEFT) {
                    AddExamFault(43, rtkTime);
                } else if (map.roads[i].active == ROAD_ACTIVE_TURN_RIGHT) {
                    AddExamFault(46, rtkTime);
                }
            }
        }
    }*/
    // 人行道、公交站刹车点;学校限速区
//    DEBUG("补全特殊区域 size = %d", map.specialAreas.size());
    for (int i = 0; i < map.specialAreas.size(); i++) {
        if (map.specialAreas[i].type == GRID_AREA)
            continue;
        if (map.specialAreas[i].area.size() == 2 && map.specialAreas[i].leftPoints.size() != 2) {
            // 计算点到左侧路边线的垂点
            int road = 0;
            for (road = 0; road < map.roads.size(); ++road) {
                if (map.roads[road].id == map.specialAreas[i].road)
                    break;
            }
            PointF vPoint = CalcProjectionWithRoadEdge(map.roads[road].leftEdge, map.specialAreas[i].area[0]);
//            DEBUG("计算垂点1 (%f, %f)", vPoint.X, vPoint.Y);
            map.specialAreas[i].leftPoints.push_back(vPoint);
            vPoint = CalcProjectionWithRoadEdge(map.roads[road].leftEdge, map.specialAreas[i].area[1]);
//            DEBUG("计算垂点2 (%f, %f)", vPoint.X, vPoint.Y);
            map.specialAreas[i].leftPoints.push_back(vPoint);
        }
        if (map.specialAreas[i].type == ZEBRA_CROSSING || map.specialAreas[i].type == BUS_STATION_AREA) {
//            DEBUG("斑马线");
            Line startLine;
            MakeLine(&startLine, &map.specialAreas[i].area[0], &map.specialAreas[i].leftPoints[0]);
            // 车头和斑马线距离不足30米
            if (IntersectionOf(extLine, startLine) == GM_Intersection &&
                IntersectionOfLine(car->carXY[ car->axial[AXIAL_FRONT] ], startLine) == 1 ) {
                DEBUG("进入减速区 %d", map.specialAreas[i].type);
                if (BreakDone == BREAK_ACTIVE) {
                    map.specialAreas[i].activeBreak = true;
                }
            }
            // 跨线后,检查刹车动作
            if (CrashTheLine(startLine, car, CarModelList)) {
                if (!map.specialAreas[i].activeBreak) {
                    // 不按规定减速,不合格
                    DEBUG("不按规定减速");
                    if (map.specialAreas[i].type == ZEBRA_CROSSING) {
                        AddExamFault(48, rtkTime);
                    } else {
                        AddExamFault(50, rtkTime);
                    }
                } else {
                    DEBUG("按规定减速");
                }
            }
        } else if (map.specialAreas[i].type == SCHOOL_AREA) {
            Polygon school;
//            DEBUG("学校");
            school.num = 4;
            school.point = (PointF *) malloc(school.num * sizeof(PointF));
            school.point[0] = map.specialAreas[i].area[0];
            school.point[1] = map.specialAreas[i].area[1];
            school.point[2] = map.specialAreas[i].leftPoints[1];
            school.point[3] = map.specialAreas[i].leftPoints[0];
            if (IntersectionOf(car->carXY[ car->axial[AXIAL_FRONT] ], &school) == GM_Containment) {
                if (ConvertMs2KMh(speed) > PASS_SCHOOL_MAX_SPEED) {
                    if (!map.specialAreas[i].overSpeed) {
                        DEBUG("通过学校区域超速");
                        AddExamFault(49, rtkTime);
                        map.specialAreas[i].overSpeed = true;
                    }
                }
            }
            free(school.point);
        }
    }
//    DEBUG("补全特殊区域 over");
}
#if 0
typedef struct {
    int road;
    int segment;
    int lane;
} CarOnTrackInfo_t;
static CarOnTrackInfo_t CarOnTrackInfo;
void TestRoadGeneral(struct road_exam2_map &map, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime)
{
    // 检测车道变更
    CarOnTrackInfo_t newCarOnTrackInfo;
    if (newCarOnTrackInfo.road == CarOnTrackInfo.road &&
            newCarOnTrackInfo.segment == CarOnTrackInfo.segment &&
            newCarOnTrackInfo.lane != CarOnTrackInfo.lane) {
    }
    CarOnTrackInfo = newCarOnTrackInfo;
}
/**************************************************
 * 车辆当前所在路段,车头需越过起始线一定距离
 * @param currIndex
 * @param map
 * @param car
 */
static void EnterRoad(int &currIndex, struct road_exam2_map &map, const car_model *car)
{
    Polygon carBody;
    carBody.num = car->bodyNum;
    carBody.point = (PointF *)malloc(carBody.num * sizeof(PointF));
    for (int i = 0; i < carBody.num; ++i) {
        carBody.point[i] = car->carXY[car->body[i]];
    }
    Polygon roadArea;
    roadArea.num = 0;
    roadArea.point = NULL;
    for (int i = 0; i < map.roads.size(); ++i) {
        if (roadArea.point != NULL) {
            free(roadArea.point);
        }
        for (int x = 0; x < map.roads[i].leftEdge.size(); ++x) {
            roadArea.num += map.roads[i].leftEdge[x].points.size();
        }
        for (int x = 0; x < map.roads[i].rightEdge.size(); ++x) {
            roadArea.num += map.roads[i].rightEdge[x].points.size();
        }
        roadArea.point = (PointF *) malloc(roadArea.num * sizeof(PointF));
        int n = 0;
        for (int j = 0; j < map.roads[i].leftEdge.size(); j++) {
            for (int x = 0; x < map.roads[i].leftEdge[j].points.size(); ++x) {
                if (n > 0 && x == 0 && isEqual2(roadArea.point[n-1].X, map.roads[i].leftEdge[j].points[x].X) &&
                             isEqual2(roadArea.point[n-1].Y, map.roads[i].leftEdge[j].points[x].Y)) {
                    // 第一个点已经存在于上一条线
                } else {
                    roadArea.point[n++] = map.roads[i].leftEdge[j].points[x];
                }
            }
        }
        for (int j = map.roads[i].rightEdge.size(); j > 0; j--) {
            for (int x = map.roads[i].rightEdge[j].points.size(); x > 0; --x) {
                if (n > 0 && x == map.roads[i].rightEdge[j].points.size() &&
                            isEqual2(roadArea.point[n-1].X, map.roads[i].rightEdge[j - 1].points[x-1].X) &&
                            isEqual2(roadArea.point[n-1].Y, map.roads[i].rightEdge[j - 1].points[x-1].Y)) {
                    // 第一个点已经存在于上一条线
                } else {
                    roadArea.point[n++] = map.roads[i].rightEdge[j - 1].points[x - 1];
                }
            }
        }
        roadArea.num = n;
        if (IntersectionOf(car->carXY[car->axial[AXIAL_FRONT]], &roadArea) == GM_Containment) {
            currIndex = i;
            goto CHECK_CAR_ON_ROAD_END;
        }
    }
    currIndex = INVALID_ROAD;
    CHECK_CAR_ON_ROAD_END:
    if (roadArea.point != NULL) {
        free(roadArea.point);
    }
    free(carBody.point);
}
/******************************************************
 * 全车都需离开这个区域
 * @param currIndex
 * @param map
 * @param car
 * @return
 */
static bool ExitRoad(int currIndex, struct road_exam2_map &map, const car_model *car)
{
    // 全车都需不在地图中
    bool ret = false;
    if (currIndex == INVALID_ROAD || currIndex >= map.roads.size())
        return ret;
    Polygon carBody;
    carBody.num = car->bodyNum;
    carBody.point = (PointF *)malloc(carBody.num * sizeof(PointF));
    for (int i = 0; i < carBody.num; ++i) {
        carBody.point[i] = car->carXY[car->body[i]];
    }
    if (IntersectionOf(&carBody, &map.roads[currIndex].area) == GM_None) {
        ret = true;
    }
    free(carBody.point);
    return ret;
}
static bool CrashSeparateLine(int currIndex, struct road_exam2_map &map, const car_model *car)
{
    Line frontAxle, rearAxle;
    if (currIndex == INVALID_ROAD || currIndex >= map.roads.size())
        return false;
    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 < map.roads[currIndex].separate.size(); i++) {
        // 分段中的每条线
        for (int j = 0; j < map.roads[currIndex].separate[i].line.size(); j++) {
            Line theLine;
            int p1 = 0;
            for (int p2 = 1; p2 < map.roads[currIndex].separate[i].line[j].num; ++p2) {
                MakeLine(&theLine, &map.roads[currIndex].separate[i].line[j].point[p1], &map.roads[currIndex].separate[i].line[j].point[p2]);
                if (IntersectionOf(theLine, frontAxle) == GM_Intersection ||
                    IntersectionOf(theLine, rearAxle) == GM_Intersection) {
                    return true;
                }
                p1 = p2;
            }
        }
    }
    return false;
}
static void DetectSeparate(int currIndex, struct road_exam2_map &map, const car_model *car)
{
    int segment;
    int lane = -1;
    CarOnTrackInfo_t newInfo;
    if (currIndex == INVALID_ROAD || currIndex >= map.roads.size())
        return;
    // 遍历每一分段
    for (int i = 0; i < map.roads[currIndex].separate.size(); i++) {
        int separate_line_num = map.roads[currIndex].separate[i].lines.size();
        struct vrecord_ {
            int valid;
            int p1;
            int p2;
        };
        vector<struct vrecord_> vrecord;
        vrecord.clear();
        bool match1 = false;
        // 遍历当前分段的每一条线
        for (int j = 0; j < separate_line_num; ++j) {
            Line theLine;
            int p1 = 0;
            struct vrecord_ v;
            v.valid = 0;
            // 单独的一条虚线
            for (int p2 = 1; p2 < map.roads[currIndex].separate[i].lines[j].num; ++p2) {
                MakeLine(&theLine, &map.roads[currIndex].separate[i].lines[j].point[p1],
                         &map.roads[currIndex].separate[i].lines[j].point[p2]);
                if (VerticalPointOnLine(car->basePoint, theLine)) {
                    v.valid = 1;
                    v.p1 = p1;
                    v.p2 = p2;
                    match1 = true;
                    break;
                }
                p1 = p2;
            }
            vrecord.push_back(v);
            lane = separate_line_num;//
        }
        if (match1) {
            for (int x = 0; x < vrecord.size(); ++x) {
                if (vrecord[i].valid == 0) {
                    // 首尾两段线的延申必有一个垂点
                    if (DistanceOf(car->carXY[ car->axial[AXIAL_FRONT] ], map.roads[currIndex].separate[i].lines[x].point[0]) <
                        DistanceOf(car->carXY[ car->axial[AXIAL_FRONT] ], map.roads[currIndex].separate[i].lines[x].point[1])) {
                        vrecord[x].p1 = 0;
                        vrecord[x].p2 = 1;
                    } else {
                        vrecord[x].p1 = map.roads[currIndex].separate[i].lines[x].num - 2;
                        vrecord[x].p2 = map.roads[currIndex].separate[i].lines[x].num - 1;
                    }
                }
                int rel = IntersectionOfLine(map.roads[currIndex].separate[i].lines[x].point[vrecord[x].p1],
                                             map.roads[currIndex].separate[i].lines[x].point[vrecord[x].p2],
                                             car->basePoint);
                if (rel != -1) {
                    newInfo.road = currIndex;
                    newInfo.segment = i;
                    newInfo.lane = x;
                    break;
                }
            }
            newInfo.road = currIndex;
            newInfo.segment = i;
            newInfo.lane = vrecord.size();
            break;
        }
    }
}
#endif
lib/src/main/cpp/test_items2/road_exam.h
@@ -32,6 +32,7 @@
void TestRoadGeneral(road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime);
bool CrashTheLine(Line line, const car_model *car, LIST_CAR_MODEL &CarModelList);
PointF GetSELine(std::vector<edge_t> &edge, PointF point);
double CalcDistanceReference(PointF point, PointF refPoint, vector<edge_t> &edge);
PointF CalcProjectionWithRoadEdge(vector<edge_t> &edge, PointF point);
#endif //MYAPPLICATION2_ROAD_EXAM_H
lib/src/main/cpp/test_items2/through_something.cpp
@@ -12,151 +12,209 @@
#include "../jni_log.h"
#include "../test_common/car_sensor.h"
#include "road_exam.h"
#include "../utils/xconvert.h"
#define DEBUG(fmt, args...)     LOGD("<through_something> <%s>: " fmt, __func__, ##args)
#if 0
using namespace std;
static const double LASTEST_BREAK_POINT = 30.0;
static const double NEXT_ROAD_TIP = 100.0;                  // 到达路口前提示下一个怎么走
static const double DISTANCE_STOP_CAR_TO_STOP_LINE = 5.0;
static map <int, int> TargetReduceRec;
static map <int, int> TargetReduceRec2;
#define NOT_ENTER           1
#define ENTER_Z             2
#define REDUCE_SPEED        4
#define STOP_CAR            8
#define OVER_SPEED          16
static const double DISTANCE_STOP_CAR_TO_STOP_LINE = 3.0;
static const double PASS_SCHOOL_MAX_SPEED = 30.0;           // kmh
static const double LASTEST_BREAK_POINT = 30.0;
static int breakActive;
static int stopActive;
static bool crashRedLine;
void StartThroughExam(int index, LIST_ROAD_MAP &RoadMapList)
static void SetTargetReduceRec(map<int, int> &table, int key, int status)
{
    if (index == -1)
    auto it = table.find(key);
    if (it != table.end()) {
        table.erase(it);
    }
    table.insert(pair<int, int>(key, status));
}
static int GetTargetReduceRec(map<int, int> &table, int key)
{
    auto it = table.find(key);
    if (it != table.end()) {
        return it->second;
    }
    return NOT_ENTER;
}
static void RemoveTargetReduceRec(map<int, int> &table, int key)
{
    auto it = table.find(key);
    if (it != table.end()) {
        table.erase(it);
    }
}
void ResetTarget(road_exam_map &RoadMap)
{
    TargetReduceRec.clear();
    TargetReduceRec2.clear();
}
void ApproachTarget(road_exam_map &RoadMap, const car_model *car, int roadIndex, bool dobreak, double speed, int moveDirect, const struct RtkTime *rtkTime)
{
    if (roadIndex < 0 || roadIndex >= RoadMap.roads.size())
        return;
    DEBUG("进入路考通过something地图 index = %d id = %d item = %d", index, RoadMapList[index].id, RoadMapList[index].type);
    if (!RoadMapList[index].tts.empty()) {
        DEBUG("播放TTS %s", RoadMapList[index].tts.c_str());
        PlayTTS(RoadMapList[index].tts.c_str());
    } else {
        DEBUG("没有TTS");
    }
    breakActive = 0;
    stopActive = 0;
    crashRedLine = false;
}
    // 路口
    for (int i = 0; i < RoadMap.roads[roadIndex].stopLine.size(); ++i) {
        PointF point;
        double distance;
void InitThroughSomething(road_exam_map &RoadMap)
{
    breakRecord.clear();
    // 为每一个刹车检测点
    for (int i = 0; i < RoadMap.specialAreas.size(); ++i) {
        point.X = RoadMap.roads[roadIndex].stopLine[i].line.X1;
        point.Y = RoadMap.roads[roadIndex].stopLine[i].line.Y1;
        distance = CalcDistanceReference(car->carXY[car->axial[AXIAL_FRONT]], point, RoadMap.roads[roadIndex].rightEdge);
        int key = roadIndex * 100 + i;
        int rec = GetTargetReduceRec(TargetReduceRec, key);
        if (distance > 1e-3 && distance < LASTEST_BREAK_POINT) {
            if (rec == NOT_ENTER) {
                SetTargetReduceRec(TargetReduceRec, key, ENTER_Z);
            }
            // 记录刹车
            if (dobreak && !(rec & REDUCE_SPEED)) {
                SetTargetReduceRec(TargetReduceRec, key, rec | REDUCE_SPEED);
            }
        } else if (distance > 1e-3 && distance < DISTANCE_STOP_CAR_TO_STOP_LINE) {
            // 路口停车观察
            if (moveDirect == 0 && !(rec & STOP_CAR)) {
                SetTargetReduceRec(TargetReduceRec, key, rec | STOP_CAR);
            }
        } else if (distance > LASTEST_BREAK_POINT + 5 && rec != NOT_ENTER) {
            RemoveTargetReduceRec(TargetReduceRec, key);
        }
    }
    // 人行道、公交站、学校
    for (int i = 0; i < RoadMap.specialAreas.size(); i++) {
        if (RoadMap.specialAreas[i].type == GRID_AREA || RoadMap.specialAreas[i].road != RoadMap.roads[roadIndex].id)
            continue;
        if (RoadMap.specialAreas[i].type == ZEBRA_CROSSING || RoadMap.specialAreas[i].type == BUS_STATION_AREA) {
            breakRecord.insert(pair<int, bool>(RoadMap.specialAreas[i].id, false));
        }
    }
    for (int i = 0; i < RoadMap.roads.size(); ++i) {
        breakRecord.insert(pair<int, bool>(RoadMap.roads[i].id, false));
    }
}
            double distance = CalcDistanceReference(car->carXY[car->axial[AXIAL_FRONT]], RoadMap.specialAreas[i].area[0], RoadMap.roads[roadIndex].rightEdge);
int ExecuteThroughExam(int index, LIST_ROAD_MAP &RoadMapList, const car_model *car,
        LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime)
{
    PointF p1, p2;
            int key =  i;
            int rec = GetTargetReduceRec(TargetReduceRec2, key);
    double distance2StopLine = DistanceOf(car->carXY[car->axial[AXIAL_FRONT]],
                                          RoadMapList[index].stopLine);
    p1.X = RoadMapList[index].stopLine.X1;
    p1.Y = RoadMapList[index].stopLine.Y1;
    p2.X = RoadMapList[index].stopLine.X2;
    p2.Y = RoadMapList[index].stopLine.Y2;
    if (IntersectionOfLine(p1, p2, car->carXY[car->axial[AXIAL_FRONT]]) == -1) {
        distance2StopLine = -distance2StopLine;
    }
    // 距离停止线30米内是否有刹车动作
    if (breakActive == 0) {
        if (distance2StopLine > 0 && distance2StopLine <= LASTEST_BREAK_POINT) {
            if (ReadCarStatus(BREAK) == BREAK_ACTIVE) {
                breakActive = 1;
            if (distance > 1e-3 && distance < LASTEST_BREAK_POINT) {
                if (rec == NOT_ENTER) {
                    SetTargetReduceRec(TargetReduceRec2, key, ENTER_Z);
                }
                // 记录刹车,停车
                if (dobreak && !(rec & REDUCE_SPEED)) {
                    SetTargetReduceRec(TargetReduceRec2, key, rec | REDUCE_SPEED);
                }
            } else if (distance > LASTEST_BREAK_POINT + 5 && rec != NOT_ENTER) {
                RemoveTargetReduceRec(TargetReduceRec2, key);
            }
        }
        } else if (RoadMap.specialAreas[i].type == SCHOOL_AREA) {
            double distance1 = CalcDistanceReference(car->carXY[car->axial[AXIAL_FRONT]], RoadMap.specialAreas[i].area[0], RoadMap.roads[roadIndex].rightEdge);
            double distance2 = CalcDistanceReference(car->carXY[car->axial[AXIAL_FRONT]], RoadMap.specialAreas[i].area[1], RoadMap.roads[roadIndex].rightEdge);
            int key =  i;
            int rec = GetTargetReduceRec(TargetReduceRec2, key);
        if (distance2StopLine < 0 && breakActive != 1){
            breakActive = -1;
            // 不按规定减速,不合格
            DEBUG("不踩下刹车,不合格");
            switch (RoadMapList[index].type) {
                case THROUGH_INTERSECTION_MAP:
                    AddExamFault(41, rtkTime);
                    break;
                case TURN_LEFT_MAP:
                    AddExamFault(43, rtkTime);
                    break;
                case TURN_RIGHT_MAP:
                    AddExamFault(46, rtkTime);
                    break;
                case THROUGH_ZEBRA_CROSSING_MAP:
                    AddExamFault(48, rtkTime);
                    break;
                case THROUGH_SCHOOL_MAP:
            if (distance1 < -1e-3 && distance2 > 1e-3) {
                if (rec == NOT_ENTER) {
                    SetTargetReduceRec(TargetReduceRec2, key, ENTER_Z);
                }
                if (ConvertMs2KMh(speed) > PASS_SCHOOL_MAX_SPEED && !(rec & OVER_SPEED)) {
                    SetTargetReduceRec(TargetReduceRec2, key, rec | OVER_SPEED);
                    DEBUG("通过学校区域超速");
                    AddExamFault(49, rtkTime);
                    break;
                case THROUGH_BUS_STATION_MAP:
                    AddExamFault(50, rtkTime);
                    break;
                default:
                    break;
                }
            } else if (rec != NOT_ENTER) {
                RemoveTargetReduceRec(TargetReduceRec2, key);
            }
        }
    }
    // 有停止标记的,是否停车(停止线5米内有停车动作)
    if (RoadMapList[index].flagStop != 0 && stopActive == 0) {
        if (distance2StopLine < 0.0) {
            // 不停车瞭望,不合格
            DEBUG("不停车瞭望");
            switch (RoadMapList[index].type) {
                case THROUGH_INTERSECTION_MAP:
                    AddExamFault(42, rtkTime);
                    break;
                case TURN_LEFT_MAP:
                    AddExamFault(44, rtkTime);
                    break;
                case TURN_RIGHT_MAP:
                    AddExamFault(47, rtkTime);
                    break;
                default:
                    break;
            }
            stopActive = -1;
        } else if (distance2StopLine < DISTANCE_STOP_CAR_TO_STOP_LINE) {
            if (moveDirect == 0) {
                stopActive = 1;
            }
        }
    }
     if (CrashSonRedLine(index, RoadMapList, car, CarModelList)) {
         if (!crashRedLine) {
             DEBUG("不按考试员指令行驶");
             crashRedLine = true;
             // 不按考试员指令行驶
             AddExamFault(3, rtkTime);
         }
     } else {
         crashRedLine = false;
     }
    if (ExitSonArea(index, RoadMapList, car)) {
        DEBUG("离开通过something区域");
        return -1;
    }
    return index;
}
#endif
void ExitTarget(road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, const struct RtkTime *rtkTime)
{
    RECHECK:
    for (auto it = TargetReduceRec.begin(); it != TargetReduceRec.end(); ++it) {
            int road = it->first / 100;
            int x = it->first % 100;
            if (CrashTheLine(RoadMap.roads[road].stopLine[x].line, car, CarModelList)) {
                DEBUG("越过路口 road %d 路口 %d", road, x);
                if (!(it->second & REDUCE_SPEED)) {
                    // 不按规定减速,不合格
                    DEBUG("不按规定减速");
                    if (RoadMap.roads[road].stopLine[x].active == ROAD_ACTIVE_FORWARD) {
                        AddExamFault(41, rtkTime);
                    } else if (RoadMap.roads[road].stopLine[x].active ==
                               ROAD_ACTIVE_TURN_LEFT) {
                        AddExamFault(43, rtkTime);
                    } else if (RoadMap.roads[road].stopLine[x].active ==
                               ROAD_ACTIVE_TURN_RIGHT) {
                        AddExamFault(46, rtkTime);
                    }
                }
                if (!(it->second & STOP_CAR) && RoadMap.roads[road].stopLine[x].stopFlag) {
                    // 不停车瞭望,不合格
                    DEBUG("不停车瞭望");
                    if (RoadMap.roads[road].stopLine[x].active == ROAD_ACTIVE_FORWARD) {
                        AddExamFault(42, rtkTime);
                    } else if (RoadMap.roads[road].stopLine[x].active ==
                               ROAD_ACTIVE_TURN_LEFT) {
                        AddExamFault(44, rtkTime);
                    } else if (RoadMap.roads[road].stopLine[x].active ==
                               ROAD_ACTIVE_TURN_RIGHT) {
                        AddExamFault(47, rtkTime);
                    }
                }
                RemoveTargetReduceRec(TargetReduceRec, it->first);
                goto RECHECK;
            }
    }
    RECHECK2:
    for (auto it = TargetReduceRec2.begin(); it != TargetReduceRec2.end(); ++it) {
            int x = it->first;
            Line line;
            int roadIndex = 0;
            for (; roadIndex < RoadMap.roads.size(); ++roadIndex) {
                if (RoadMap.roads[roadIndex].id == RoadMap.specialAreas[x].road)
                    break;
            }
            PointF point2 = CalcProjectionWithRoadEdge(RoadMap.roads[roadIndex].leftEdge,
                                                       RoadMap.specialAreas[x].area[1]);
            MakeLine(&line, &RoadMap.specialAreas[x].area[1], &point2);
            if (CrashTheLine(line, car, CarModelList)) {
                if (RoadMap.specialAreas[x].type == ZEBRA_CROSSING &&
                    !(it->second & REDUCE_SPEED)) {
                    DEBUG("不按规定减速");
                    AddExamFault(48, rtkTime);
                }
                if (RoadMap.specialAreas[x].type == BUS_STATION_AREA &&
                    !(it->second & REDUCE_SPEED)) {
                    DEBUG("不按规定减速");
                    AddExamFault(50, rtkTime);
                }
                RemoveTargetReduceRec(TargetReduceRec2, it->first);
                goto RECHECK2;
            }
        }
}
lib/src/main/cpp/test_items2/through_something.h
@@ -6,6 +6,12 @@
#define MYAPPLICATION2_THROUGH_SOMETHING_H
#include "../driver_test.h"
void ResetTarget(road_exam_map &RoadMap);
void ApproachTarget(road_exam_map &RoadMap, const car_model *car, int roadIndex, bool dobreak, double speed, int moveDirect, const struct RtkTime *rtkTime);
void ExitTarget(road_exam_map &RoadMap, const car_model *car, LIST_CAR_MODEL &CarModelList, const struct RtkTime *rtkTime);
/*
void StartThroughExam(int index, LIST_ROAD_MAP &RoadMapList);
void InitThroughSomething(road_exam_map &RoadMap);
lib/src/main/java/com/anyun/exam/lib/RemoteService.java
@@ -25,6 +25,7 @@
import androidx.annotation.Nullable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -102,6 +103,24 @@
        ringUri = GetRingIndex(this, "Mira");
        PlayRing(this, ringUri);
        Log.d(TAG, "基带版本 " + getBaseband_Ver());
        String ver = getBaseband_Ver();
    }
    public String getBaseband_Ver(){
        String Version = "";
        try {
            Class cl = Class.forName("android.os.SystemProperties");
            Object invoker = cl.newInstance();
            Method m = cl.getMethod("get", new Class[] { String.class,String.class });
            Object result = m.invoke(invoker, new Object[]{"gsm.version.baseband", "no message"});
            Version = (String)result;
        } catch (Exception e) {
        }
        return Version;
    }
    private Uri GetRingIndex(Context context, String ring) {
lib/src/main/java/com/anyun/exam/lib/SvrManager.java
@@ -9,6 +9,8 @@
import android.text.TextUtils;
import com.anyun.basecommonlib.MyLog;
import java.util.LinkedList;
/**
lib/src/main/java/com/anyun/exam/lib/crash/CrashHandler.java
@@ -8,7 +8,7 @@
import android.widget.Toast;
import com.anyun.exam.lib.MyLog;
import com.anyun.basecommonlib.MyLog;
import java.io.PrintWriter;
import java.io.StringWriter;