yy1717
2020-05-15 76859aa4b23ea8ebd90bd7553fd70e144bdc96ba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
//
// Created by YY on 2020/3/24.
//
 
#include "stop_car.h"
#include "../driver_test.h"
#include "../native-lib.h"
#include "../jni_log.h"
#include "road_exam.h"
#include "../utils/xconvert.h"
#include "../common/apptimer.h"
#include "../test_common/car_sensor.h"
#include "../defs.h"
 
#define DEBUG(fmt, args...)     LOGD("<stop_car> <%s>: " fmt, __func__, ##args)
 
static bool inactiveBreakHandbreakTogether, notCloseEngine, inactiveHandBreakAfterOpenDoor, occurOpenDoor, doorNotClose, checkRoadDistance;
static int examTtsSeq = 0;
static int ttsPlayEnd;
static double moveDistance;
static double prevSpeed;
static struct drive_timer prevPointTime;
static int prevMoveDirect;
static uint32_t stopTimepoint = 0;
static uint32_t openDoorTimepoint;
 
const int ENGINE_MIN_ROTATE = 200;
 
static const uint32_t STOP_CAR_TIME = D_SEC(2);
static const uint32_t OPEN_DOOR_TIMEOUT = D_SEC(15);
static const double DISTANCE_TO_ROAD_EDGE_1 = 0.5;
static const double DISTANCE_TO_ROAD_EDGE_2 = 0.3;
 
static void PlayTTSTimeout(union sigval sig);
 
void StartStopCarExam(std::string tts) {
    DEBUG("靠边停车");
    ttsPlayEnd = 0;
    moveDistance = 0;
    prevMoveDirect = 0;
    inactiveBreakHandbreakTogether = false;
    notCloseEngine = false;
    inactiveHandBreakAfterOpenDoor = false;
    occurOpenDoor = false;
    doorNotClose = false;
    checkRoadDistance = false;
 
    if (!tts.empty()) {
        examTtsSeq = PlayTTS(tts.c_str());
    } else {
        examTtsSeq = PlayTTS("请靠边停车");
    }
 
    AppTimer_delete(PlayTTSTimeout);
    AppTimer_add(PlayTTSTimeout, D_SEC(8));
}
 
void StopCarTTSDone(int id)
{
    // 等语音播报完毕后计时
    if (id == examTtsSeq) {
        DEBUG("StopCarTTSDone %d", id);
        ttsPlayEnd = 1;
    }
}
 
void TerminateStopCarExam(void)
{
    AppTimer_delete(PlayTTSTimeout);
}
 
