From 03a6317a0cfa2c340c0392c36d44210d2355681a Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Tue, 12 Jun 2012 05:29:25 +0000 Subject: [PATCH] Added LocalizationExample --- matlab/examples/LocalizationExample.m | 58 ++++++++++++++++++++++++++ matlab/examples/OdometryExample.m | 1 + matlab/examples/gtsamExamples.fig | Bin 7342 -> 9239 bytes matlab/examples/gtsamExamples.m | 10 ++--- 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 matlab/examples/LocalizationExample.m diff --git a/matlab/examples/LocalizationExample.m b/matlab/examples/LocalizationExample.m new file mode 100644 index 000000000..0e801e4c0 --- /dev/null +++ b/matlab/examples/LocalizationExample.m @@ -0,0 +1,58 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% GTSAM Copyright 2010, Georgia Tech Research Corporation, +% Atlanta, Georgia 30332-0415 +% All Rights Reserved +% Authors: Frank Dellaert, et al. (see THANKS for the full author list) +% +% See LICENSE for the license information +% +% @brief Example of a simple 2D localization example +% @author Frank Dellaert +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Assumptions +% - Robot poses are facing along the X axis (horizontal, to the right in 2D) +% - The robot moves 2 meters each step +% - The robot is on a grid, moving 2 meters each step + +%% Create the graph (defined in pose2SLAM.h, derived from NonlinearFactorGraph) +graph = pose2SLAMGraph; + +%% Add two odometry factors +odometry = gtsamPose2(2.0, 0.0, 0.0); % create a measurement for both factors (the same in this case) +odometryNoise = gtsamSharedNoiseModel_Sigmas([0.2; 0.2; 0.1]); % 20cm std on x,y, 0.1 rad on theta +graph.addOdometry(1, 2, odometry, odometryNoise); +graph.addOdometry(2, 3, odometry, odometryNoise); + +%% Add three "GPS" measurements +% We use Pose2 Priors here with high variance on theta +noiseModel = gtsamSharedNoiseModel_Sigmas([0.1; 0.1; 10]); +graph.addPrior(1, gtsamPose2(0.0, 0.0, 0.0), noiseModel); +graph.addPrior(2, gtsamPose2(2.0, 0.0, 0.0), noiseModel); +graph.addPrior(3, gtsamPose2(4.0, 0.0, 0.0), noiseModel); + +%% print +graph.print(sprintf('\nFactor graph:\n')); + +%% Initialize to noisy points +initialEstimate = pose2SLAMValues; +initialEstimate.insertPose(1, gtsamPose2(0.5, 0.0, 0.2)); +initialEstimate.insertPose(2, gtsamPose2(2.3, 0.1,-0.2)); +initialEstimate.insertPose(3, gtsamPose2(4.1, 0.1, 0.1)); +initialEstimate.print(sprintf('\nInitial estimate:\n ')); + +%% Optimize using Levenberg-Marquardt optimization with an ordering from colamd +result = graph.optimize(initialEstimate); +result.print(sprintf('\nFinal result:\n ')); + +%% Plot Covariance Ellipses +cla; +plot(result.xs(),result.ys(),'k*-'); hold on +marginals = graph.marginals(result); +for i=1:result.size() + pose_i = result.pose(i); + P{i}=marginals.marginalCovariance(i); + plotPose2(pose_i,'g',P{i}) +end +axis([-0.6 4.8 -1 1]) +axis equal diff --git a/matlab/examples/OdometryExample.m b/matlab/examples/OdometryExample.m index bb9d06c70..68bdf0380 100644 --- a/matlab/examples/OdometryExample.m +++ b/matlab/examples/OdometryExample.m @@ -52,4 +52,5 @@ for i=1:result.size() P{i}=marginals.marginalCovariance(i); plotPose2(pose_i,'g',P{i}) end +axis([-0.6 4.8 -1 1]) axis equal diff --git a/matlab/examples/gtsamExamples.fig b/matlab/examples/gtsamExamples.fig index 39370f3df54fab4ef92d744742611a8679b409bd..e29163e28733672598de3319389497c87053bf2c 100644 GIT binary patch delta 8860 zcmV;NB4gdIIhRO~K?*f8Ix;gLGB7bRkx?U&UGv3{aW3NA&P?V7-Z{O^^H}7LS@3)g_ z0Puf)1(*=@lIR79+XcywrTP`oTg{zn?!uRVY85wqwWV$=4(h7-^x_1D{R+i(s=)Yge# zH(l>Y3~W*-yh&1OGxE_uXxFH}%K{mB*d`+K+b(ATbDd})^&GXkl(R3=T4Dq4G0tkt zV!;vYaq6#;fV5|ff@Cck>BI#pEf0Oiyq<={Ir=(9M z{Y%nklKw5}b4g$P$LMp-&S#n*Pc=W4-@~@^_-F0vH~uOPDlRHcDsC!{Dy}NdD(=I! z^Z3W~tm1!m4eJJ$?r!z$L&(-Mnl3NnMMy*@vvF>*Z9tmLX}EH(D^Rr0>JsAm)S`qdyz6JcFELHZ+pyPeFe|~uDuOXE<;-bXG>|Zw zA8`}mef*=XS+02?-p6w2><)i9q;IOf_N1F64RavqR2ROSei7A$>t|dS9`;!mTIY3PBz0l-lN(c*=C&bqMWQ3rp% z8v(WZt_=X^_2GY{`kPh1y*(Pf@ zJL~R5+nziK)`Or2u?TweAbJq-;8AZq`VWYL2Z?y{;6;B#cXoH!$#m@|X<7^2fnoM# z_xoIzt(F07keh-6~Eel3ZLs>4u(xQDEWMEO0fz#$-1+Xops3-~onC@9RTlNpky%Yra8`d*>gTXnD^O<~8Q-8dUa3oDq>y7{ z)_lZ1!Nb0O&ORbT1u4rlRM&xnv)Mk-#^O*tmY)OMa{&V>o6hBlJOnoQW5HqC!8^;~ zML9bnpm|@3JZN2h3^MmZ_Sh*u=ElSmi3DSp7fzJJiBcT8!8Xo)(4OB$8GIS)_#%|0 zvK@bzx@i~S#uFa65e}Egb*W~6Zq$!>tg|0DekSzx2}J)^PiJwG#5b?Fp6BAGALsoz zzm0J|EhAm@<9zqyd>A-!-YZ`9aO)znxiKy9LiB=7`awXvs?+$}7Q_l8%dLX%4BDJd1S6ia%D%VFB zg0!099xGzm!C}vz8}A{|%sV-M<&&Rs_a1#qHjYj8y&V3QJU2A_OSzD4g-cZb%KUoPEl{QCMj z*-CxD@)5IT>X=*MaTT<8KE3k#R@Z;ARefp)9R&}(?XLrdO@CYU>wsNR2l(&Fd;2{Z za(ofF#X2B^O2j)&T0417_Ui%QUJuaccDf#T@Sp2}=RdCh{;=3^tp^0Kxt|Px=KUoy z>!8%WPWjyF_x)Da(=8l+^upclI^lC5Zhcqw>x5lVC-~nB_V)LJD;!@$ZuNhEQ>2U2 z`AjOy7YTm>00960>{!iD6G0Ro%C~~47lo*?@dHXELcxPkV_S;GCl0jt#yji{U03GcpRqpg3~)Fd{;$~24h2UDz}n8p3~A;Mp|+LY8gdJ z-b2Qusl&9y;a%hKngu)RENq5P<(B+($;a*0TchY#okM(hdwrZ8=Zk;n@pd#?>yQ7^ zb}~}R@ACRSYew~ki|Ew|zZ;-&9lL#QQGFI(m_L$=T=*IOfIdZ^w0;Y(+fXuGJXksARm%Q229SWt+LR~NV&WL{b$*c<$ zf1jN6B9>l@Z)<;XWcd-~;sOAk(XA{VmlbPfzg}W}bF%M_5HBj5_NAm`i?9% zp?YN+s=6YX!FF11dTF^yvJ2PVxk<_62c`1^=KD_bgZmZc2aA`!e0|%n;u=5b-Gls~ z*Cl=+;)r88xbE_UQyxEX@Ymx99zUoAKS&DkqH?MHK!JZ6G|C_d9zSsA2h8W4<_A-i z{{P_f(&*(k%VqI{{h;uCshm&D4SKMv_<_?qU|%%bF1K*Ru^8_5^Mf{zA2|5y@dJ+^ z>@t2ZDw{c|c>KUMe!$Lnr}=?eA%39zetG!S!t?OQ=1}0+jqk4UgM4D{9e!Y6G}|t> zaKy0~?)HE4gP_L`9Q^h8fyWQr;s^f#00960+*nPF6h#!Snf-x<#Vlw95~D?*pf z9`G-jo*lp)+;w4R85W{0HQlu{B{f}bcMa?i4;(aNj0qQ_Cu2MrHIW!ixEXGkXo7n2 zV%Wrkf*yzmJs5*k-PJSIJ-u{KFSrRW=~Tbh{a$~)e)a0Tui8HDSWrjcE&#w;e)aQf zEx&q!M}3md@M~UY*G=sBq}uWI z-dBJ0Hiq8Ia7$B#>5|~L@@t`C>I_qJz6MQ$p!t*3mJx2-n^5d+2>H=3ZTt2Gzs0-# zIjcNdFURnA^+&`<^*5{d@l=eS>c@bT8#e?!q$QbG)z8X1p?4rguQxRBHhz)6KG^)} zm*;Z79Dd{KKfnHvyFf4I-`;vj@?YeVet@sqyIJ z9&V7l7zuP(84_&F!m4jC?t9jSzGq$Qdy4+&+)_K?G0tw(zHDHfn#`s|v6Chb1ubPB zar4kx(_P$$B!8Y?hfK`;8X;($SEi~>8>Ug9gxbKbR{rzC9$uf6_xJIyDdAK8_6C2G z*kKjAI7=;$KR_KU>Vf~f#B6L<+xmwbWUD6gmPN1*g^DYd>CmFI>uFNE&eQ7@GTL_3 zIusT69uSPXs6)oHSEk>6?^^Ea!((edyYE_V|6umfx9+{_?!U7=ZF@rz_SAI{?;q<) zw{GJ5>yQyxu_>7HEi1OqguiQu-;IL!{uHIBNxd!E?&9d@$FLF?09ezKS-gOWylZ!_B>3Rv zP`m`65FeBnvJov$cZm+t*P%Nd9}I%k!3Q&|j1T@Oe2%^v_$C!Th{_W$F}Ht}r-1Y$p4lLj+aBvmzH@y%=>y_ z`^(Ma)8$;+efzJ{AJXK_hd=f|Q$IGQ-T&tA2QR#`N!$MQ+@J5D5$%7wZ#fMPBw_7Q?z z@&s4SI>+?-t&DMLE%_2t$p6|2Wuo$ki;#K1Fx>HQ>SQ9VaC1hi9&WG*Sq98%Xe+NNPIKlOn z1ao6<64#5SP8v$i9Ep$}jgS>0Wcdi0PFQT20JPjCu_j;e1F_7sTN* zNgeD5!8#~-i(-FMY}_>S@}nraRsE-%b8A{Z)5OR7|CI8aAaU4A=hb5Lqt1VPf1W_1 zGAt9fBkPN*k6D3|HS{Tmj-XX)<6vuF>jLi z(uIZFx}Mp9UKWUMbf@SgjZ0VSpXm-iZ{)L;fR&)r~u7e4QdC6O9;o2c_fKEH?z+vBjJAcHLZ!qy4KtkfMNeBsU`v${K zlQs!uS;Iy*DNk~p_p5(?FVBwsUJi9+RJL*1GO}g8Udef>afZ;Oe7+&um^Ut$@(#@# z3Gqe{Ut4o|P~a|HrmTidgFq9oL{++UpXY; zrBJ+EF@9xG*spQ#d1JFMt@xXhJ$^QZKPv5B^7O~@g%=qSHVVreXCjKvVC|`4afj(e zPPye`y{Dd(h;35bzK2`T#b$K_qGM+*Y{NX)A;@i1B1p%V0y8K?u#f={tC96Tuq7Zy zQ}lnZGPlUO#4#;UVz3r4fvSW-O|(Nc6t+Zk(F|bo*fIzUzwdo+6G3O1p+vM@45(S>CeiLfyE~4EI@p2W`96PJjw#4$H(oVq*ELa=v8J7P*T5o}l6Bl0 zhUz#H04a+$SS2iQ5G$A_l`&8=cK>p{rQyBtuu57Lrco!bXCC#zmiu7EK3Jg-=IIN- zbg;a2DpF#ak<}zmidbuc9^DT~&IMh*bo5;4#~TarI=aaTQy*>;yNol4^5V|PtgC;; z+w&#pZ_@bqekO?z<5mmPWOlJ5_)*xMj^R&4_)3@G=W|de!(ZYScW-3n(;1KVul^_D zYrx!N?l5uBg!mbBy^r66+>;3H=99!L>)B0`H=O-i{qW=aPJZQWZR7LLciX|dVNgF1 zI^ORqnlH(`BoR-;X6(L<`swE@!{C3#?c-4tj;GR}Ip9DayMyGR$F+{9B|lHXJ8WDA zTK~*odGlpYSG}L#fL>tC%l8^LJM-?M!REc_>8h`SAybVCTT|z4Adyh>ZVfo^1y5If zMU%-?CpQnJx+iU&Q{Kt0hYz~flnk{VMl)_byp`6&X+4b6dRR$X52y8TS`UAx_3*Ik z;l0;ae_ea^e!I^1&wcr}lmC}`co_|+9!|2(t6bhyt>M(SXZEO@pbngxju#grAw4nltK|oPjVpP;*?s^4VZKd{(BBIv4 z+qt`uz1?+p7J7|8{9yzWO^SaCN(}nLpZWt)5EIe(!$b`se2Ef3E0m8CO`7-z;Rnv_ z?ddeaxFTGw+p|f*`bzX9{_yl4p{Thsib_uz3NSUr#6u2k=bt z`yrRylrnMwm)ta)PvPZP+QL+R+suM|&_jMQu{+16pA8AZIt5`vD29JEs)Bibo0!~` z)>TuHqN=Rw7O(KD0PV=oWHI-on1v2+wUmbZx2tv0fZeJD-Lie194GHfL`ln#;}sdO zc`-Ct!dnkfI)e+m4pm2kgfGew8KsphRIt#66d1#~A{&&q9!WUk;&qF98Y#u|?NJSc zky^y$d_17XSk545+t@SakCunkJJNP>p}iE6ZECI5(c|LfK9w zDVwgG*-(b}Oc`FZ3@=iKXVbkje(#26)KVo z(YnNUo@9|E(PP?cp1i-TZuu|d{N(dXCNyCgyVb;3O{ITs>Usu?%P7R^LmGc+Vsw{X*zbnG$}bcl@vX9T?K_z@7Jie!KUfh znIuJ3zD6%9d2i-A`^o=XB_D4kxk~FW(f1n#_xNx7lGRv+eK|=81VfYj)=4HJ366DD zcG>q^H(Y-e9=7`H%x$&pw|bl2Bb4^nd>ES|DRZcO>2wY3uJ@+0xpYxKGqHU-k0}!C&1Sw&fawwZ)O; z$5K~Z1OewXJBw3@-8)-UeUqVy$$Y$qJp9|p#f#ELYH>?=X=ZKWMVQ3P;byWdw0&Nd z#)f~GT|FRXH5nR9m#i_dsl$G@+mr(e$OG1G^x3)YO=jQp1S5e zms|t)U4Urnj;@VSx=AR>!~Q~q3;Nvqat7xItLd43N;l?zo(;O*&9KL6`Wd&smFn(l z&*hFA6z&XI{*%--$q_<`W~EL|LW-V zOM8Leekq@r#nk@LCWc=dfeu5WE^bS~X8SLLj;R5*V*j|F?fcXw4I8xCMrf-1-hrwID z6pw*9CuS2o4&I4VJmI{rq=(J_fj){C!Ac9xf!)thJPVpFI0IN*d3hGshNFM=1do8( z$7c~d=Gfo0f#NC8c(QSe1((448!4U!ckFH^c&MTt7Wai8E+BXqY=4U4QSf$*;&HI| zQwqOVZJ&)S9{f78ykhZZd=_W+p3&_6P!Gi;Hhl`rwcw=V=k_5AM@sx;`Nj0ivET&Y z`ORnM6Flw6v;4#sj5zV!_c?!s5of*sZlpNs_{Y9ydf2-2ap3d4(*9z4^YoZAe`bG` z1*72LR}}uR^X*W@b*^N8^A3~X1#kPO8VUXacJ@&$jX%pbFZ(PX8C@yQD%ofA{rVt< zKfyl$00960tytS{R7Duy8Zr1F)?R2$%a#{kd@v#si$*>ZG|@Lyih_Sev(mL`*s#59 zFPaFiKDHQIN(}W+pm#77o=ub#+TCrXw!7_iyM?xtTd5Jn`G)hGmG3y7-NfH7%a=Jb z^WA68DVHuXR;g0sXYy%mJcK;a$+$w#Yy3q0eT<|T_Z(zSx%NdgQdFUFjUN2LxIv>A z7|V2Vl(9mc9gH!;dhCDSC}U=f9Z1{r){`xY3obu8_A$qtbyL)JfElCjK4gv)=H))b zWs9?Nxm}irt&bj;Yb53G z<;*1-8f2u5|APaJdDnX6?WoZ&Y-)OAR9*tFc=x5%v z#*e<1_M|^@pQ*odo<^rHC@#C~+v<-x$@<%#%R2Oa&YZROzbpSDewk+(C;A@q_@1!c zx4FvxD}8^8NzZ#6=L7F8^bgLz?OaHSe9CxnuX){L@B{aQ^c()5k0EXAA#u;-n?LN6 zed{IRm+d@z$##tlt>0s0->183m~MS|?^kPN==|h4#f+z&bMXzeOi@#3qhivW zGbvxwSajFj`R*GTW~6DC#saOEGVT2feK=pY));>YlXv)od7B=@kG{rt$4-rT8o1i8 zIA`)I_am?P&bn2|%-VlNBlq`jdv}}SA`SF2=BR4cuQ+4X13UO$={w6v(2n<+N%KC= zw~vqySx590@{i}pGv+bIJp8-;9COap3I1Xp@xl-E7xbXc@;T}x`xAYHe7^As^9DVr zU@m{tpOwrNT6>n6aP=MPF7qJ!-FChZ7siMme~03|e@tW56~C;r%|5>odKOi{h}|6;7tagCc+`!DZfCS3NUKXRX}|DMm7t8~fv{|0<_*y@iy zlJ&PemvzA3zd856hC5%jIMMf*$9~&=o2!3(bw4xZd5`0KGac?MzU$$4k?@rivz z$g#)%0sH}6;0EfkM-Ch~fK(w=p$e-03C!D_@$OC>d;QV6MHy-R_Ra2l^FGG!{dVR7 z;PHQt0JDN#5LX_eaZd8N#C1trt>%8Ua;+kUdanR)$>-O^6?8l*RkVmxw<5;#U61+! zqa4f@v+6!|#4Puy$%qxcF)yy`5Zh7cVaKebIEs>Qux8t*C*^1R_<`f1oX7G0BWj?$ zw~#Fk%I^iq7sbz^!vYS8vEf>-e`3NWUUz@uQ)bc6iA}o`+fG26)ZgmHZQD5(QQIPZ z-E_T_c0@8hB-SaGF5>yk-ACP9sj4&St^v~xdNaquIvqgMj2Gr-Vo-OE~*BO6E z=d~oRpMS#f?+u-zzRK+B`ivg>x-Y%)>_S4n@9^mj?0NcyLwe@XgO z(!V8rCh0$tK9}^xYet`Ic0SYmc&hoS{2q6l#XoJ=u<=)MP;pUlQgKspRB=^tR&gJ9 zoW(z)(~AG}Mu-ofe?R*K()|qiGWLH?UanKiBBGa-WvP}Yu)XMZeu|13O zX!e%mRt2z8>sAJ=JCj;>2HZv?lUzO}mj}cIS>y^SxdJ$@L$mbzIW0cOr<@+s-#zG$ z6OwjgUta_@)V?hk5nYtDWQ?V^cu(rNVjSZ5LGn*FjdA=Ogp)5oI?l+O#Ik>C#5~g1 z?d1<7sKUW0SDYOVAFF)7C$7&9w>NL?dWaY~ScC_6iN)$MYz+Tj=Z4ciFM09#0s=F# zV_I!RPXp3qPQ#V&x&lS}tS%w0Pc2Hg!n=M7{1VfoybF8n2D4&ZtRffzQ_h^GMFR<= zd54<_@1s9$&2r5n@jQ}4XZL@}F|8xs4>`PXByb<+yXDFv3-{4hZn(Iq@3j?(zn{?g z`&50wcx~RQwF7j|bG^1_i|>v&PlNVPa=pB`%a15m7*Xz>S8V5~ahdBOH%z^K*>ym- zH#ef6Z;Bj1wm$!{7FXm)?(;TeUiW3;i$VM7ytXd#QQcUZh`jOL>Ggk0)v8|gYZ~WG zZ5GwSaq2dJ9iBs!hU|Am$s6L@kpE+)@iwVZ3*w<4$ml0Fxc-Bgc>Usl_3{0CGo#xZ zZARa9gXlS@9`Q-gJtE`O378YR&}cg*8e5fF)p1y_e0>1vd?8;>IL^yE>j$^jZ&vSo zR9RcAtrE}6RDW|Ry*YmYQvT5tro7k73GJu7AWmVn*?LFu=Yq zw0I%U8y{ATrPglkOKJuy^jM^&F80fEs(372MF@k3kyW)1udbYsS!uQzQl)Kq8M2)V zUexSDo`|N`vE8;pD1+j!MpBQGdzg@0(B4DTv9qzekNmrEVjq82;|Rz4lIN3injNZ! zDE-KnqT4_6kj{6nzLf&~ z(E!{?8E$_Bj4(c`)l-;WU$iFz52M7GPgi;)}}m z+|f~GU|}+QP0isU^#<9NJj8Ht9^0^RdI=UxU9|`Lr!39DY1Js6!)jqR33WXSbBp~$ z8x)7;iy9p{ju&+b1kIK+M#&Q7_ZQy_5Y_$)(i8x$O%l9v&9#3c~4`!iZF~{xT7DYN*V`^2jVA(dTP0j77qtQb-KgIhu+9$P`I*wzu2B73Ew#l- z8sC5TQDV123TC~aNLogUn~ctXO$c|V$gy+%T!`D;|2MNIjPo2fjPoSUCv{}2VVtjj zoNoqRoDYguEz-KE>}*U0yimPpnSK;duc|fvmN^92J$b>;F0jcMgzx8%MJ`=*63d@n`AvHTdLv{4IK)xZATH|8nVe>DSlS@k;6gk&hUYxnpjJ z$5l|>`3%bI+g-8TMsB;Yd`4(<@-xz(LuR=wes2M_x(!O zQ!gBO48q;%I^lDq&;70()(N|!P6)pj?CtLbS0uiuT~y=ymd!$i>?D)fH{18^yf-ti zpEST3EkwoxsJ}$L7WI1650ZcRz~)%Z4I~Fs*lt06ydYCreIKfmngX&s zqj!zbYa;VC#I7aUR3F>T#^Z93c~?h9tk=cp)mrq-bs8g|6=Ykz)yh+*A0 zqg!pG+sNpKh~3>69)cPlPW2}S==$8|bB^%~+W4{gs6i`iA~qgHpy{JP6mr8LPxYMQ zX|TkDZ5&KD4aQ>~>*z+eAY`Get59Tg+?+$)egsZzoWqB8Tg!Wh*zZvvkp*4j%+?FC zlX(>ug05sg<_$%LYaLKa|`jcIZmHd{G)-^Uf_9osTgC3L)I`JAc4)*-vRS8>I8$8{)o zab@t?{CaGyHCq4X=z8o%WAM!5Lu(uNZ?4MJ3)$$g`+z?`R^@+g-*EgA&_$3@A=Hic z8m|Bq=xE2NE$f2J(_?0>%O!QlE|148dBk=nvq4(tKw`K*(VM>2-4%^y&H_a#sULQ_ zfg;@i*U6REopSu*#IHHHwLH@E5n=Mear%rxPVu-Pk|*=m%Ua*;)_2#EFKlb$r@P{j ziNVZ0KC5@|Q)qu%a_C&Q=XDK8SEhlah`bhQ!{w$2mzy-baBUqWP96DzfJZ9V-tN8* z0U63O5-iZW@05SqSRLy3Kk@;MeW&^0L52BX@zU3C@9I}QidqR$7O z@d4fAo#q3nLVO_pes%cu!i(6arfB%s%_YzHz&MzDhY!q)X0FRC9qZ_%yZw9+@%g|e zUY`$qKG=Vid~iMG$Or!b00960+!#xY6h*XV_5%wGSVl;Lst?VwKcP2?sE9N)&C`I=)= zOq{t2bSxXqoh06I--RZU&pCT@y7WMw&3el*4@q?`_K2ceDcM)%+E8gU;X=+?=u(3#q3+# zE(!eeOgnM19>o32@gnwX(B6&<*@?P-N$q)7;!A7zWP9{54L1m!k2dsa5!%?AhUG|J ztNpA~_Oq_OpM12PTPjB#Tgla(%NjO`Lp^_DOLCILA%~^Z!$BOnYdW+0fWXhQ=dgom zlp{EdLi2dpBQ?j$5u11*2W`8=XwmoFUY4Jv`TN;!3iwoXyump3X^AXM6F0;U5+Cz? z5PdID4?E=s|6w0_vdFCK+Sr7gB_NA%s6$eJI>f88@H&O8h8#H$>FnMG;&$hG$a;U~ z%H%umUdvp4Xk_iD_g>2!=ubcL<~>(~^LMtZA#Xq^Vk+|jq0W5H=TYjDfZ&HKfhzQ5!Lfu z=mc{Mukb@<>ci^31z2@$ zxj*f#-Ups9Cadx_=GrQg;@V`KF{Rhn@n?Vj%kq2WR;-m>;ArN*9F$hSL zo`o88wPRo~PKb~4j*n=aG}|ofNHghZGf8b2Kyy#QA!#3BR#=%eSr7=LB|Wc)Ih-?$ zklJm0%;CUnh%b#AN&Ax!mNI|Qcx`ykcl}cjH07hV;Dizq}$D8o2 z(dhpXSPrgd;`pzb_;^|QzO>AI6_5B-`OB>n!R1WSbNi1}ACkn)2S4;aT|G8p-1o+B zhc3Ll+1T;b>>qEVA>-R`81(nGRd-Z>aaaw$R{6IF#LpkcdCq(StWJMDX{FDlXP4I} z@};a#bRXXX>-zq6NC5x&yL7oSoU& znf>n;_={cIx)W4}R`*d3nmPmaV&Apl;tQ-Q)oJ^zGE(R6^PrD{Y9;X&^9m)@CF_)J zq|jmu0Bto3Xfp_xD~*402F8eoPcb^Qvo($kW~Qtivwe+HRx-&+XTKQ<&3On?)WA9HMK)4t zqcwjqYsR%13j(`{eO$seri%d$+3qxPvH3h&tk1)A8u^m(BAtJ|noDu1Zm$AcH&|kf z+1d{6T|ge@_k7rxrfUhB{yT8c^$CHtc04v_$8k09n08HynIjt7Q4KApp=C8Rflnca z^-jW1IUBpK;!VtMjAjK{YCIc4~P9E$9@jS?Jmtcn<+$8I=t0=lv^{112Yf?Rv z*eCq|l<=M)`mleMu4}a5*WLfv`8N^^Ao>5vpuN0tC3Eq^V~5TUUe9cOu3|jJ`rDQKkGNgut1HIW#ru-Pel8JK ztE#QzQ`J}gKk;AlCFwU`t)UvytlN%#$^86n^=CT9mj-{l8r>;;?b@Xy|ED_ZpSK8{ zk5Qk4tgPdRzOT3^l)D5vle<~qd>lt*)^g;Xd7gKrh9b#*Ym>nFm^WEd753<{miPbW z=hf!>7XSeN|Lj-IZqq;z-lRWj0aXPd(MLcaByPYdO_P>HqzIZcg$jvo?Wwb3vuo@% zkgA6sIP`xFxbq{fyg|h~fP}=Ml@Jo#`UYj!aT43Obz@r6N*-xr&li6?<5_z>-z3T+ z&JdbF2;G!pRE{w@hEdx_JU=5x);lVjJjJ}B0B;EKwKbPl^6^Gvc;j+R$+7R+PVV#D zm4~0M?&YTLHm2{Oz1)O%o&Ok@*Ki=OVI<&{P`rQJF?nTBFt0K1d}A{|t@xW0J$^QZ zKO*B^_WUREh8GzTHVWDtXCjQxVC|VZjp6~W16SLU`=2GRS1KsXa!;@ zY>9v9qT$2lv1Jezyx#}hCW7z)y1)evV^v`hW(2uqCcrW+kiT854wfLAKRa1_M+nY} z{3V;yI+GSGzyf-{vLa9jV>6E3%4@-FN|@;s>cl3igc8wmF`#CRn?$<@t?qS1)WG%? zuamRon1ZZ!>s6I;-4G>NYuc`N6)b`&S;v39%TNu63LtIK2CIk#_G5X|q_PHT#_nHk zwlw%`JgSgpnQ7GVJu{CZu;mD>5P{_*Fwb8Ari10JQ-KoG46P=4TEJQZ^zieLWM9zb zO^5e|DBfs**Y-_Ln0j%O#ATd8m>0KCW?e5nUdR0TCaq5=&m{F>+-hQ)EG~8gKaPL6 z(=q(<5MTN7{d@sxXE>m4ao>%sJUi#{{x$z3d<~ep%^jugnE*e7ZbanW&vz1`-CUA- zWxcpb`iAr0Dj$FT*vYNDt8RSx^?uvmH}snaLMQuvh5IGhmn7n8*o=KH!+Cc4l|k_0 zp5qY|tf%syJK#V>+zwjVw;n$1yQXZQ zdKk^PdUz|JxdsUB9A>fuxmr+PTm!-LktdvC7&zW(~dc8%{}`1*Y(_b-2Xco_{w z4<}jYRW83(&B5r~R2QGEK0VdNsV+`=|BrW^y7;i~o3erG;?09~@gD#H0RR8pSWRpj zMHC*dlh9Tar3gVPAr%Qh6BB#li#0vBan_`SY-T!QsrOc99XrJG}T;JQlF$64-tnwosS1 zXgkP!cacL6tuPzu*p0Hm32Z4)haiKOP!RGecxNAP6Je(*VqS@Hyd!`4kQ4}ZXbVvR zmN7*Y(N5@4yiIJ2rp8-=+`%-t-!!j~}AsAg?m*`SG5?bU43KY|7EFgkR-n{R%3-zQmB}i?8Hn4|lm|)TF@DOpU%*FNB zP`mpc7FFbF&Wmj3zAJxlt?RFf)Z0-}lD;N^zblAiNbnAfUjtQWI6#i`9^wm7K%G}` zT_Sy;Bz7NltR>0Vcw-s2%Ct^=EoR>A!F#I*uh@fE=)nu=bwq8%!*ePU?7GHj;;kaA zH<4||!vk{8$~gvtd>je+qae=D5fJC+xTI{kX@z^f4{j`h3uu3rVX6{0jb6$qGI3)) za9Is!b*TROqM_TH)<2P*Y5YSOZ$XkyFZ2aF3cdM0_~Qm%(K0_TB6Twy;J04qq~H6N z{B7r9L=4AC%q+Ie+@< z%QIJQ-T3Z@YVCiixli|U6R$M$FMz#Nc7Or=7L7Fdl}+HXK%ni^ani!Jt*+^Q`!wyf z4zTyXz@>@j_kHA}9(o7yFKaaJ>UmlToCVa^=>LKn)GtGwehGHx`ucBq8P!;EUXFl_l^sc2C;31$wre{J^BMMy|Z@}lQOqZu;$+GXsC8rznwT0ooqhS_JD{gv5UnLXJcem?<{ zephr*AF6+QFqV@huI!h7S^ebm+qvB*=Z<~z=8AGldUyG}lK7Kr7_)*a_ z+5vepD~0NEVSa1<+1a_d+B48~Q`OHiAYI*^4{?7J)^L7|;$u?t3jm_+hEd$W(Rb$( z;}<*^)&qZC?PK5DhQAc;HJ+HwPc~O;@1eSwMi=F=sP=iv5gu$UZo`&KkT-dD$rnCH zTT!;1o!*C-c6_YXNY>O;M^D;&2+Ah4-C}-}`-iD(zR+-|jQ289(n@i)qUh6LUmR}5 z9*%$I>3Mn5up_GJBl(J+2!8%-Y0plE>mdD%Ztp>L_n`N3>2Eb2&mX3bTI++;`+lYO zF*&`DfBWn5ozHSFU;BFR_Ybe