yincheng.zhong
2025-11-25 427d0b6ee0966fcf19a75914a47360969e00e456
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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
o
9x$i„–ã@sÚdZddlmZddlZddlZddlZddlZddlZddlZddl m
Z
ddl m Z m Z mZmZz ddlmZmZmZWn eyIdZYnwzddlmZWn ey]dZYnwdd   lmZmZmZmZmZdd
lmZmZm Z d Z!d Z"d Z#dZ$dZ%dZ&dZ'e
e(ƒ )¡j*Z+e+dZ,e+dZ-e- .d¡Z/e+dZ0d:dd„Z1d;dd„Z2d<d=d$d%„Z3d>d'd(„Z4d?d*d+„Z5Gd,d-„d-ƒZ6Gd.d/„d/ej7ƒZ8Gd0d1„d1ƒZ9Gd2d3„d3ej:ƒZ;d@d5d6„Z<d7d8„Z=e>d9krëe ?e=ƒ¡dSdS)Au]
HITL ä»¿çœŸå™¨ GUI:左侧地图显示路径/车辆,右侧显示状态与控制信息。
é)Ú annotationsN)ÚPath)ÚDictÚListÚOptionalÚTuple)ÚQtCoreÚQtGuiÚ  QtWidgets)Ú
list_portsé)Ú ControlStatusÚ
PoseStatusÚ StackStatusÚ StateStatusÚ nmea_checksum)Ú
HitlConfigÚ HitlSimulatorÚ  RunLoggerZCOM11ZCOM17zX$GNGGA,080112.000,3949.8105069,N,11616.6876082,E,4,44,0.42,48.502,M,-6.684,M,1.0,0409*73)çrrriÂiz
runlog.txtzpath_text_input.txtz.czdashboard_state.jsonÚ  path_filerÚreturnúList[Tuple[float, float]]c  Cs"| ¡s
tt|ƒƒ‚|jdd ¡}|sgSg}|j ¡dks$| d¡rZz)t    |¡}|D]}t
|t t fƒrJt |ƒdkrJ| t|dƒt|dƒf¡q,|WStjyYgYSw| d¡D]/}| ¡}|shq_| d ¡}t |ƒdkrtq_z| t|dƒt|dƒf¡Wq_tyŽYq_w|S)
Núutf-8©Úencodingz.jsonú[érr ú;ú,)ÚexistsÚFileNotFoundErrorÚstrÚ  read_textÚstripÚsuffixÚlowerÚ
startswithÚjsonÚloadsÚ
isinstanceÚlistÚtupleÚlenÚappendÚfloatZJSONDecodeErrorÚsplitÚ
ValueError)rÚtextÚpointsÚdataÚptÚtokenÚparts©r8ú/E:\GIT\Lawnmower_STM32H7\python\hitl\run_sim.pyÚload_path_points+s< 
€ÿ
 " ÿr:r2r"c   CsŽ| dd¡ d¡}g}|D]7}| ¡}|sq | d¡}t|ƒdkr"q zt|d ¡ƒ}t|d ¡ƒ}| ||f¡Wq tyDYq w|S)NÚ
ú rrrrr )Úreplacer0r$r-r/r.r1)r2Útokensr3r6r7ÚxÚyr8r8r9Úparse_path_textIs"
  ÿrArr3ÚdecimalsÚintc    Cs„|sdSd|›d}dg}t|ƒD]&\}\}}|t|ƒdkr!dnd}| d| |¡›d | |¡›d
|›¡q| d ¡d  |¡S) Nz%const float g_motion_path_xy[] = {};
z{:.zf}z"const float g_motion_path_xy[] = {r rÚz    zf, Úfz};r;)Ú enumerater-r.ÚformatÚjoin)r3rBZfmtÚlinesÚidxr?r@Zcommar8r8r9Úformat_path_for_mcu\s *
 
rKÚggac
Cs¶|pd ¡}|s
dS| d¡d}dd„| d¡Dƒ}t|ƒdkr#dS|d}|d   }|d
}|d }t|ƒd krA|d rA|d nd}|›d|›d|›d|›}   |rY|   d|›7} |   S) NrDÚ*rcSsg|]}| ¡‘qSr8©r$©Ú.0Úpr8r8r9Ú
<listcomp>msz'gga_to_short_origin.<locals>.<listcomp>réréééé   )r$r0r-)
rLr2Úbodyr7ZlatÚlat_dirZlonÚlon_dirÚaltZshortr8r8r9Úgga_to_short_originhs    r\Útemplatec CsLdd„| dd¡ d¡Dƒ}t|ƒdkrtdƒ‚|d}|d   ¡}|d
}|d  ¡}t|ƒd kr6|dnd}|d vs@|dvrDtdƒ‚|pGt}d} | d¡rW|dd…}d}   | d¡d}
|
 d¡} t| ƒdkrt|  d¡t| ƒdksi| dpyd| d<|| d