int ExecuteStopCarExam(int index, road_t &road, const car_model *car,
                             LIST_CAR_MODEL &CarModelList, double speed, int moveDirect, const struct RtkTime *rtkTime) {
    if (ttsPlayEnd == 1) {
        ttsPlayEnd = 2;
        prevSpeed = speed;
        Rtk2DriveTimer(prevPointTime, rtkTime);
    }
 
    if (ttsPlayEnd != 2)
        return index;
 
    uint32_t diff = TimeGetDiff(rtkTime->hh, rtkTime->mm, rtkTime->ss,
                                rtkTime->mss * 10,
                                prevPointTime.hour, prevPointTime.min,
                                prevPointTime.sec, prevPointTime.msec * 10);
    if (diff >= D_SEC(1)) {
        moveDistance += (double)diff * (speed + prevSpeed) / 2.0 / 1000.0;
        prevSpeed = speed;
        Rtk2DriveTimer(prevPointTime, rtkTime);
        DEBUG("停车已行驶距离 %f", moveDistance);
    }
 
    if (moveDistance > 150) {
        // 150米内未停车,不合格
        DEBUG("停车距离超标,靠边停车结束");
        AddExamFault(33, rtkTime);
        return -1;
    }
 
    if (moveDirect != prevMoveDirect) {
        if (moveDirect == 0) {
            stopTimepoint = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
            DEBUG("####### 靠边停车,停车了 %d %d %d %d %d %d %d ######", rtkTime->YY, rtkTime->MM, rtkTime->DD, rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss);
        }
        prevMoveDirect = moveDirect;
    } else if (moveDirect == 0) {
        uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
 
        if (tp - stopTimepoint >= STOP_CAR_TIME && !checkRoadDistance) {
            // 停车超2秒,开始判断
            DEBUG("检测和路边的距离");
            PointF pc, vp;
            bool get_vp = false;
            double dis2roadEdge = 0;
 
            checkRoadDistance = true;
            // 前后轮的中点
            pc.X = (car->carXY[car->right_front_tire[TIRE_OUTSIDE]].X + car->carXY[car->right_rear_tire[TIRE_OUTSIDE]].X) / 2;
            pc.Y = (car->carXY[car->right_front_tire[TIRE_OUTSIDE]].Y + car->carXY[car->right_rear_tire[TIRE_OUTSIDE]].Y) / 2;
 
            // 检测道路边缘线
            for (int i = 0; i < road.rightEdge.size(); ++i) {
                PointF p1, p2;
                Line edge;
 
                p1 = road.rightEdge[i].points[0];
                for (int j = 1; j < road.rightEdge[i].points.size(); ++j) {
                    p2 = road.rightEdge[i].points[j];
                    MakeLine(&edge, &p1, &p2);
 
 
                    if (VerticalPointOnLine(pc, edge, vp)) {
                        get_vp = true;
                        goto FIND_VP_END;
                    }
 
                    p1 = p2;
                }
            }
 
FIND_VP_END:
            if (get_vp) {
                dis2roadEdge = DistanceOf(pc, vp);
            } else {
                // 没有找到匹配线端,按最小距离顶点计算
                dis2roadEdge = 100;
                for (int i = 0; i < road.rightEdge.size(); ++i) {
                    for (int j = 0; j < road.rightEdge[i].points.size(); ++j) {
                        double dis;
                        if (dis2roadEdge > (dis = DistanceOf(pc, road.rightEdge[i].points[j]))) {
                            dis2roadEdge = dis;
                        }
                    }
                }
            }
 
            DEBUG("停车距路边距离 %f", dis2roadEdge);
 
            if (dis2roadEdge > DISTANCE_TO_ROAD_EDGE_1) {
                DEBUG("停车超出路边0.5米");
                // 停车距离超过50厘米,不合格
                AddExamFault(36, rtkTime);
            } else if (dis2roadEdge > DISTANCE_TO_ROAD_EDGE_2) {
                DEBUG("停车超出路边0.3米");
                // 停车距离超过30厘米,扣10分
                AddExamFault(37, rtkTime);
            }
        }
    }
 
    if (!inactiveBreakHandbreakTogether && ReadCarStatus(BREAK) == BREAK_INACTIVE && ReadCarStatus(HAND_BREAK) == BREAK_INACTIVE) {
        // 拉手刹前,松脚刹,扣10分
        DEBUG("拉手刹前,松脚刹");
        AddExamFault(39, rtkTime);
        inactiveBreakHandbreakTogether = true;
    }
 
    if (!notCloseEngine && ReadCarStatus(ENGINE_RPM) < ENGINE_MIN_ROTATE && ReadCarStatus(DOOR) == DOOR_OPEN) {
        // 下车前,不熄火,扣5分
        DEBUG("下车前,不熄火");
        AddExamFault(40, rtkTime);
 
        notCloseEngine = true;
    }
 
    if (!inactiveHandBreakAfterOpenDoor && ReadCarStatus(DOOR) == DOOR_OPEN && ReadCarStatus(HAND_BREAK) == BREAK_INACTIVE) {
        // 开门前,未拉手刹, 扣10分
        DEBUG("开门前,未拉手刹");
        AddExamFault(38, rtkTime);
 
        inactiveHandBreakAfterOpenDoor = true;
    }
 
    if (ReadCarStatus(DOOR) == DOOR_OPEN) {
        if (!occurOpenDoor) {
            occurOpenDoor = true;
            openDoorTimepoint = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
        } else {
            uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
 
            if (!doorNotClose && tp - openDoorTimepoint >= OPEN_DOOR_TIMEOUT) {
                // 开门时间超过15秒,不合格
                DEBUG("开门时间超过15秒");
                AddExamFault(35, rtkTime);
                doorNotClose = true;
            }
        }
    } else if (occurOpenDoor) {
        DEBUG("开车门,靠边停车结束");
        return -1;
    }
 
    if (occurOpenDoor) {
        uint32_t tp = TimeMakeComposite(rtkTime->hh, rtkTime->mm, rtkTime->ss, rtkTime->mss*10);
 
        if (tp - openDoorTimepoint >= OPEN_DOOR_TIMEOUT + D_SEC(5)) {
            DEBUG("开门时间大于20秒,靠边停车结束");
            return -1;
        }
    }
 
    return index;
}
 
static void PlayTTSTimeout(union sigval sig)
{
    AppTimer_delete(PlayTTSTimeout);
 
    ttsPlayEnd = 1;
}