yincheng.zhong
2025-12-04 f88f3da8f132cd1dd321dfc584a1fe68b6eb2138
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
o
C0i{Xã@s0dZddlZddlZddlZddlZddlmZddlmZm   Z   m
Z
ddl Z ddl Z ddlmZddlmZddlmZz.ddlZe ¡ZedkrQgd¢e jd <ned
kr]d d ge jd <nd dge jd <de jd<WnYej eeeƒjjƒ¡Gdd„dƒZGdd„dƒZdd„Ze dkr–eƒdSdS)ud
车辆运动模型校准数据分析工具
解析$CAL格式日志,提取差速运动模型参数
éN)ÚPath)ÚListÚDictÚTuple)Úoptimize)Ú defaultdictZWindows)zMicrosoft YaHeiZSimHeiZSimSunzfont.sans-serifZDarwinz PingFang SCzHeiti SCzWenQuanYi Micro HeizNoto Sans CJK SCFzaxes.unicode_minusc@seZdZdZdefdd„ZdS)ÚCalibrationDatau校准数据点ÚlinecCsN| ¡ d¡}t|ƒdkrtd|›ƒ‚t|dƒ|_t|dƒ|_|d|_t|dƒ|_t|dƒ|_  t
|d ƒ|_ t
|d
ƒ|_ t
|d ƒ|_ t
|d ƒ|_t
|d ƒ|_t
|dƒ|_t
|dƒd|_t
|dƒd|_t
|dƒd|_t
|dƒd|_t
|dƒd|_t
|dƒd|_d|_d|_d|_d|_|j |_dS)Nú,ézInvalid CAL line: ééééééééé    é
é é ç@@é éééég)ÚstripÚsplitÚlenÚ
ValueErrorÚintÚseqÚtime_msÚstateÚ throttle_pwmÚ steering_pwmÚfloatÚenu_xÚenu_yZenu_zÚhdgZpitchZrollZgxZgyÚgzÚaxZayÚazÚvelocityÚyaw_rateZlatZlonZalt)Úselfr  Úparts©r3úcalibration_analyzer.pyÚ__init__*s2 
 zCalibrationData.__init__N)Ú__name__Ú
__module__Ú __qualname__Ú__doc__Ústrr5r3r3r3r4r(src@sŽeZdZdZdefdd„Zdd„Zdd„Zd   efd
d „Z   d   efd d „Z
d   efdd„Z de fdd„Z de fdd„Zdededed   efdd„ZdS)ÚCalibrationAnalyzeru校准数据分析器Úlog_filecCs||_g|_ttƒ|_dS©N)r<ÚdatarÚlistÚ states_data)r1r<r3r3r4r5RszCalibrationAnalyzer.__init__c Cs:td|j›ƒt|jdddd8}|D]-}| d¡rAz t|ƒ}|j |¡Wqty@}z td|›ƒWYd}~qd}~wwqWdƒn1sLwY|jsXtd   ƒ‚td
t   |jƒ›d ƒtd t
d d„|jDƒƒd›dt d d„|jDƒƒd›ddt
dd„|jDƒƒd›dt dd„|jDƒƒd›dƒdS)u解析日志文件u解析日志文件: Úrúutf-8Úignore)ÚencodingÚerrorsz$CALu警告: è§£æžè¡Œå¤±è´¥: Nu未找到有效的$CAL数据u 成功解析 u  æ¡æ•°æ®ç‚¹uENU坐标范围: X=[csó|]}|jVqdSr=©r)©Ú.0Údr3r3r4Ú  <genexpr>kó€z0CalibrationAnalyzer.parse_log.<locals>.<genexpr>ú.2fz, z], zY=[csrFr=©r*rHr3r3r4rKlrLz] (m)) Úprintr<ÚopenÚ
startswithrr>ÚappendÚ   Exceptionr!r ÚminÚmax)r1Úfr    r>Úer3r3r4Ú parse_logWs*
 €þüÿÿ