<|| d <|| d<|| d <|dur”|| d<d | ¡}
t   |
ƒ} |
›d| ›|   ›S)NcSsg|]
}| ¡r| ¡‘qSr8rN)rPÚtr8r8r9rR|sz/build_gga_from_short_origin.<locals>.<listcomp>r;r<rrUu)原点格式应为 'lat,N,lon,E[,alt]'。rr rrTrV)ÚNÚS)ÚEÚWu方向必须是 N/S/E/W。rDz
éþÿÿÿrMé z$GNGGArW)
r=r0r-r1ÚupperÚDEFAULT_ORIGIN_GGAÚendswithr.rHr) r2r]r>Zlat_dmrYZlon_dmrZr[ÚbaseÚnewlinerXZfieldsZchecksumr8r8r9Úbuild_gga_from_short_origin{s<   
 
 
 ÿ
rjc@s.eZdZdd„Zd dd„Zdd„Zd d
„Zd S) Ú HitlGuiBridgecCstjdd|_t ¡|_dS)NéÈ)Úmaxsize)ÚqueueZQueueÚ threadingZLockÚ_lock©Úselfr8r8r9Ú__init__szHitlGuiBridge.__init__Úkindr"cCs:|j| ||f¡WdƒdS1swYdS©N)rpÚ_enqueue)rrrtr4r8r8r9Úpublish¡s"ÿzHitlGuiBridge.publishc Cs„|j5|j ¡s(z|j ¡Wn
tjyYnw|j ¡r   WdƒdSWdƒdSWdƒdS1s;wYdSru)rprnZemptyÚ
get_nowaitÚEmptyrqr8r8r9Úreset¥s
ÿ ýÿÿ"ûzHitlGuiBridge.resetc Csvz |j |¡WdStjy:z|j ¡Wn
tjy"Ynwz
|j |¡WYdStjy9YYdSwwru)rnZ
put_nowaitZFullrxry)rrÚitemr8r8r9rv­sÿÿùzHitlGuiBridge._enqueueN)rtr")Ú__name__Ú
__module__Ú __qualname__rsrwrzrvr8r8r8r9rkœs
 
 rkcsheZdZe ee¡Z    ‡fdd„Zddd„Zd‡fdd    „ Z d‡fd
d „ Z
ddd„Z d‡fdd„ Z ‡Z S)ÚZoomableGraphicsViewcsztƒj|i|¤Ž| tjjd¡| tjj   ¡| 
tjj   ¡|  tjj ¡|  tjj¡d|_d|_t ¡|_d|_dS)NTgffffffò?F)ÚsuperrsZ setRenderHintr    ZQPainterZ AntialiasingZsetTransformationAnchorr
Ú QGraphicsViewZAnchorUnderMouseZsetResizeAnchorZ setDragModeZNoDragÚ setCursorrÚQtÚOpenHandCursorÚ _zoom_factorÚ_panningZQPointÚ _pan_last_posÚ on_user_pan)rrÚargsÚkwargs©Ú  __class__r8r9rs¿s
 
zZoomableGraphicsView.__init__ÚeventúQtGui.QWheelEventcCs4| ¡ ¡}|dkr |jnd|j}| ||¡dS)Nrçð?)Z
angleDeltar@r…Zscale)rrrÚdeltaZ scale_factorr8r8r9Ú
wheelEventËs zZoomableGraphicsView.wheelEventúQtGui.QMouseEventcsJ| ¡tjjkrd|_| ¡|_| tjj¡|     ¡dSt
ƒ  |¡dS)NT) ÚbuttonrrƒÚ
LeftButtonr†Úposr‡r‚ZClosedHandCursorÚacceptr€ÚmousePressEvent©rrrr‹r8r9r—Ðs
z$ZoomableGraphicsView.mousePressEventcsŠ|jr2| | ¡¡}| |j¡}||}| ¡|_| | ¡ | ¡ ¡|jr,| ¡| ¡dS|j    j
|  | ¡¡Žt ƒ  |¡dSru)r†Ú
mapToScener•r‡Ú   translater?r@rˆr–ÚsceneMouseMovedZemitÚ _scene_coordsr€ÚmouseMoveEvent)rrrÚ   scene_posZlast_scene_posrr‹r8r9rÙs 
z#ZoomableGraphicsView.mouseMoveEventÚview_posú QtCore.QPointrúTuple[float, float]cCs| |¡}| ¡| ¡fSru)r™r?r@)rrrŸržr8r8r9rœçs
z"ZoomableGraphicsView._scene_coordscsF| ¡tjjkr|jrd|_| tjj¡| ¡dStƒ     |¡dS)NF)
r“rrƒr”r†r‚r„r–r€ÚmouseReleaseEventr˜r‹r8r9r¢ës z&ZoomableGraphicsView.mouseReleaseEvent)rrŽ)rr’)rŸr rr¡)r|r}r~rZ
pyqtSignalr/r›rsr‘r—rrœr¢Ú __classcell__r8r8r‹r9r»s  
    
