yincheng.zhong
2025-12-10 8d0d8dec18cc9170f3fb82a4dba18160dd8e5233
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
o
i4iŽ5ã@s’dZddlmZddlZddlZddlmZddlmZmZddl m
Z
m Z m Z djdkdd„Z dZdZdZdZdZdldd„Zdmdd„Zdnd#d$„Zdnd%d&„Zdod'd(„Zdod)d*„Zdpd+d,„Zdqd=d>„Z  ?drdsdCdD„ZdtdEdF„ZdudIdJ„ZeGdKdL„dLƒƒZeGdMdN„dNƒƒZeGdOdP„dPƒƒZ eGdQdR„dRƒƒZ!eGdSdT„dTƒƒZ"eGdUdV„dVƒƒZ#GdWdX„dXƒZ$dvd[d\„Z%dwd_d`„Z&dxdbdc„Z'dydedf„Z(dzdhdi„Z)dS){uŠ
与 STM32H7 äº¤äº’的协议封装:
- æž„造 IM23A "fmin"/"fmim" ä¼ æ„Ÿå™¨å¸§
- è§£æž PythonLink æŽ§åˆ¶å¸§
- è§£æž ASCII çŠ¶æ€æŠ¥æ–‡
é)Ú annotationsN)Ú    dataclass)ÚdatetimeÚtimezone)ÚCallableÚOptionalÚTupleéÜéôçø?ÚvalueÚintÚcenterÚspanÚ  max_speedÚfloatÚreturncCsd|dkrd}|dkr d}d|}|dkr"d}t|ƒdkrdS||Sd}t|ƒd   kr,dS||}|S)
u×
    å°† PWM ä¿¡å·è½¬æ¢ä¸ºçº¿é€Ÿåº¦æˆ–角速度。
    åŸºäºŽ motion_config.h ä¸­çš„æ¨¡åž‹å‚数:
    Forward: v = K_fwd * (1500 - pwm) + Bias (但模拟器这里主要是为了闭环,不需要完美匹配Bias,只要方向对)
             1000 PWM = 0.56 m/s
             1500 PWM = 0.0 m/s
             2000 PWM = -0.2 m/s (backward)
    Turn:    w = K_turn * (1500 - pwm)
             1000 PWM = 63 deg/s (Left)
             2000 PWM = -61.5 deg/s (Right)
    ièiÐr g$@gú~j¼t“X?é(çg¸…ëQ¸¾?é
)Úabs)r rrrÚdeltaZk_linZ k_ang_degZdeg_s©rú1E:\GIT\Lawnmower_STM32H7\python\hitl\protocols.pyÚ_pwm_to_velocitys  rédé4sfminsfmimsedÚdtrcCs$|jdur |jtjdS| tj¡S)N)Útzinfo)rÚreplacerÚutcZ
astimezone)rrrrÚ _ensure_utcHs
 r!Úsentence_without_starÚstrcCs*d}|dd…D]}|t|ƒN}q|d›S)NréZ02X)Úord)r"ZcsÚchrrrÚ nmea_checksumNsr'ÚbufÚ    bytearrayÚNonecCó| t dt|ƒ¡¡dS)Nz<d©ÚextendÚstructÚpackr©r(r rrrÚ _write_doubleUór1cCr+)Nz<fr,r0rrrÚ _write_floatYr2r3cCr+)Nz<I©r-r.r/r r0rrrÚ