64
ÿzCalibrationAnalyzer.parse_logc   Cs<tdƒt|jƒD]a\}}|dkrj|j|j|djd}|dkrj|j|j|dj}|j|j|dj}t |d|d¡||_|j |j|dj   }|dkrZ|d8}n|dkrb|d7}t 
|¡||_ q   |jD] }|j |j  |¡qntd   t|j ƒ›d
ƒ|j  ¡D]\}}td |›d t|ƒ›d ƒqŠdS)u9计算速度(ENU坐标已在单片机端计算完成)u计算速度和角速度...rr rr é´ihiLÿÿÿu数据分组完成,共 u
 ä¸ªçŠ¶æ€z  z: u ä¸ªç‚¹N)rOÚ  enumerater>r$r)r*ÚnpZsqrtr/r+Zdeg2radr0r@r%rRr Úitems) r1Úir>ZdtZdxZdyZdhdgr%Údlistr3r3r4Úcompute_enu_and_velocityns*
€
ÿz,CalibrationAnalyzer.compute_enu_and_velocityÚreturncsrtdƒi}gd¢}g}|D]B}||jvrP|j|‰ˆtˆƒdd…}|rPt dd„|Dƒ¡}t dd„|Dƒ¡}| ||f¡t|›d|d    ›d
|d ›d ƒqt|ƒdkr£t d d„|Dƒ¡}t dd„|Dƒ¡} dd„}
t |
|| ¡\} } | \} }dt | ƒt   |ƒd| d›d|d›dd„|Dƒdœ|d<td| d›d|d›ƒgd¢}i}|D]D}||jvrï|j|‰tˆƒdkrïdd„ˆDƒ}‡fdd„ˆDƒ}t|ƒdkrït 
||d¡}|d}t |ƒ||<t|›d|d ›d!ƒq«||d"<d#|jvr7|jd#‰tˆƒdkr7d$d„ˆDƒ}‡fd%d„ˆDƒ}t|ƒdkr7t 
||d¡}|d}t |ƒ|d&<td'|d ›d!ƒ|S)(u分析前向运动模型u!
=== åˆ†æžå‰å‘运动模型 ===©Z
CRUISE_LOWZ
CRUISE_MIDZ CRUISE_HIGHr NcSóg|]}|j‘qSr3©r&rHr3r3r4Ú
<listcomp>óz=CalibrationAnalyzer.analyze_forward_model.<locals>.<listcomp>cSrbr3©r/rHr3r3r4rdžrez: PWM=ú.0fu  , é€Ÿåº¦=rMz m/scSóg|]}|d‘qS©rr3©rIÚpr3r3r4rd¤ócSrh©r r3rjr3r3r4rd¥rlcSs||d|S)NéÜr3)ZpwmÚkÚbiasr3r3r4Ú linear_model¨sz?CalibrationAnalyzer.analyze_forward_model.<locals>.linear_modelÚlinearzv = z.6fz * (pwm - 1500) + cSs g|] \}}t|ƒt|ƒf‘qSr3©r()rIrkÚvr3r3r4rd³ó )ÚmodelrorpÚformulaÚpwm_velocity_pairsÚpwm_to_velocityuPWM-速度模型: v = )Ú    ACCEL_LOWÚ  ACCEL_MIDÚ
ACCEL_HIGHrcSrbr3rfrHr3r3r4rd¿recó g|] }|jˆdjd‘qS©rr©r$rH©r^r3r4rdÀrur ru: åŠ é€Ÿåº¦ = ú.3fu m/sÂ²Ú accelerationÚBRAKEcSrbr3rfrHr3r3r4rdÏrecr}r~rrHr€r3r4rdÐruÚ decelerationu制动减速度: ) rOr@r r[ÚmeanrRÚarrayrZ  curve_fitr(Zpolyfit)r1ÚresultsÚ cruise_statesrxr%Ú stable_dataZavg_pwmZavg_velÚpwmsÚvelsrqZpoptÚ_Z  k_forwardrpÚ accel_statesZ accel_resultsÚ
velocitiesÚtimesZcoeffsZaccelZdecelr3r€r4Úanalyze_forward_modelsj
 
€  
û
 
   € 
 z)CalibrationAnalyzer.analyze_forward_modelcCsœtdƒi}gd¢}g}|D]w}||jvr…|j|}t|ƒd}dt|ƒd}|||…}|r…t dd„|Dƒ¡} t dd„|Dƒ¡}