rc@sNeZdZddd„Zdd„Zdd„Zdd d „Zddd„Zddd„Zd dd„Z dS)!ÚDashboardStateStoreÚpathrcCst|ƒ|_i|_| ¡dSru)rr¥r4Ú_load)rrr¥r8r8r9rsõs
 zDashboardStateStore.__init__cCsL|j ¡s
i|_dSzt |jjdd¡|_WdSty%i|_YdSw)Nrr)r¥r r4r(r)r#Ú    Exceptionrqr8r8r9r¦ús
  ÿzDashboardStateStore._loadcCs:z|jjtj|jdddddWdStyYdSw)NFr)Z ensure_asciiZindentrr)r¥Ú
write_textr(Údumpsr4r§rqr8r8r9Úsaves
$ ÿzDashboardStateStore.saverú+Optional[Tuple[float, float, float, float]]c  CsT|j d¡}t|tƒr(t|ƒdkr(z
tdd„|DƒƒWSttfy'YdSwdS)NÚposerUcss|]}t|ƒVqdSru)r/)rPÚvr8r8r9Ú  <genexpr> s€z/DashboardStateStore.get_pose.<locals>.<genexpr>)r4Úgetr*r+r-r,Ú    TypeErrorr1©rrr¬r8r8r9Úget_pose s ÿzDashboardStateStore.get_poseÚeastr/ÚnorthÚupÚheadingcCs||||g|jd<| ¡dS©Nr¬©r4rª©rrr³r´rµr¶r8r8r9Úset_poses zDashboardStateStore.set_poseú Optional[str]cCs|j d¡}t|tƒr |SdS©NÚorigin)r4r¯r*r")rrr½r8r8r9Ú
get_origins 
zDashboardStateStore.get_originÚ
origin_strr"cCs||jd<| ¡dSr¼r¸)rrr¿r8r8r9Ú
set_origins
 zDashboardStateStore.set_originN)r¥r)rr«)r³r/r´r/rµr/r¶r/)rr»)r¿r")
r|r}r~rsr¦rªr²rºr¾rÀr8r8r8r9r¤ôs
    
 
    
r¤csôeZdZdF‡fd
d „ ZdGd d „Zdd„ZdHdd„ZdIdd„ZdJdGdd„ZdKdd„Z   dd „Z
dLd"d#„Z dMd&d'„Z d(d)„Z d*d+„Zd,d-„Zd.d/„Zd0d1„Zd2d3„Z‡fd4d5„Zd6d7„Zd8d9„Zd:d;„ZdMd<d=„Zd>d?„Zd@dA„ZdBdC„ZdDdE„Z‡ZS)NÚ HitlDashboardÚ    simulatorrÚbridgerkÚ path_pointsrÚ initial_uart2r»Ú initial_uart5csätƒ ¡||_||_t|pgƒ|_g|_d|_d|_d|_   i|_
d|_ |  d¡|  dd¡d|_g|_ttƒ|_| ||¡| ¡|j ¡ ¡sT|jrT| |j¡| ¡| ¡t |¡|_|jj |j ¡|j !d¡dS)NTuHITL ä»¿çœŸçŠ¶æ€é¢æ¿iiÐFéP)"r€rsrÂrÃr+rÄÚ trail_pointsÚcontrol_statusÚ pose_statusÚ state_statusÚ stack_statusÚ _auto_followZsetWindowTitleZresizeÚ _serial_openÚ _last_portsr¤Ú
STATE_FILEÚ state_storeÚ    _build_uiÚ_load_saved_path_textÚ   path_textÚ toPlainTextr$Ú_update_path_text_from_pointsÚ_load_saved_poseÚ _init_scenerZQTimerZtimerÚtimeoutÚconnectÚ _drain_queueÚstart)rrrÂrÃrÄrÅrÆr‹r8r9rs"s0
 
 
   zHitlDashboard.__init__c Csôt ¡}t |¡}| |¡t |¡|_t ¡}t |¡}| dddd¡| d¡t  |jƒ|_
|j |j
_ |j
j  |j¡|j|j
ddt d¡|_|j d¡|jj |j¡|j|jtjjdt d¡|_|j d ¡|j|jtjjd|j|d
dtdu|_t ¡}t |¡}| d ddd¡|j|d dt d ¡}   t  |   ¡}
t !¡|_"t !¡|_#t $d¡|_%t $d¡|_&t d¡|_'|j' d¡|
 t d¡dd¡|
 |j"dd¡|
 t d¡dd¡|
 |j#dd¡|
 |j%dd d d¡|
 |j&d ddd