_write_u32]r2r5cCr+)Nú<Hr4r0rrrÚ
_write_u16ar2r7cCs,t|ƒd@}| t d|¡¡| t¡dS)Néÿÿr6)Úsumr-r.r/Ú
IM23A_TAIL)r(ÚchecksumrrrÚ _append_tailes r<Ú   timestampÚlat_degÚlon_degÚalt_mÚeast_velÚ   north_velÚup_velÚ heading_radÚ pitch_degÚroll_degÚ
accel_biasúTuple[float, float, float]Ú gyro_biasÚ temperature_cÚ status_flagsÚbytescCsôttƒ}t|t|ƒƒt||ƒt||ƒt||ƒt||ƒt||ƒt|| ƒt||    ƒt||ƒt||ƒt|dƒt||
dƒt||
dƒt||
dƒt|| dƒt|| dƒt|| dƒt|| ƒt|| ƒt|ƒt|ƒS)Ng{®Gáz”?rr$é)r)ÚIM23A_NAV_HEADERr1Ú_seconds_of_dayr3r5r<rL)r=r>r?r@rArBrCrDrErFrGrIrJrKr(rrrÚbuild_im23a_nav_frameks,
 
 
 
 
 
 
 
 
 
 
rP©rrrÚaccel_gÚ
gyro_deg_sÚreservescCs¤ttƒ}t|t|ƒƒt||dƒt||dƒt||dƒt||dƒt||dƒt||dƒt||dƒt||dƒt||dƒt|ƒt|ƒS)Nrr$rM)r)ÚIM23A_IMU_HEADERr1rOr3r<rL)r=rRrSrTr(rrrÚbuild_im23a_imu_frame“srVcCs,t|ƒ}|jd|jd|j|jdS)Nié<g€„.A)r!ZhourZminuteÚsecondZ microsecond)rr rrrrO¨sÿþýÿrOÚpayloadúTuple[float, float]cCsxt|ƒdkrt d|¡\}}||fSt|ƒdkr3t d|¡\}}t|dd}t t|dd¡}||fStdt|ƒ›ƒ‚)  Néz<fféz<HHgð?)rg€V@u ä¸æ”¯æŒçš„æŽ§åˆ¶è´Ÿè½½é•¿åº¦: )Úlenr.ÚunpackrÚmathÚradiansÚ
ValueError)rYÚforwardÚturnÚ steering_pwmÚ throttle_pwmrrrÚ_decode_payload²s   rfc@seZdZUded<ded<dS)ÚPythonLinkFramerrbrcN©Ú__name__Ú
__module__Ú __qualname__Ú__annotations__rrrrrg¿ó
 rgc@seZdZUded<ded<dS)ÚPythonAsciiMessager#Útagz list[str]ÚfieldsNrhrrrrrnÅrmrnc@s~eZdZUded<ded<ded<ded<ded<ded <ded
<ded <ded <ded <ded<ded<ded<ded<dS)Ú ControlStatusrÚ forward_mpsÚ  turn_rateÚfreq_hzr rdrer#ÚstageÚ timestamp_msÚeastÚnorthÚupÚ heading_degÚtarget_heading_degÚ target_eastÚ target_northNrhrrrrrqËs
 rqc@sVeZdZUded<ded<ded<ded<ded<ded<ded<ded <ded
<d S) Ú
PoseStatusrrwrxryrzrErFr|r}rvNrhrrrrr~Ýs
 r~c@s.eZdZUded<ded<ded<ded<dS)Ú StateStatusr#rurÚcross_track_errorÚheading_error_degrvNrhrrrrrês
 
 rc@s&eZdZUded<ded<ded<dS)Ú StackStatusr#Ú task_namer Ústack_high_waterÚheap_free_bytesNrhrrrrr‚òs
 r‚c@sNeZdZdZdZdZdZddd„Zdd d „Zddd„Z ddd„Z
ddd„Z dS)ÚPythonLinkDecoderu>
    è§£æž PythonLink æŽ§åˆ¶å¸§ (0xAA 0x55 ... 0D 0A)。
    sªUs
éÚon_frameú!Callable[[PythonLinkFrame], None]cCstƒ|_||_dS©N)r)Ú_bufferÚ  _on_frame)ÚselfrˆrrrÚ__init__s
zPythonLinkDecoder.__init__ÚdatarLcCsÌ|sdS|j |¡  | ¡}|dkr|j ¡dS|dkr$|jd|…=t|jƒdkr-dS| ¡}|dus<t|jƒ|kr>dSt|jd|…ƒ}|jd|…=z| |¡}|rZ| |¡Wn  t ydYq
wq )NTré  )
r‹r-Ú _find_headerÚclearr]Ú_expected_frame_lengthrLÚ _parse_framerŒÚ   Exception)rrÚstartZ   frame_lenÚframeÚparsedrrrÚfeeds4 
 
 
€ þîzPythonLinkDecoder.feedrr cCst|jƒ}| |j¡}|SrŠ)rLr‹ÚfindÚ FRAME_HEADER)rrÚidxrrrr‘ s
 zPythonLinkDecoder._find_headerú Optional[int]cCs8t|jƒdkr dSt |jdd…d¡}d|ddS)NééÚlittlerM)r]r‹r Ú