t dd„|Dƒ¡} |   d   } | | |
| f¡t|
ƒd
krft| |
ƒntd ƒ} t|›d | d ›d| d›d|
d›d| d›d| d›d ƒqt|ƒdkrÌt dd„|Dƒ¡}t dd„|Dƒ¡}t    ||¡t  |d¡}dt|ƒd|d›ddd„|Dƒdœ|d<td |d›dƒ|S)!u分析转向模型u
=== åˆ†æžè½¬å‘模型 ===©ZTURN_LEFT_LIGHTZTURN_RIGHT_LIGHTZTURN_LEFT_HEAVYZTURN_RIGHT_HEAVYrrcSrbr3©r'rHr3r3r4rdírez>CalibrationAnalyzer.analyze_steering_model.<locals>.<listcomp>cSrbr3©r0rHr3r3r4rdîrecSrbr3rfrHr3r3r4rdïrerng{®Gáz„?Úinfu : èˆµæœºPWM=rgú (z+.0fu ), è§’速度=ru rad/s, é€Ÿåº¦=rMu m/s, è½¬å‘半径=z mr cSrhrir3rjr3r3r4rdýrlcSrhrmr3rjr3r3r4rdþrlrruω = ú.8fz * (steering_pwm - 1500)cSs(g|]\}}}t|ƒt|ƒt|ƒf‘qSr3rs)rIÚoÚyrtr3r3r4rds()rvrorwr>Úpwm_to_yaw_rateu转向模型: Ï‰ = )
rOr@r r[r…rRÚabsr(r†Úsum)r1r‡Ú turn_statesZpwm_yawrate_pairsr%r^Ú   start_idxÚend_idxr‰Zavg_steering_pwmZ avg_yaw_rateZ avg_velocityZsteering_offsetZturning_radiusZoffsetsÚ    yaw_ratesZ
k_steeringr3r3r4Úanalyze_steering_modelÚsH
 
   ÿÿ
þ€   
üz*CalibrationAnalyzer.analyze_steering_modelcCsŒtdƒi}d|jvrDd|jvrD|jdd}|jdd}d}|jdD]}|j|krC|j|j}t|ƒ|d<td|›d    ƒ|Sq%|S)
u分析响应延迟u
=== åˆ†æžå“åº”延迟 ===ZWARMUPrzéÿÿÿÿr皙™™™™¹?Úthrottle_response_delay_msu油门响应延迟: z ms)rOr@r/r$r()r1r‡Z warmup_lastZ accel_firstZthreshold_velocityrJZdelay_msr3r3r4Úanalyze_delays s
  úz"CalibrationAnalyzer.analyze_delaysÚ