¡|
 |j'd
ddd
¡| |   ¡tdur'|j% (d¡|j" )d¡|j# )d¡t d¡} t | ¡} t *¡|_+|j+ ,d¡|j+ -t.j/j0¡t ¡} t $d¡|_1t $d¡|_2|  |j1¡|  |j2¡|  |j+¡|  3| ¡| | ¡t d¡}t  |¡}t4|j5j6j7ƒ}t 8|¡|_9|j9 ,d¡t $d¡|_:| t d¡dddd ¡| |j9dd dd ¡| |j:dd¡gd¢}g|_;t<|ƒD]N\}}t =¡}|d
krÕ| >dd¡| ?d
¡n | >d d!¡| ?d ¡| t |¡d|d |d d ¡| |d|d |d d d¡|j; @|¡q¼t $d"¡|_A| |jAd
ddd¡| |¡t d#¡}t |¡}t d$¡|_B|jB CtjjDtjjB¡|jB d%¡t E¡}| Fd¡| G|jB¡| |¡|j|ddt d&¡}t |¡}t Hdd
¡|_I|jI Jgd'¢¡|jI K¡ Ld¡| |jI¡| |¡t d(¡}t |¡}t *¡|_M|jM Nd¡| |jM¡|j|dd|j Ot. P¡t. Qt. Rd)¡d¡¡|_S|j Ot. P¡t. Qt. Rd*¡d¡¡|_Td+|_U|j V|jU |jU |jUd |jUd t. Qt. Rd,¡d¡t. Wt. Rd-¡¡¡|_Xt. Qt. Rd.¡d¡}| YtjjZ¡|j Ot. P¡|t. Wt. Rd.¡¡¡|_[d/|_\|j V|j\ |j\ |j\d |j\d t. Qt. Rd0¡¡t. Wt. Rd0¡¡¡|_]|j1j^ |j_¡|j2j^ |j`¡|j:j^ |ja¡|jAj^ |jb¡|j%j^ |jc¡|j&j^ |jd¡| c||¡| ed¡| f¡dS)1NrrUr )Zstretchu自动跟随车辆T)Z  alignmentzE: 0.00  N: 0.00zQcolor:#222; background:rgba(255,255,255,190); padding:2px 6px; border-radius:4px;rTéru 串口设置u刷新õ 打开串口õ状态: æœªè¿žæŽ¥ú color: gray;zUART2:zUART5:Fu 路径轨迹u)示例:23.36,-42.93;29.26,-52.99; ... ;u加载到地图u导出 MCU æ ¼å¼u 原点/起点z3949.9120,N,11616.8544,E[,alt]u 更新原点u坐标 (lat,N,lon,E):)zE (m)zN (m)zU (m)z Heading (deg)g@Àg@@g€vÀg€v@u 重置位置u 车辆状态õ等待数据...z6font-family: Consolas, 'Courier New'; font-size: 12px;u 堆栈监测)u任务u堆栈余量(word)u剩余堆(byte)u 串口日志ZgrayZblueçÐ?z#d11d29z#ff4b5cz#ff8c00g{®Gáz´?Zgreen)gr
ZQWidgetZ QHBoxLayoutZsetCentralWidgetZQGraphicsSceneÚsceneZ QVBoxLayoutZsetContentsMarginsZ
setSpacingrÚviewÚ_handle_user_panrˆr›rÚÚ_update_mouse_posZ  addWidgetZ  QCheckBoxÚfollow_checkboxÚ
setCheckedZtoggledÚ_on_follow_toggledrrƒZ  AlignLeftZQLabelÚmouse_pos_labelÚ setStyleSheetZ
AlignRightr Ú_port_refresh_supportedZ   QGroupBoxZ QGridLayoutZ QComboBoxÚ port2_comboÚ port5_comboZ QPushButtonÚport_refresh_btnÚserial_toggle_btnÚserial_status_labelÚ
setEnabledZ setEditableZQPlainTextEditrÔZsetPlaceholderTextZsetWordWrapModer  Z QTextOptionZNoWrapZ path_load_btnZpath_export_btnZ   addLayoutr\rÂÚconfigÚ
origin_ggaZ QLineEditÚ origin_textÚ
origin_btnÚpos_spinrFZQDoubleSpinBoxZsetRangeZ setDecimalsr.Úreset_pose_btnÚ
info_labelZ setAlignmentZAlignTopZ QScrollAreaZsetWidgetResizableZ    setWidgetZ QTableWidgetÚ stack_tableZsetHorizontalHeaderLabelsZhorizontalHeaderZsetStretchLastSectionÚlog_viewÚ setReadOnlyZaddPathÚ QPainterPathZQPenZQColorÚ   path_itemÚ
trail_itemÚ
robot_sizeZ
addEllipseZQBrushÚ
robot_itemZ setJoinStyleZ   RoundJoinÚ heading_itemÚ target_radiusÚ target_itemZclickedÚ_load_path_from_textÚ_export_path_to_mcuÚ_update_originÚ_reset_positionÚ_refresh_serial_portsÚ_toggle_serialÚ_set_controls_enabledÚ_update_serial_ui)rrrÅrÆZcentralZlayoutZ
left_panelZ left_layoutZ right_panelZ right_layoutZ serial_groupZ serial_layoutZ
path_groupZ path_layoutZ
button_rowZ origin_groupZgridZdefault_origin_shortZlabelsrJZlabelZspinZ status_groupZ status_layoutZ info_scrollZ stack_groupZ stack_layoutZ    log_groupZ
log_layoutZ arrow_penr8r8r9rÒFs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
$" 
 
 
 
 
 
 
 
 
 
 
  ""úýú   
 zHitlDashboard._build_uicCs8|jr|j d¡|j d¡|j d¡d|_dSdS)NTF)rÍrçÚ blockSignalsrèrqr8r8r9råïs    