from_bytes)rÚ payload_lenrrrr“%sz(PythonLinkDecoder._expected_frame_lengthr—úOptional[PythonLinkFrame]c Cs²| |j¡r | |j¡sdS|d}||jkrdSt |dd…d¡}d}||}|||…}t |||d…d¡}t|d|…ƒd@}||krMtdƒ‚t  |ƒ\} }
t
|   |
dS)NrMrŸržr r8u校验和不匹配)rbrc) Ú
startswithr›ÚendswithÚ FRAME_FOOTERÚ TYPE_CONTROLr r¡r9rarfrg) rr—Z
frame_typer¢Z payload_startZ payload_endrYZchecksum_receivedZ checksum_calcrbrcrrrr”+s
   zPythonLinkDecoder._parse_frameN)rˆr‰)rrL)rr )rr)r—rLrr£) rirjrkÚ__doc__r›r¦r§rŽr™r‘r“r”rrrrr†ùs
 
 
 
r†ÚlineúOptional[PythonAsciiMessage]c Csà|sdS| ¡}| d¡sdSd}t|ƒ}| d¡}|dkr*|}||d|d…}|d|…}d}|D]}|t|ƒN}q4|rWzt|dƒ}Wn
tyPYdSw||krWdS| d   ¡}|s`dS|d} |dd…}
t| |
d
S) Nú$ÚÚ*éÿÿÿÿr$rŸrr‡ú,)rorp)    Ústripr¤r]ršr%r raÚsplitrn) r©Z checksum_strZdata_endZstar_idxrYZcalcr&ZprovidedÚpartsrorprrrÚparse_ascii_message=s:
 
  ÿ
  r³ÚmsgúOptional[ControlStatus]cCs&|j ¡dkst|jƒdkrdSzft|jdƒ}t|jdƒ}t|jdƒ}tt|jdƒƒ}tt|jdƒƒ}|jd}t|jd   ƒ}t|jd
ƒ}t|jd ƒ} t|jd ƒ}
t|jd ƒ} t|jdƒ} t|jdƒ} t|jdƒ}Wn
ty€YdSwt||||||||| |
| | | |dS)NZCTRLérr$rMrŸr\ržéér[rré é é )rrrsrtrdrerurvrwrxryrzr{r|r})roÚupperr]rprr rarq)r´rbrcZfreqZsteeringZthrottlerur=rwrxryÚheadingZtarget_headingÚtarget_eÚtarget_nrrrÚdecode_control_status\sH
 ÿòrÀúOptional[PoseStatus]c
Csä|j ¡dkst|jƒdkrdSzJt|jdƒ}t|jdƒ}t|jdƒ}t|jdƒ}t|jdƒ}t|jdƒ}t|jd   ƒ}t|jd
ƒ}t|jƒdkrWt|jdƒnd }   Wn
tydYdSwt||||||||| d  S) NZPOSEr[rr$rMrŸr\ržr·r¸r)  rwrxryrzrErFr|r}rv)ror¼r]rprrar~)
r´rwrxryr½ZpitchZrollr¾r¿r=rrrÚdecode_pose_status‚s4$ ÿ÷rÂúOptional[StateStatus]cCs|j ¡dkst|jƒdkrdS|jd}z t|jdƒ}t|jdƒ}t|jƒdkr2t|jdƒnd}Wn
ty?YdSwt||||dS)NZSTATErŸrr$rMr)rur€rrv)ror¼r]rprrar)r´ruZxteZ heading_errr=rrrÚdecode_state_statusžs 
$ ÿürÄúOptional[StackStatus]cCsv|j ¡dkst|jƒdkrdS|jd}ztt|jdƒƒ}tt|jdƒƒ}Wn
ty3YdSwt|||dS)NZSTACKrŸrr$rM)rƒr„r…)ror¼r]rpr rrar‚)r´ZtaskZstack_hwZ heap_freerrrÚdecode_stack_status°s
 ÿþrÆ)r   r
r )
r r rr rr rrrr)rrrr)r"r#rr#)r(r)r rrr*)r(r)r r rr*)r(r)rr*)r=rr>rr?rr@rrArrBrrCrrDrrErrFrrGrHrIrHrJrrKr rrL)rQ)
r=rrRrHrSrHrTrHrrL)rrrr)rYrLrrZ)r©r#rrª)r´rnrrµ)r´rnrrÁ)r´rnrrÃ)r´rnrrÅ)*r¨Ú
__future__rr.r_Z dataclassesrrrÚtypingrrrrZ IM23A_NAV_LENZ IM23A_IMU_LENrNrUr:r!r'r1r3r5r7r<rPrVrOrfrgrnrqr~rr‚r†r³rÀrÂrÄrÆrrrrÚ<module>sV   2
 
 
 
 
 
 
 
, ü
 
 
 
D
 
&