output_dirc!
sÈtdƒ|jdddtjdd\}}‡fdd„ˆjDƒ}dd„ˆjDƒ}d d„ˆjDƒ}|j||d
d d d |jddd|jd ddd|jddd|j   ddd| 
¡}|j||ddddd|jdddd|jdddˆjdj }|d} t t |ˆjƒƒD]5\}
\} } | j |ks˜|
tˆjƒdkr¹|j|   | ddd |j|   | d!t|ƒd"|d#d$dd%| j }| }   q„tjd&d'd| ¡tj|d(d)d*td+|d(›ƒt ¡tjd,d\}}d-d„ˆjDƒ} d.d„ˆjDƒ}i}d}tj t ddd/¡¡}ˆj ¡D]}||d/||<|d7}qˆj ¡D]!\}‰d0d„ˆDƒ}d1d„ˆDƒ}|j||||d!|d2d!d3q|jd4dd|jd5dd|jd6d'd|j ddd| d7¡|jd$d8d9t ¡tj|d:d)d*td+|d:›ƒt ¡tjdd!dd\}\}}gd;¢}|D]0}|ˆjvrÁˆj|‰ˆtˆƒd!d<…}d=d„|Dƒ}d>d„|Dƒ}|j |||d?d@dAq’|jddd|jd dd|jdBd'd|j   ddd| ¡gdC¢}|D]:}|ˆjvr"ˆj|‰tˆƒdD}dEtˆƒdD}ˆ||…}dFd„|Dƒ}dGd„|Dƒ}|j |||d?d@dAqé|j!ddHdId?dJ|j"ddHdId?dJ|jdKdd|jdLdd|jdMd'd|j   ddd| ¡t ¡tj|dNd)d*td+|dN›ƒt ¡tjdOd\}}gdP¢}|D])}|ˆjvr¦ˆj|‰‡fdQd„ˆDƒ} dRd„ˆDƒ}|j| |d2dE|d!dSq~|jdTdd|jd dd|jdUd'd|j ddd| ¡t ¡tj|dVd)d*td+|dV›ƒt ¡d<S)Wu生成可视化图表u
=== ç”Ÿæˆå¯è§†åŒ–图表 ===T)ÚparentsÚexist_ok)rr)Zfigsizecs"g|] }|jˆjdjd‘qSr~)r$r>rH)r1r3r4rd+s"z6CalibrationAnalyzer.generate_plots.<locals>.<listcomp>cSrbr3rfrHr3r3r4rd,recSrbr3rcrHr3r3r4rd-rezb-gø?u 速度 (m/s))Ú  linewidthÚlabelu 时间 (秒)r)ÚfontsizeÚb)rªÚcolorr˜)ÚaxisZ
labelcolorg333333Ó?)Úalphazr--r g333333ã?u    æ²¹é—¨PWM)r¨r®r©rArr¢Zgray)r®r¬r gÍÌÌÌÌÌì?Úcenterr)ZharªZrotationu!速度与油门PWM随时间变化rzvelocity_time.pngé–)Zdpiu保存: )rrcSrbr3rGrHr3r3r4rdNrecSrbr3rNrHr3r3r4rdOrercSrbr3rGrHr3r3r4rd[recSrbr3rNrHr3r3r4rd\rer—)r¬r¨r©ÚmarkerÚ
markersizeu
东向 (m)u
北向 (m)u车辆运动轨迹 (ENU坐标)ZequalZbest)rªÚlocztrajectory.pngraNcSrbr3rcrHr3r3r4rdurecSrbr3rfrHr3r3r4rdvregà?é)r©r®ÚsuPWM-速度关系r‘rrcSsg|]}|jd‘qS)rnr’rHr3r3r4rd‡scSrbr3r“rHr3r3r4rdˆreroz--)r¬Z linestyler¨u舵机PWM偏移 (相对1500)u角速度 (rad/s)u舵机PWM-角速度关系zpwm_relationships.png)rr)rzr{r|rƒcr}r~rrHr€r3r4rdŸrucSrbr3rfrHr3r3r4rd re)r±r²r©r¨u相对时间 (秒)u加速/制动特性zacceleration.png)#rOÚmkdirÚpltZsubplotsr>ZplotZ
set_xlabelZ
set_ylabelZ tick_paramsZgridZtwinxr%rZÚzipr ZaxvspanÚtextrUÚtitleZ tight_layoutZsavefigÚcloseÚcmZtab10r[Zlinspacer@Úkeysr\Z    set_titler­ZlegendZscatterZaxhlineZaxvline)!r1r¥Zfigr-rrŽZ  throttlesZax2Z current_stateZstate_start_timer]ÚtrJZxsZysZ state_colorsZ color_idxZ colors_listr%Zxs_stateZys_stateZax1rˆr‰rŠr‹rœrržZsteering_offsetsrŸrZ    times_relr3)r^r1r4Úgenerate_plots#sÞ ÿ€ 
ÿ
 
€ 
  € 