üzHitlDashboard._handle_user_panÚcheckedÚboolcCs4||_|r|jr|j |jj|jj ¡dSdSdSru)rÍrÊräÚcenterOnr³r´)rrrr8r8r9réös
ÿz HitlDashboard._on_follow_toggledr³r/Úscene_ycCs&| }|j d|d›d|d›¡dS)NzE: z .2fú  N: )rêÚsetText)rrr³rr´r8r8r9ræûs zHitlDashboard._update_mouse_posNcsŠg‰trz dd„t ¡Dƒ‰Wn tyg‰Ynw|p#|jjjp#d}|p,|jjjp,d}d
‡fdd „ }||j|ƒ||j|ƒˆ|_   dS) NcSsg|]}|j‘qSr8)ZdevicerOr8r8r9rRsz7HitlDashboard._refresh_serial_ports.<locals>.<listcomp>rDÚcomboúQtWidgets.QComboBoxÚsavedr"cst| ¡}| d¡| ¡ˆr| ˆ¡|r|ˆvr| |¡|p"|}|r3| |¡}|dkr3| |¡| d¡dS)NTrF)Ú currentTextr ÚclearZaddItemsZaddItemZfindTextZsetCurrentIndex)rrZcurrentÚtargetrJ©Zportsr8r9Ú_fill   s
 
 
 
 
z2HitlDashboard._refresh_serial_ports.<locals>._fill)rrrr")
r Zcomportsr§rÂróÚ
uart2_portÚ
uart5_portrírîrÏ)rrrÅrÆZ saved_uart2Z saved_uart5rr8rr9r   ÿs ÿ  
z#HitlDashboard._refresh_serial_portsÚenabledcCs(|j |¡|j d¡|j d¡dS)NFT)røròrõrürö)rrrr8r8r9r s  z#HitlDashboard._set_controls_enabledcCsZt ¡r)ztjdd}Wn tyd}Ynw|j |¡t|ƒ}|r+||_dSdSdS)NrrrD)ÚPATH_TEXT_FILEr r#r§rÔÚ setPlainTextrArÄ©rrr2r3r8r8r9rÓ!s ÿ 
øz#HitlDashboard._load_saved_path_textr3cCs:|s    |j ¡dSd dd„|Dƒ¡d}|j |¡dS)Nrcss&|]\}}|d›d|d›VqdS)ú.2frNr8)rPr?r@r8r8r9r®0s€$z>HitlDashboard._update_path_text_from_points.<locals>.<genexpr>)rÔrrHr )rrr3r2r8r8r9rÖ,s
 
z+HitlDashboard._update_path_text_from_pointsr2r"c
CsVz tj| ¡ddWdSty*}ztj |dd|›¡WYd}~dSd}~ww)Nrrõ路径u保存路径文本失败: )rr¨r$r§r
Ú QMessageBoxÚwarning)rrr2Úexcr8r8r9Ú_save_path_text3s $€ÿzHitlDashboard._save_path_textcCsf|j ¡}|r1|jd |d¡|jd |d¡|jd |d¡|jd |d¡dSdS)Nrr rrT)rÑr²r÷ÚsetValuer±r8r8r9r×9s
üzHitlDashboard._load_saved_posecCsx|j ¡ ¡}t|ƒ}|stj |dd¡dS||_|j     ¡| 
|¡|  ¡|  ¡tj  |ddt|ƒ›d¡dS)Nr#u9未解析到有效的轨迹点,请检查输入格式。u
已加载 u ä¸ªè·¯å¾„点。)rÔrÕr$rAr
r$r%rÄrÈrr'rØÚ _refresh_viewÚ informationr-r!r8r8r9rAs
 
 z"HitlDashboard._load_path_from_textc
