From 085b2032afb74c410e40851905328ed8de349573 Mon Sep 17 00:00:00 2001 From: zhouyr9 Date: Thu, 15 Jan 2026 10:26:20 +0800 Subject: [PATCH] update --- data/KSP_data/log_book.xlsx | Bin 26911 -> 26884 bytes src/KSP_tools/krpc_explore.py | 130 +++++++++++++++++++--------------- 2 files changed, 74 insertions(+), 56 deletions(-) diff --git a/data/KSP_data/log_book.xlsx b/data/KSP_data/log_book.xlsx index 1f24825d31a49fbaf3aea2adfb482717c5c30c86..663bc2142280d1c0f5c77c644167453db898c746 100644 GIT binary patch delta 14157 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

sjG2ofHadpD(413Dq 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 delta 14257 zcmZ9zWmsHGvo?&oTX1)GcY+3Y4eqYN7jD6a0Ko|s+#N!24Fm}8kiiLV!QNr-=R42& z&iq(cubS%as=KPX)>YjdF$0}H16_BEfQ&}0oLdG91r?l%NDOQXVm$@VJVjUO*h`ee z%8W>B>qApHcw1xQx2%DfsX&C=juv~QTAI~2JsW~p#A9o*M{=73H@|;mf8GnNoU%?Q zp3){zJ|pkT;OAycdOLB~5&dmarZGHT8k-!X?Y1n#(IlDw(DUrkjDKOzGysBz>e?@S zTfW*_MXh8f7YDpc(ZUd6q2l>s#=M}L@=j@+x=`D?9K6_KYaQXz(#-D zG|H$af~BbSB_ueduIuY`!#-(S{79LKiyZYhw8f}q>3e2%E2|WsaaTIk8pS-L%{dK6 zoIJ1|JzOgwtQuF3=wmVCfRYJJQ!`BvjzkMve3GVm-Y&2yO1qGH_4$C9Twn1tx2g*^ z{T3zaBwwzdvRa8noc1)=?gUl<@w!%*wd7XhfS7iwCs|pKSyoO7g)i~*7kA8{u=2&3 zBKY>vXp;24npt}h@`k^NLTYr%1vlZ^8l$maXnOG#oYkIet#!IR4XmYa>4xM=#qjQuiVj&-OYT5&hwdsupJ+`Osb;ph=;K76`Lo$8qN6BB z%m2Pa(<&D8SV$50D1Vr8<$;MPF&%fQD2ARA=w&Momdh)|Qvc%%sJc?lwl#02T%B(R zU@gDrBu7&YSS9=Xr;Ud@+PT$nIlNGWczMz;UPJ<*Bs{oJp(Ocq>{wM8FcKM-=cJ-w zaB8-)QFr%g=tBVT`R}vM*W2Lz5O0A_TQ8%o3MsXOi_mj@r)K>w_P5uXQ$Nxd!tPs^ zgU#xd{J+kf=kzc0Ss%d(iV&_CKFv(8`tQeR)$QQ*Ss!l2faWN5yj3an*3jRVKYg%U zo07x>U>F|3ObQpAJ8A3YkKi@{MppcB z8zPD^U;Kl1qPxJgh811p)W2p4qfhq%7ej8x=j&AXbME!Kgf@TMhhzP@m9($u zS7d7*745adZax0`#wP?fvO*3N&n5*jOFd7fQ9O4PDKk6?{SQ3o@}~5cqn}$^ckZ{T zs6`iiIf)R$FHaCZd==}-zy=prAQ*KTz_RWOAXfx67^H1=Xv`ljfd@gnTE7p%fZT%T#Yzy9c=i{HF^UeNu0OQqERGRv^$S#temYl~^#^lT>=m4HST+_6!s9(U*fzLZf7x%Li zrV_wk6RI9&D}m&Qfe0N%Y!7BmY^?zn)2CvQ}*he*Gj^^ z`(JUu<-*Gt-!L3nzbPSNuIYVw)RSN7y)}0`>h(JNSxz@r>D@%s#oC``)KeNBUBj;N zt)}Q?)0!~w%I9xUC%Sxl>+eUS^10KS>0ZeA2vcd%M|QvihlEeQd5$FCr%PqfW z*=4_HMU%5@k=GRc=m}g2OfQb{5cL?Jovc-}?D))txiIZ>MpdgbztzsEpC^SsNA> z%zv!OB+Gx5*%>GJ zABJ7iyeMTOY))VOU*Z@dv3&BUx>_WYgu`E2Fx{D8KZt6A`7~< zce}QQf3L?$n%o(2z{9r_O(uEdWP9eUxZPAEEw*ggZ^{WxCi0V5lgxNRU@|05V%nFx zA5Clt7ck9agh7ya`rWT5A>iWnqR%w7G;JfycQ2}g?UQlH;J*LtQ>U5N2#JVFH3E)^ z?w6~*>r)h#LAVZbRJJ(MH(thwA-8B7ZoAOk@F)NL#SK_85gODBpIt4ol>fRn_)-E|uC$ z*xc`%)^jsN!5{h2EHDU|0_~fs_mdF3FzLdmze@%I z<)xX~S>|QNw(=`WXl0jiA>M*dY{#SDQ%=+Nj_r7|c`rWhi5wfA)oLd2=RN z`Vjb@;2b~YcOw4)U4TUXj*6l4g;TpZ4QKf2{mk`YoNBjJ=_xCWQ-^cH`=R5UV%-q% zQ?)42UOqcFHJS$k=U|6;!kl%HsI5G((i{Cn3i}1H$Mb6BO}Ho_b1vf{J!I))PY4bp zLf~Iz+*_Wu;kW)ujR)OW|4h&d4>l&DFAX57K!VucACJ=0H)_$AK54eF%dvmJi=&f4 zj1k7CJTEHoK&~hUGGnBEG>Q~rg zI#)70jj9W>VCDI*AIS7@-G# zi0oLZw=aC$M;6c$mJ<%j*dKk|LJu@#H1+R0fs<2$5Hgs$BGpjAVrp%<-`$$sq}((D z?|lnhTG_!`vth$uEXH8Z4XNfq#u5R>gJP{NXMdR3(oDs+)YzJ>$;x>B=Z|bXq=3CC zhgs?Sd0ZEUI?TW`_G#B&v)${eAs4mwy$#<+dw$@~;D>$mcs_Q4`CUm8B;_d<;AmgG zv(eo-?b?dFDe54dv^=9Qs)uAJ*|Vk^a+&|ZY==E5mocceik5V5%3j zvrV}T%l+0BWViJhv3`3$68=JIr%XWYuL^r9A`h+Uc3YVs8|DIxBGo?IllKN9%C?g_ z8^gt5Vn72;dyGV_1f8&Hp+x7$ir8yGIYi2)t6W9qm$I40WN z>2nylirm#ewb%p)LB-s>+_VHcFsQ`CKOd zSN_(7i3V`fiNd5@g z`_z2D&}QJ_ve1p{u;R8sSt}``p{0OMF=bifD*cYA>pd_gQ-w>O-r`(Ecjcb^lW+p= ziu}a|#yHhq>{@X_I6=*&mH~J>Uq~LlqLWr#3{^PDzxqG#N+)`d>CC1@T*A^|}oD{=?oVVFUaJ;_Rv_?9!6Tjv6Bf>0W?1Vns zC#+iLGgiD)!Mt+%F`N+vCl#S$s*3b-kbLy7jUwX}XX(1e6PpG@0ZYKK5jX5ysff>0 z^90UlJR9qHtiRu?P_>Tjf*wv}Tx7zp0oRGmRhly|zPaBjL6y_iFBQCuNHc7~Erz$c z;WBZG5_IT}Z!~N%>6>e2^tM|!GT_jim7d2lOlaJ5N-)t%)gsqy@?sS?f#x&oD00i- zLd!Jtc#Yx3@ADx!2CmL!SVPP!p(;bP{OlqREEqKgetpyIpAvZJH(sk2s2y16&y}FO@>k23b%Bi_0v~`V?197AYIjRe(*oR z4BDYwr;8KjpH^IQz(VYg8vSRO#WxE)K25Xwr8cVOG~Q+<6>gnjWGoN=0aqhlJ5DaTdk^7Y^1bRFKyoX8eX5)_d{R zP5gOSe!-TzqK{7ta9AFzY$w98EQqnF(_$)FEf>2%2D}l{$)vtX9 z>%>tns$H};XiGLG^N^twJzr62sr!rA0e&6Gi10a7>E4jjgXyRta!w+d8hFJLcLg9;f9$^RGMF7ruDzV0KpVC*X`9-VpY$fgo0Fy2J7UI8E3Ku z?5&>WNg5koXY!b4gl9-8=7h z$W8qF<$KvJ30OKOX?()V-`_=kae4QprX1=-isK#-G8)&~#^bSLI|;Le)sE!y^7Z&C z{799P)40wTk&45LPtWkcdoH2k1g!lON>YjB=YS}=L0n^)!Ek`! zWtS)dfi&;RG0tnkfZRjB0?V)n35GO1mZ&pRum5aAkqP3XT&|dq@G8Ly%LSkC2}(?o zMuQ`=yDTvKC5FvYI`t-4A}~mgQS4s+`k&XmR9+3C_DeMRygHBCBG+_$xlv?%kP(>6 znDDuf?q~pr&jpXJ+3;FUUetA0ObAvygNu{mC>MpBmFjULfh{lbY_Q5#7&bNLgv~RF z51M0LV5(?Y8`3Bsu|GAXpE~RxsV;fsFg{+nPH0Sos}|RK$CDCZlj^(>b;PS8K@f$b z7c?L3-eD+2iT6ttiwI-7(I2`g(COfh5Z(n?)jECO`$dYHBf)#7M>~r}Vi4=TL*$NxWqv@<kfz7~V3R$= z9u$QT>)lJP+#!(xX*Os7jt+G)zuOaJC0cnm7T8C|kVQw3>9VjWwoWB&so zP+yxr@$bm`#K$`g5nB++MtTcy|3$dI@%^Vjy0{sL@`2&m?*Gb?=-XUe_ZOl|D(rT= z*1t4yZ|CVEGk`O$Cjjq1NTVGFhS(*2_dZ_$Ua{zCvV zox*?{#Eet!`rIwrmDcF5el(icuQ~tE95_4b_>TY1QEKxg?jIUaXUbed2a!^l6dOZF9D zz{QAqu?u_H3A9sZb(~EHkqIJ_)p0DO^(qssUjHEI59+kf&Y|eAITIV&t0O2RxeS#m zlCtI%e^f^I=t}^PlGFz1;3f8Z^i^-Njj;TF|2ez9v5ThS8FkoPXlsgS+!Pa8N6O&+ z^tX3| zE)`@Qbl3l_wg<;m>qeT6>!RH8cFWWd!SmxDt6JFmVwA}X(r9awBH+xl;M3%Ib~dhy zcD>vj5K15f$(t+23yhENevBPJ)>q=lmp%xjZ5o3FIxmqsbvbS;*Aqy+8S zF|U4>GCX8AS8wc&wBomoVE5JQzHprzp0g-1GWTN8CECm zAgg%aH3VB-H|?i4{{jz5xSC^EL_zMP1P8hJ@LCXAZddAjR~irkTVGYU)52fD`Hv1X z`u-^h&zUYSvV<7_6ZvlpXFT!j8(N}F>J z!sm8z*3{Z<`f{MCf~A^1PDYg}UjsaM|HCxWa-i`W0!JaBOF`gAs_ zC+Ow*vei|hC+LadpX%a24=3$$mle*&N}6$KWQ0?Bs1{@>C|nRgM+yA@i_xAV22_<5 zm3DfEgB8P$!)U!IEs$EYA*2?Kkm`hA9!C(04yn_=aKe6!E~*$MuL8;K@y1#xNup{g zbdMgi)>ihW;q0|Ts@%N4uiz5JSvPu&NaNQ!P`=~R+GWg+J=jcU;^H&@p`HyH%AL_4 z6cY!Q(LEF3-#4jN*w~XMecslbP2_C7^&&uNp4M(oQ7f7!P-->-pwCOKNRnC}qn48+*AA$a_q zG1IAUWjZgthbwtO@+J$RQEEH$z~q1^-h96P)$C_W*Ko;9mTAFCfjaE+mn^8Kg|=|u zO8b|>>XfQSS%wK5$D4(R#yg#d&@O#V$P4h&ke7b3p6+log63Qe$JAZug@;}Yr$iGc; z?Rj46I^q80JPC-sh-SZt@hWKD;20qkE6FPW5so!XJBrLlH5g z0^$1BB{jg`Ht~3LGY_gTU54k(vKDVl-%yO3!7M$Kr7a#cNDoM>^cIEZu0kM&#V2R& zOEH{FMi++SrTbdi8lpZ-Hz0_DmKQH$yW6K*Dz zgox_C%1<{^DkBM-b-*TRty+6$<~FXM?uZc}j`EH}y&A?QmLEhfvs|Ovp_OAoKyI3h zi5XE)Y{buI69N#bACN+I!@sqNR1reKqI9dn%JYJ)-}SvpbWxYCf}tPrNYPheI`ghq zHN#@j#U${+b}TXQftM`YVmxG{#H!4`rrzikQ>0xW-taI#SFVAvVQSAZJUSXs*)*~7 zh!H8qCuN36IDlWZD-BgzzYasKVL|5>DoB44UJO@n2av2~M!>);9|#C*ngtZy2FJmY z_CtHrVNG#qEYV7a5Yeov8MUOeiRPOV~*>m*4lF!`>X7ZKyrY(le1gnrzI z984Kslu^IH^)^8Vib^`Ho>p9m(1y6wRG_Q^j2G(qq7X_GFrXO$XPDYzXgdiP9Y(ip zj$xlD00?(gR17&lVS9%XrDN@W=m-muAbu>eMsdHG##H*M4Z~Jq;LXCpj|c;AX)Z}9 z@3O|ZL-J5xF}**`C|7J&g-(k`fEb}zX2UxASb+DGdT*#O*?5Awx-h4+M2fVJXhM#( zvv2#`C**4@N=qHX+qV+huJXvR?o}I4w4q-K909brM@0l|)>Vsi1k78-fZ>j`y2-DE zqxHBucs?lDbTpqu>QR!U;&5Exhz~+JrKpLYiqgX91X_wWb$pbOqayi6EP8ZYS<=Ix z3xAH?1e527t^KMIzGSRtD;kTIQu~yCFwQuep#lDtsX@;)k^32;#W^jQRAPg6yya(> zMk{dPhMDH$=jG&*cT;O=ECoqxR>}&KHmH_spWD6nXj#ejNed+dW2I;^c0 z6JyjR@QHH~hDtdL;N=Wfk9)>P(5&tFmOY(s9E~-U8-h--Kqm9cSMIN$@$+sH!i&Ow zh&oK~%{Ai_oUYZog26|00yibf1(O|n$86=$Q`eWzVZD#dMpX?=K-^AGwE@iDO6~qJrL!kl`UTBXxaAQE*KO3p|5zj&hr`4_ z4!izG1x_$*ECu3H@SLXUr%7$6(Rki_2HATQz4FL+@+B9YV&yU|Ev#h^-(rZ;bw)HC z9&$4VI3kfH8l;HG_pGzuo8Gy@26u7dFj7}W{(AO`wPH=Jgg12JS$n8Oe?bHVuy3KH z$4Jw>M}mSXp?}>#2LT)iuU{<7|FeA#;wg)%tLQL1QR>#e_I1udu8-OI#gE!_*m=50 zRfn%L$Q~9Sd*b@M!85vT!$EQZw~RDLz>7hxQ~<8PJLxFc__m&4lSVkcoXS@b8Aks7 zXEylZ!^hki5-nK$u!woQrk0lR{-0;Wv^=4Q1%scJ>_-9C=eeVwUc~wb0;BZGU+i#{ z=nWy;=RxQ)I-fS(D(`fq9Rp&bq6~hyI!u2KrN8GB9KEtxNoY$Yqt^X`eY07ZrjRF5 zWmK|MA+_-!Xqj`&7mWK@B0~(kP=oM{S&EoRD20ysOqcVcFO$!44`yC;G6hljM3MEr z^Dz5m7yAN%7Ie1yf8`c`!+8#uTvjup{uL1pmLs(M5G#j$6GnmV3G91lpj6d)%JOQ% zKVj|Nj%G%UN4gfA!uaeCX0` z#?H*cld0u^!jCrKeq2;bg-iTxUu+jX8FYB)CQJ(0apz1Z@)PzB_Lut$AP_9^aOM$> z9uWeWy*!-cM3=N9spnn<58>ToXv{ZQ@!`pgC_}T1LGW-%lQL&d0*uJptXak!mg2uG zQzzfw-6O)YVE?rcha8~#&#rq_){4gpKUS2fZ2yB2Oj4@+jI!^9qaCTxq%0^NTzazd zhEf;mb~p@MXTvXNqjNJ_%q*0&rZxi@4+sdB$j5M%cz)kahWn|iMq+BC_HS94NyA@x z@ZMe-$4g7b(IxodforLzky?l>FX0A+O#upOn0axV>v{4XyNUi$J8OQaoVu)Zwc)Gs z4V)!6!&qZ4qvtn9mrFU?R{VxmC<865cr$e>tk^3x0pY-|^qn1X{ZO8oJB$jzGFqA{ zhUE&EuncoCA2&l}noFr+w3xmgs~Vl*9&I}1n!z!8cyi&P{P(I{fW2nJYn8T)-sGvi z;<~0gQ(;NR%n^%p_j!kK!3kN92BAh|(}6C&a#=c%Pt_{jG|j+3D&7z}yrP9LOcic` zwfINoTlh9|xN$Dts9V}lQ*Q@g_ds|7`R;My`e`^npJU@&mgym7o|=oL!g%Rt)L3;R zWV7%Hhnx|M@eh*4%`j2bA&dKVTwq#(Uj*s1A~Nnxy)_tNw}gfXFw>=-&Fk5bRtaP( zEm?tR5t`0)lJjpq*FW-qK?)q& z?`o>$c$z}>jybud)O9l}C&wq=z?Mkq8ytW1h6+@!AeIp>@apkN&^NC!L{DOj%+<#; zXKA6Hd~eQEN>?AFIkI37cd0_9jo2FyU%ML`_~G7=LXTj#vOe6G>WyP1bQhtUsuhh# zG(+J$3KZM1mHhaYow*p$-N>tjir;|0I=tu*N1=(DK=#AOKT6v-s)^VP)w>2;_AIm- zAKKJyVLFv?1CRSv_&`tnZA#yyEuEEQ*JcyF@s&F}WTc&iU$ig-lC{`6_HLR2?=T%a z-Sk_T2bmD}yloxn<5?7vL+3|ZgiweP$US-ezm~Iz;GZd|76LH8inj}}&1ot(d5kor za3iFDuFVfh$=Kbj&!gEndC$On$$66?t&|C0x1EZhj=*&^R9L^O%iNDW^pK@!?Ix~( z8XqjI%tAj9=TR+SWlo{Vi?Cnp7DR4YMvraQOQoT0El9UcsyaLXWhT#@H%3GocE_fzt_u~Vayn#CZ8)ZP=M%?GV3JC6Uni(k|Y2wJ1 zvP_rDC&fJ5$>Kb?EZ};Ft4YplWB;~~$5M^l+dihuGg7PdrD(L;@i+4i<%F2~-Uh`T z*qwOG{e5;yLaRnzRh0{?t{1ye0*-8W-ugss(d_fE^4k`hWf01?U+;jGYLwQ`o_51B z^U&S_$8lhqwr^m(Uru+6jkFw!o>r2f@{D@2(k6_cjAqoUiZ?6WU1D4V9ak|!e4;OjW-(o@E`YOw0_$uL^JQi%d6q6 zx$sv$k>k{z$0-(ZaDiPX1ud2RG@&66SI5%e?Mbv5lrO!aWJQdb6qd>|@RspG%%Aci zlFeu;3+$STw@dI%lY}*)_X_M*&x4E4s<;$bVm$IDHL@-P^NBZZ3tAB5eR0nF)Da@3 z{N+?D!ulvh7a0TJHBBY%G!S@E9vFQ|E0y{A!cxsEzn^g3dh1(Usb&AI7x81dw&+X+ zWl_mq-X?)cL-TF!wOpv%h6AGN-`>R99lAMA3&+$0k|L=I*|H|(J$hO$J zI@rsf{Ob?Tmj!X_{+r*CS@Ct=37{mN`-;DKD%gBL)Jb80oQ@MNdp#XzxGz0_loNd4 zb)3LdpSS>D>xC{P7FO~BQX8=eaBlH|g`AFa$evB`{K1=8y%@61KZ6eZvSVu2Slu#h zOmwykdDE+?I61AF8tg@JI22P_?A)&+Z~ruNxYzI#I@D%`Py}l^hOtp;9f2>kw^A$f_pN&2yU!_i9 zzFFW9&d0}LIWD3`7|Z!)Is5P&GIVKRS5S*{b7P?zC{fe2?%xla2crD4#h1KOhEN&T ztr9!?1Cenp;43qnMTD{7JzP>7TN%qqj_x|S@cNdf{T1fd{?F>rz#mzzy!(e;f*I*I z2Uy)bh=ak29y^WeO~u1?uoSS2F%-V?ZhX3;XLME>5W$fw2R4np-b^Y51A265r{zB&4J&;5uO zpBi8CwZPKK&Lq@(9AM7|wys6Ug+FwiGZH5tI&pSEJ)M@5p~R|Ftk^NfO2ic2Eq7PbElv+n zJUP0k?W(GV9?6*8O5ZeWngk?tkXpoCDUvq}Sp%psE?gkyl?~ZyouFgSOjSD+c)fHJ z1Hou3jFk3i`fqq%qoXC8Z_$+x2$jU5RJgPvGYNU9e-7eIRLP(XPS6i8pWWhETyL9PTQk0wOuCOYQqUre?ZVp;ZTna_jp66` z7{dnVIc;I=c*5Yza+6ejoZMRdh$LXR^2hVJH#~sb>X`;-LiQUXhr3bA!pjX*qlicr zBJ%9lZ~G+(P*C}xb!i$vozQ8&Ud(>Q*}hm2&t6!Qps`oIW%|smV6~oMjQ!(piiRoX zPFDJ*-;VU4sgY_Jr-~=2)?Ss)IqtNN0aMivRfuaDEE~9g-0?cif8tJmqDB#{lNm<0 z5j$V$thb7hR<8P9-^KY|%ss*K-1_Bms)NfQ;O+;hB{ftm<)2tjK$>8ofpo?5*yvoR z?K|`%H#*G*wHwKg-@e%9>nq4!fwvDDc!O{&ffI0SuZGUzH z9>Xu2D+{$YQiKM$m<2V-HcNdd%``gtvP8J^9sR=}P8j3+nc87GJOpz)_}3#H$4Z@+ zjFcqr-P4lUS(q6f0A_z$I+et;?sszxH=VsR6c4ln$8JQ)d5g=u$fF#!q(9xu*id41 zqY7noQ1V+-Pd|Fdg&eIdojeWRjwg5B-7VygMxHWkygc8$^KcKr$(#}Y=1Mp0cTN{1 zr+R+dImDml3i`EKrqLu5qT4(63~y)&547wNEtI^2s1vc zn4|_g{yjJa>}t!wo$JE(I`*)Q%T3v*Vdz|<$gp_{qs1%*OBU+8x_IFL?Y^O*kT`B! z6mGdfNchBWIH89)DZ7PB{+7ZDFQ~$j4R{G^L6jjkn&O2INAPH-Q0)2fut$170|*Qp zix0sRF)~x$0At(|XDu)PcTm$0bkeRqvleImKo1O-#dl#}p%$R|vly{5{9`@lxKw5( zo%=bJt0Q?64BjRneOW4INZcy=9t~M1OFpHs=Tf% zrNUs$>J8I>QvEFR69$URM8M0cg7~p?=n1T&GS}S5G>E%Q2F{L>TgklFo#c5qBVSTP zvS(d!*a16LbmUOOZyVmmjsytl@~9KXv5z3mp3rh-HCoTiI4k(y{T<;A3PNdzQ+1q- zB^|K8(cH_QW8DTDtcyITcYmDmp-fnM+p{TVPQw4D7TbLw*yr46Rsin5S$pd>nuuGz z@$)aMnUtDIhJ&6Q%Dat<`f^&D%_wi%UTNBOsA3%A6)#x zSr%$=?%;M4HZkX0;}pEMha0CqmGt*8-ba+bc1d}llgl?5|?hdWu)VJ{>`td&f=-Qkv6C^ zC*FW{9sIie{`P`+BinawOqyFUQKgJgCpRv%@xr?OcgEQ*k{1?qCW^z`S7-#@Bh};W zIJT)Gza~9r8x*GIXko2SMgmc^!ic!PKT}EtXfUA z$;Lh8*H0QBud5@Vl4m!~$_|brJaW9h*(Vf1{TnMAZ*lW$ehDWrDOclbGb+AVE(~U9rF+5l?m-rRX>iqM=LJ;CzBhn%1Na^<$FP4;13Lf%T{p3k8`z#kZ~hBaJ?;JdSpQ;EIQDXRm2w?(HZcCnvcx+_6|4_xZc zTf)WI5cD@+T}efo)5+Uc9v5+27fj8EP5!EXE$jZ~ek#+aa5Zpp?dY$LLNExJ$D-WK znGU-(Ab*Rr{(Un*;fhG+=_R5|CqqP-I^Wk}br_yf?AYIH2WQ)?ZGETp$2pE?y~K2u65?x;w;AX0rcJ0Q5i}kX-#`&EFlrkepNHMxS36cdzsCI_(*}Q zxw*GmeBN{MTK=17;Rq6)tE)QM*R2(}Z6vEV_ACDu(P9ArGsxuw=jo3e8O0szFg-av z0x$8p>6dBV{6c}Nr*pIRXMfXLUF@aCPb?~t-a$Q2?l6ZAeqI+pPd2KUUC0q41MR+* zw`t{NEeM2@C(4W&LW^PAIeuTxF*!?49ODFb$8oYhI*}YOa$N}$)VWEnbSe5BIVH8h z4qyx237%tuzDwgb=9n46{`dYE=*3bMx*Mcw#YXzy>nTuBkXtJM>-PpdRS+LkWra`r zKih@u|CdLf?v>{P!t>uM-T&oz%kjzsaKMAatg%S{`@R2v`4$CI1&Kie)>t5rH8ISc z2&mSYj^uwnZg`-e(EpckP*7cB=tHNZmqZ&xdWe|Q0de|i7d5<}a9Ol`GcIE+AMwzQxnTMn4pf1B)f9MC 0: + return g + except Exception: + pass + try: + g = float(getattr(local_vessel.flight(), 'surface_gravity', G_EARTH)) + if g > 0: + return g + except Exception: + pass + return G_EARTH + +def auto_land_predictive( + bottom_clearance_margin=12, + thrust_discount_wait=0.85, + host='localhost', + port=50000, + target_altitude=1.0, + target_vspeed=-1.0, + safety_margin=3.0, + verbose=True): """预测式自动着陆(suicide burn 思路)。 关键点: @@ -83,14 +109,46 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 若需要更精细,可改成取 surface_velocity 向量的径向分量/或用垂直速度替代。 bottom_clearance_margin = 12 # m:按载具尺寸调整(越大越早开始末端减速) - """ - try: - import math - except Exception: - math = None - if krpc is None: - raise RuntimeError('krpc 未安装') + 参数说明: + bottom_clearance_margin (float): + - 单位:米(m) + - 说明:从雷达(bedrock_altitude)读取的高度中减去该几何余量以近似载具最低点到地面的距离。 + 用于避免脚本在实际着陆时因底部结构接触地面而过早判断已着陆。值越大会更早开始末端减速。 + - 典型值:10~25,根据载具底部高度调整。 + + thrust_discount_wait (float): + - 单位:无(比例系数) + - 说明:在 WAIT 阶段估算可用推力时对 vessel.available_thrust 的折减因子。 + 会用 avail_thrust * thrust_discount_wait 来保守估算用于决定何时点火(补偿推力建立/响应延迟)。 + - 取值范围:0.0~1.0;越小越保守(更早点火)。默认 0.85。 + + host (str) / port (int): + - 说明:连接 kRPC 服务的地址和 RPC 端口(用于 krpc.connect)。一般本地运行时用 'localhost' 和 50000。 + + target_altitude (float): + - 单位:米(m) + - 说明:目标的“触地点高度基准”,脚本在计算剩余高度时会把 radar_alt - bottom_clearance_margin 与此值比较。 + 通常设为想要在接触地面时的质心高度(或 0/地面高度上方的偏移)。 + - 典型值:0~5(例如 3 表示目标在底部余量之上 3m 处被视为触地)。 + + target_vspeed (float): + - 单位:m/s(竖直速度,负值表示向下) + - 说明:期望的着陆竖直速度(向下为负)。脚本会把该值取绝对值作为目标的向下速度(vf_down)。 + 在计算刹车距离和 PID/前馈控制里以该目标速度为参考。 + - 典型值:-0.5 ~ -1.5(更接近 0 的值更“柔和”但更难实现)。默认为 -1.0。 + + safety_margin (float): + - 单位:米(m) + - 说明:在刹车距离上再加的安全余量,用于补偿模型误差(如空气阻力、推力随时间变化等)。 + - 典型值:几米(例如 3~10)。默认 5. + + verbose (bool): + - 说明:是否打印并记录运行时信息到返回的 status['logs'],用于调试或观察倒计时/燃烧过程。 + + 返回值: + 返回一个 dict 格式的状态描述,包含 'result' 字段('failed' / 'landed' / 'touchdown_pending')和 'logs'(运行时消息列表)。 + """ conn = krpc.connect(name='auto_land_predictive', address=host, rpc_port=port) sc = conn.space_center @@ -102,7 +160,7 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 status = {'result': 'failed', 'logs': []} # WAIT 阶段按折减推力估算刹车距离(提前点火,补偿点火/推力建立延迟) - thrust_discount_wait = 0.85 + # 低空/接地参数(用于“最后几米慢下来”) touchdown_vspeed_tol = 0.6 # m/s:认为“软着陆”的竖直速度容差 @@ -112,22 +170,6 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 # 由于 surface_altitude 近似是“载具质心高度”,末端会偏乐观。 # 用 bedrock_altitude(雷达高度)并减去一个底部几何余量,近似得到“最低点离地高度”。 - def _get_g(local_vessel): - try: - body = local_vessel.orbit.body - g = float(getattr(body, 'surface_gravity', 9.81)) - if g > 0: - return g - except Exception: - pass - try: - g = float(getattr(local_vessel.flight(), 'surface_gravity', 9.81)) - if g > 0: - return g - except Exception: - pass - return 9.81 - # 使用 body 的 reference_frame 读取 surface speed / vertical_speed(对应 get_surface_speed 思路) try: surface_frame = vessel.orbit.body.reference_frame @@ -152,19 +194,13 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 v_speed = float(getattr(flight, 'vertical_speed', 0.0)) mass = float(getattr(vessel, 'mass', 0.0)) avail_thrust = float(getattr(vessel, 'available_thrust', 0.0)) - g_local = _get_g(vessel) - try: - situation_name = str(getattr(getattr(vessel, 'situation', None), 'name', '')) - except Exception: - situation_name = '' + g_local = get_body_g(vessel) + situation_name = str(getattr(getattr(vessel, 'situation', None), 'name', '')) return alt, radar_alt, srf_speed, v_speed, mass, avail_thrust, g_local, situation_name try: # 初始确保不点火 - try: - vessel.control.throttle = 0.0 - except Exception: - pass + vessel.control.throttle = 0.0 # 倒计时/等待点火 last_log_t = 0.0 @@ -213,18 +249,9 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 break # 确保仍在滑行 - try: - vessel.control.throttle = 0.0 - except Exception: - pass + vessel.control.throttle = 0.0 time.sleep(0.01) - # # 点火 - # try: - # vessel.control.activate_next_stage() - # except Exception: - # pass - # 燃烧闭环:根据 remaining_alt 反推需要的减速度 -> 油门 while True: alt, radar_alt, srf_speed, v_speed, mass, avail_thrust, g_local, situation_name = _read_state() @@ -239,10 +266,7 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 # 因此要求:LANDED 且竖直速度足够小才结束 is_landed = str(situation_name).strip().lower() == 'landed' if is_landed and v_down <= (vf_down + float(touchdown_vspeed_tol)): - try: - vessel.control.throttle = 0.0 - except Exception: - pass + vessel.control.throttle = 0.0 status['result'] = 'landed' status['logs'].append('检测到 vessel.situation=LANDED 且竖直速度满足软着陆阈值,着陆完成') if verbose: @@ -251,10 +275,7 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 # 兜底:极低高度 + 速度足够小(防止 situation 迟迟不切换导致卡死) if remaining_alt <= max(0.2, float(target_altitude)) and v_down <= (vf_down + float(touchdown_vspeed_tol)): - try: - vessel.control.throttle = 0.0 - except Exception: - pass + vessel.control.throttle = 0.0 status['result'] = 'touchdown_pending' status['logs'].append('达到高度/速度阈值,但 vessel.situation 仍未变为 LANDED') if verbose: @@ -295,10 +316,7 @@ def auto_land_predictive(bottom_clearance_margin=12, host='localhost', port=5000 if is_landed and v_down > (vf_down + float(touchdown_vspeed_tol)): throttle = max(throttle, 0.8) - try: - vessel.control.throttle = throttle - except Exception: - pass + vessel.control.throttle = throttle if verbose: msg = (