€ z"CalibrationAnalyzer.generate_plotsÚ output_filec   Cstdƒ| ¡}| ¡}| ¡}t|jƒt|jƒ|jdj|jdjdt dd„|jDƒƒt
dd„|jDƒƒt   dd„|jDƒƒt
d   d„|jDƒƒd
d œd d „|j   ¡Dƒdœ|||dœ|  |||¡dœ}t|ddd}tj||dddWdƒn1s€wYtd|›ƒ|S)u生成JSON参数报告u
=== ç”ŸæˆJSON参数报告 ===r¡rrcsrFr=rGrHr3r3r4rK¼rLz;CalibrationAnalyzer.generate_json_report.<locals>.<genexpr>csrFr=rGrHr3r3r4rK½rLcsrFr=rNrHr3r3r4rK¾rLcsrFr=rNrHr3r3r4rK¿rLz;ENU coordinates computed onboard, relative to first RTK fix)Zx_minZx_maxZy_minZy_maxZnotecSsi|]  \}}|t|ƒ“qSr3)r )rIr%r^r3r3r4Ú
<dictcomp>Âsz<CalibrationAnalyzer.generate_json_report.<locals>.<dictcomp>)r<Z total_samplesZduration_secondsZ    enu_rangeZstates)Ú forward_modelÚsteering_modelÚdelays)ZmetadataZdifferential_drive_modelÚrecommended_configÚwrB)rDr F)ÚindentZ ensure_asciiNuJSON报告已保存: )rOrr r¤r:r<r r>r$rTrUr@r\Ú_generate_recommended_configrPÚjsonÚdump)r1rÀrÂrÃrÄÚreportrVr3r3r4Úgenerate_json_report®s4ûõý íÿz(CalibrationAnalyzer.generate_json_reportrÂrÃrÄcCs i}d|vr|dd|d<|dd|d<d|vr"|dd|d<d|vr8|dr2t|d ¡ƒnd    }||d
<d |vrDt|d ƒ|d <d |vrN|d |d<|S)u生成推荐的配置参数ryroZMC_CFG_FORWARD_KrpZMC_CFG_FORWARD_BIASr™ZMC_CFG_STEERING_Kr‚gð?ZMC_CFG_MAX_ACCELERATIONr„ZMC_CFG_MAX_DECELERATIONr£ZMC_CFG_RESPONSE_DELAY_MS)rUÚvaluesrš)r1rÂrÃrÄZconfigZ   max_accelr3r3r4rÈÓs z0CalibrationAnalyzer._generate_recommended_configN)r6r7r8r9r:r5rXr_rrr r¤rr¿rÌrÈr3r3r3r4r;OsM3 %r;c CsVtjdd}|jdtdd|jddtdd   d
| ¡}t|jƒ}| ¡s1td |›ƒt    
d ¡t|j ƒ}td ƒtdƒtd ƒt t|ƒƒ}|  ¡| ¡| |¡|d}| |¡}tdƒtdƒtd ƒ|d ¡D]#\}}t|tƒr‡td|d›d|d›dƒqptd|d›d|›dƒqptdƒtdƒtd| ¡›ƒtd ƒdS)Nu*车辆运动模型校准数据分析工具)Ú descriptionr<u&校准日志文件路径 (.log或.txt))ÚtypeÚhelpz-oz--outputZcalibration_resultsu*输出目录 (默认: calibration_results))rÏÚdefaultrÐu错误: æ—¥å¿—文件不存在: r z<============================================================zcalibration_parameters.jsonz=
============================================================u4推荐的配置参数 (可复制到motion_config.h):rÅz#define z<35r•r–zf)ú)u分析完成!u输出目录: )ÚargparseÚArgumentParserÚ add_argumentr:Ú
parse_argsrr<ÚexistsrOÚsysÚexitÚoutputr;rXr_r¿rÌr\Ú
isinstancer(Zabsolute)  ÚparserÚargsr<r¥ZanalyzerZ json_filerËÚkeyÚvaluer3r3r4Úmainïs>  ÿ
 
 
 
 
 
 ràÚ__main__)!r9rÓrÉÚrerØZpathlibrÚtypingrrrZnumpyr[Z
matplotlibZmatplotlib.pyplotZpyplotr·ZscipyrÚ collectionsrÚplatformÚsystemZrcParamsÚpathrRr:Ú__file__Úparentrr;ràr6r3r3r3r4Ú<module>sB    '#3
ÿ