Cs´|j ¡ ¡}t|ƒ}|stj |dd¡dSt|ƒ}tj  ¡}| 
|¡z t j |ddWnt yK}ztj |dd|›¡WYd}~nd}~wwtj |ddtt ƒ¡dS)Nu导出u3没有可导出的路径点,请先加载路径。rru写入文件失败: u#已复制到剪贴板,并写入:
)rÔrÕr$rAr
r$r%rKÚ QApplicationÚ   clipboardrÚPATH_EXPORT_FILEr¨r§r*r")rrr2r3Z  formattedr,r&r8r8r9rNs
 
"€ÿz!HitlDashboard._export_path_to_mcucCsÊ|j |jrdnd¡|jr0|jjjpd}|jjjpd}|j d|›d|›d¡|j d¡n |j d ¡|j d
¡|j }|j  
|pI|j   ¡¡|j  
|pT|j   ¡¡|j rc|j 
|j ¡dSdS) Nu 关闭串口rÞu未知u无u状态: å·²è¿žæŽ¥ (UART2=z, UART5=ú)z color: green;rßrà)rðrrÎrÂÚuart2ÚportÚlog_uartrñrëríròZ
isEditablerîrìrï)rrr/Úuart5Z enable_portsr8r8r9r ]s  ÿzHitlDashboard._update_serial_uic
Csò|jr   | ¡dS|j ¡ ¡}|stj |dd¡dS|j ¡ ¡}|p&d}||j   j
_ ||j j
_ ||j j _||j   j_z|j    ¡Wn#tye}z|j  ¡tj |dd|›¡WYd}~dSd}~wwd|_|j ¡| d¡| ¡dS)Nu串口u请先选择 UART2 ç«¯å£ã€‚u打开串口失败: T)rÎÚ _close_serialrírr$r
r$r%rîrÂrórrr/r0r1rÜr§ÚstopZcriticalrÃrzr r )rrr/Z
uart5_textr2r&r8r8r9r
ms2
 
 
 
 
€ý
 
 zHitlDashboard._toggle_serialcCs€|j ¡|j ¡|j ¡d|_d|_d|_|j   ¡|j
 ¡|j   d¡|j  d¡d|_| d¡| ¡| ¡dS)NrárF)rÂr4rÃrzrÈrrÉrÊrËrÌrûrùrrúÚ setRowCountrÎr r r)rqr8r8r9r3†s
 
 
 
 
 
 zHitlDashboard._close_serialcs|jr| ¡tƒ |¡dSru)rÎr3r€Ú
closeEventr˜r‹r8r9r6–szHitlDashboard.closeEventc
CsÆ|j ¡ ¡}|stj |dd¡dS|jjjpt   }zt
||ƒ}Wnt y?}ztj |dd|›¡WYd}~dSd}~ww|j  |¡||jj_|j  t|ƒ¡|j |¡tj |dd¡dS)Nu原点u,请输入坐标,格式:lat,N,lon,E[,alt]u格式错误: u原点已更新。)rõr2r$r
r$r%rÂrórôrfrjr1Z update_originrr\rÑrÀr*)rrr2r]rLr&r8r8r9r›s"€þ 
 zHitlDashboard._update_origincCsp|jd ¡}|jd ¡}|jd ¡}|jd ¡}|j ||||¡|j ||||¡tj |dd¡dS)Nrr rrTu位置u已重置仿真状态。) r÷ÚvaluerÂZ reset_staterÑrºr
r$r*r¹r8r8r9r¬szHitlDashboard._reset_positioncCs$|js|j dddd¡dSt ¡}d}g}g}|jD]"\}}| |¡| | ¡|r6| || ¡d}q| || ¡q|j  |¡t
|ƒ}t |ƒ}t
|ƒ}   t |ƒ}
||} |
|   } t d| dƒ} t d| dƒ}t   || | || dkrx| nd| d   | dkrƒ| nd|d   ¡}|j |¡dS)
NiÿÿÿiôTFg$@gè?rrg@)rÄrãZ setSceneRectr   rýr.ÚmoveToÚlineTorþÚsetPathÚminÚmaxrZQRectF)rrr¥ÚfirstZxsZysZpxÚpyZmin_xZmax_xZmin_yZmax_yÚwidthZheightZpad_xZpad_yZ
scene_rectr8r8r9rصs<
  üzHitlDashboard._init_scenecCs*|j |¡|j ¡ |j ¡ ¡¡dSru)rûZappendPlainTextZverticalScrollBarr(Zmaximum)rrr2r8r8r9Ú _append_logÖs zHitlDashboard._append_logcCsÐd}  z
|jj ¡\}}Wn
tjyYnGw|dkr ||_n;|dkr?||_|j |j|j f¡t
|jƒdkr>|j  d¡n|dkrG||_ n|dkrR||j |j<n |d kr[| |¡d}q|rf| ¡dSdS)
NFTÚcontrolr¬iÐrÚstateÚstackÚlog)rÃrnrxryrÉrÊrÈr.r³r´r-ÚpoprËrÌÚ task_namer@r))rrÚupdatedrtr4r8r8r9rÛÚs4ÿ €
î ÿzHitlDashboard._drain_queuecCsŽg}|jr?|j}|dd|jd›d|jd›d|jd›ddd|jd    ›d
|jd   ›d |jd ›d |jd ›d|jd ›dg
7}|j rn|j   }|ddd|j
d›dd|j d›dd|j ›d|j ›d|jd›dd|j›g7}|jrŒ|j}|dd|j›d|jd›dd|jd ›dg7}|jr¯|dd g7}|j ¡D]}| d!|j›d"|j›d#|j›d$¡qš|s´d%g}|j d& |¡¡| ¡| ¡dS)'Nu位置 (ENU, m):z  E: z+7.3frz  U: rDu 姿态 (deg):z   Heading: z+7.2fz   Pitch  : z   Roll   : z   Target : (z+6.2fz, r.u
控制量:z   Forward : z+6.3fz m/sz   Turn    : z rad/sz  PWM     : steer=z
 throttle=z   Freq    : z6.2fú Hzz   Stage   : u算法状态: z   XTE    : z mz degu 堆栈监测:z  z: stack=z  words heap=z Brár;)rÊr³r´rµÚ heading_degZ pitch_degZroll_degÚ target_eastÚ target_northrÉÚ forward_mpsÚ   turn_rateZ steering_pwmZ throttle_pwmÚfreq_hzÚstagerËZcross_track_errorZheading_error_degrÌÚvaluesr.rFÚstack_high_waterÚheap_free_bytesrùrrHÚ_update_scene_itemsÚ_refresh_stack_table)rrZ
info_linesr¬ZctrlÚstr{r8r8r9r)òsZ      ö 
ù    
ü ÿ zHitlDashboard._refresh_viewc Cs~|j t|jƒ¡t|j ¡ƒD],\}}|j |dt |j   ¡¡|j |dt t
|j ƒ¡¡|j |dt t
|j ƒ¡¡qdS)Nrr r) rúr5r-rÌrFrPZsetItemr
ZQTableWidgetItemrFr"rQrR)rrZrowÚstatusr8r8r9rT!s ýz"HitlDashboard._refresh_stack_tablec
Cs|jr/t ¡}d}|jdd…D]\}}| }|r"| ||¡d}q| ||¡q|j |¡|jrD|j}|j}|j    }|j
}|j   |||||d|d¡t  d|j¡}t  |¡}   t  |¡ }
|
} |   } d} d}d}d }d
}||   | ||
| f}|d |   ||d |
|f}|d |   ||d |
|f}|d | ||d | |f|d | ||d | |f|d | ||d | |f||d | ||d | |f|d | ||d | |f|d | ||d | |fg}t ¡}|j|d Ž|d d…D]}|j|ސq | ¡|j |¡|j}|j  |j||j ||d|d¡|jrF|j ||¡dSdSdS) NTi$úÿÿFrg€V@râg333333ë?gìQ¸…ë±?gÍÌÌÌÌÌÜ?gìQ¸…ëÑ?rr )rÈr rýr8r9rÿr:rÊr³r´rrZsetRectÚmathZradiansrIZcosZsinZ closeSubpathrrrrJrKrÍrär)rrÚtrailr=r?r@rr¬ÚsizeZ heading_radZdir_xZdir_yZperp_xZperp_yÚoffsetZ shaft_lengthZshaft_half_widthZ head_lengthZhead_half_widthrÜZ  shaft_endZtipr3Z
arrow_pathr5Z target_sizer8r8r9rS(s  "
 
 
þþþþþþþþþê 
ü²Mz!HitlDashboard._update_scene_items)
rÂrrÃrkrÄrrÅr»rÆr»)rÅr»rÆr»)rr)r³r/rr/)NN)rr)r3r)r2r")r|r}r~rsrÒrårérær   r rÓrÖr'r×rrr r
r3r6rrrØr@rÛr)rTrSr£r8r8r‹r9rÁ!s6
$*
 
 
 
 
      
!/rÁúargparse.NamespacecCsÚtjdd}|jdtdd|jdtdd|jdtd   d|jd
ttd d d |jdttddd |jdttddd |jdttdd |jdt   t
dd |jdt t dd |jddd|jdddd |  ¡S)!NuHITL ä»¿çœŸå™¨ GUI)Z descriptionz--uart2uSTM32 UART2 ä¸²å£å·)ÚdefaultÚhelpz--uart5uSTM32 UART5 ä¸²å£å·z--originu
GGA åŽŸç‚¹z--eastru 初始 E (m))Útyper\r]z--northr u 初始 N (m)z--upru 初始 U (m)z   --headingu初始航向 (deg)z
--gps-bauduUART2 æ³¢ç‰¹çއz
--log-bauduUART5 æ³¢ç‰¹çއz--pathu初始路径文件 (.json/.txt))r]z--no-guiZ
store_trueu"不启动 Qt GUI,仅打印数据)Úactionr]) ÚargparseZArgumentParserZ add_argumentÚDEFAULT_UART2_PORTÚDEFAULT_UART5_PORTrfr/Ú DEFAULT_ENUÚDEFAULT_HEADING_DEGrCÚDEFAULT_UART2_BAUDÚDEFAULT_UART5_BAUDÚ
parse_args)Zparserr8r8r9rg…s rgc
sÚtƒ}ttƒ}| ¡}| ¡}|r|n|j}|r(|d|d|df}|d}n |j|j|jf}|j }t
|j |j ||||j |jd}ttƒ}t||d} tƒ‰‡fdd„‰‡fd d
„| _‡fd d
„| _‡fd d
„| _‡fd d
„| _‡fdd
„| _g}
|jr z tt|jƒƒ}
WntyŸ} z td| ›ƒWYd} ~ nd} ~ wwtdus¨|jrzbzE|  ¡tdƒ  z ˆj j!dd\} } Wn
t j"yÈYq²w| dkrÒt| ƒn| dkrîtd| j#›d| j$d›d| j%d›d| j&d›d   ƒq³t'yûtdƒYnwW|  (¡| )¡tdƒdS|  (¡| )¡tdƒwtj* +¡p"t *g¡}t,|   ˆ|
|j |j ƒ}|jr8|j- .|j¡| /¡z| 0¡W|j1rJ| 2¡|  (¡| )¡tdƒdS|j1r`| 2¡|  (¡| )¡tdƒw)Nrr rrT)rrrôÚ initial_enuZinitial_heading_degZ gps_baudrateZ log_baudrate)Ú
run_loggercsˆ ||¡dSru©rw)rtr4)rÃr8r9rw³szmain.<locals>.publishcó
ˆd|ƒS)NrAr8©rVrjr8r9Ú<lambda>¶ó
zmain.<locals>.<lambda>crkr·r8rlrjr8r9rm·rncrk)NrBr8rlrjr8r9rm¸rncrk)NrCr8rlrjr8r9rm¹rncrk)NrDr8)Úlinerjr8r9rmºrnuARN] è·¯å¾„加载失败: uF[INFO] HITL ä»¿çœŸå™¨å·²å¯åЍ (无 GUI æ¨¡å¼)。按 Ctrl+C é€€å‡ºã€‚Tr)rÙrDrAz [CTRL] stage=z F=z+.2fz m/s T=z  rad/s freq=r"rHu
[INFO] ç”¨æˆ·ä¸­æ–­ã€‚u[INFO] ä»¿çœŸå™¨å·²åœæ­¢ã€‚)3rgr¤rÐr¾r²r½r³r´rµr¶rr/r2Zgps_baudZlog_baudrÚ RUN_LOG_PATHrrkZon_control_statusZon_pose_statusZon_state_statusZon_stack_statusZon_logr¥r:rr§Úprintr
Zno_guirÜrnr¯ryrOrLrMrNÚKeyboardInterruptr4Úcloser+ÚinstancerÁZ path_linerZshowZexec_rÎr3)r‰rÑZ saved_originZ
saved_poserôrhZinitial_headingZcfgriZsimrÄr&rtr4ZappZ  dashboardr8)rÃrwr9Úmain•s®
ù
 €ÿÿ
 
ÿÿþÿø ÿý
 
 ü
ruÚ__main__)rrrr)r2r"rr)r)r3rrBrCrr")rLr"rr")r2r"r]r"rr")rr[)@Ú__doc__Z
__future__rr`r(rWrnÚsysroZpathlibrÚtypingrrrrZPyQt5rr    r
r§Z serial.toolsr Z    protocolsr rrrrrÂrrrrarbrfrcrdrerfÚ__file__ZresolveÚparentZBASE_DIRrprZ with_suffixr-rÐr:rArKr\rjrkrrr¤Z QMainWindowrÁrgrur|Úexitr8r8r8r9Ú<module>sh   ÿ ÿ
 
 
 
 
!9-
hVÿ