From d06b40ea290a32f946cea93dff02ff3050b83f46 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 24 Feb 2011 03:35:19 -0600 Subject: [PATCH 001/284] Initial import of my androidgcs framework --- androidgcs/AndroidManifest.xml | 18 + androidgcs/bin/OpieMobi.apk | Bin 0 -> 148198 bytes androidgcs/bin/classes.dex | Bin 0 -> 12640 bytes .../ObjBrowserExpandableListAdapter.class | Bin 0 -> 3092 bytes .../openpilot/androidgcs/ObjectBrowser.class | Bin 0 -> 951 bytes .../bin/org/openpilot/androidgcs/R$attr.class | Bin 0 -> 358 bytes .../org/openpilot/androidgcs/R$color.class | Bin 0 -> 447 bytes .../org/openpilot/androidgcs/R$drawable.class | Bin 0 -> 418 bytes .../bin/org/openpilot/androidgcs/R$id.class | Bin 0 -> 403 bytes .../org/openpilot/androidgcs/R$layout.class | Bin 0 -> 449 bytes .../org/openpilot/androidgcs/R$string.class | Bin 0 -> 445 bytes .../bin/org/openpilot/androidgcs/R.class | Bin 0 -> 627 bytes .../org/openpilot/uavtalk/UAVDataObject.class | Bin 0 -> 1127 bytes .../org/openpilot/uavtalk/UAVMetaObject.class | Bin 0 -> 1440 bytes .../uavtalk/UAVObject$AccessMode.class | Bin 0 -> 1199 bytes .../uavtalk/UAVObject$UpdateMode.class | Bin 0 -> 1333 bytes .../bin/org/openpilot/uavtalk/UAVObject.class | Bin 0 -> 2255 bytes .../openpilot/uavtalk/UAVObjectManager.class | Bin 0 -> 5422 bytes androidgcs/bin/resources.ap_ | Bin 0 -> 140460 bytes androidgcs/default.properties | 11 + .../gen/org/openpilot/androidgcs/R.java | 31 ++ androidgcs/proguard.cfg | 36 ++ androidgcs/res/drawable-hdpi/icon.png | Bin 0 -> 48558 bytes androidgcs/res/drawable-ldpi/icon.png | Bin 0 -> 48558 bytes androidgcs/res/drawable-mdpi/icon.png | Bin 0 -> 48558 bytes androidgcs/res/layout/main.xml | 12 + androidgcs/res/layout/objectbrowser.xml | 8 + androidgcs/res/values/strings.xml | 7 + .../ObjBrowserExpandableListAdapter.java | 99 ++++++ .../openpilot/androidgcs/ObjectBrowser.java | 21 ++ .../org/openpilot/uavtalk/UAVDataObject.java | 27 ++ .../org/openpilot/uavtalk/UAVMetaObject.java | 50 +++ .../src/org/openpilot/uavtalk/UAVObject.java | 117 ++++++ .../openpilot/uavtalk/UAVObjectManager.java | 332 ++++++++++++++++++ 34 files changed, 769 insertions(+) create mode 100644 androidgcs/AndroidManifest.xml create mode 100644 androidgcs/bin/OpieMobi.apk create mode 100644 androidgcs/bin/classes.dex create mode 100644 androidgcs/bin/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.class create mode 100644 androidgcs/bin/org/openpilot/androidgcs/ObjectBrowser.class create mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$attr.class create mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$color.class create mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$drawable.class create mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$id.class create mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$layout.class create mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$string.class create mode 100644 androidgcs/bin/org/openpilot/androidgcs/R.class create mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVDataObject.class create mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVMetaObject.class create mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVObject$AccessMode.class create mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVObject$UpdateMode.class create mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVObject.class create mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVObjectManager.class create mode 100644 androidgcs/bin/resources.ap_ create mode 100644 androidgcs/default.properties create mode 100644 androidgcs/gen/org/openpilot/androidgcs/R.java create mode 100644 androidgcs/proguard.cfg create mode 100644 androidgcs/res/drawable-hdpi/icon.png create mode 100644 androidgcs/res/drawable-ldpi/icon.png create mode 100644 androidgcs/res/drawable-mdpi/icon.png create mode 100644 androidgcs/res/layout/main.xml create mode 100644 androidgcs/res/layout/objectbrowser.xml create mode 100644 androidgcs/res/values/strings.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.java create mode 100644 androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/UAVObject.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml new file mode 100644 index 000000000..83d19e96c --- /dev/null +++ b/androidgcs/AndroidManifest.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/androidgcs/bin/OpieMobi.apk b/androidgcs/bin/OpieMobi.apk new file mode 100644 index 0000000000000000000000000000000000000000..87a15c5e83805a3bb48265a78f9bd9154813cd35 GIT binary patch literal 148198 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⋘Lj~+icr=hU5&=G=F4lyq? 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 literal 0 HcmV?d00001 diff --git a/androidgcs/bin/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.class b/androidgcs/bin/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.class new file mode 100644 index 0000000000000000000000000000000000000000..306bc08c9eca5d510d01792bc7011e1ef8b75cc0 GIT binary patch literal 3092 zcmb_e`*Raj6#i~rn}%%(EhN+wXrJyJ1yVD^C9E%I!J3anCXB^P5es8!I)lWI66^)o8k=tsx?i_5Jhr zc*b<|bB1HS)LS67YB$!Kj=;cj>9(<9aMxz3JjLoVbxOI%@@2a;>4z{y5*h`7|OoVYh+O%QfO4o1j5*Ch0D)`*TCBm{Prth#w+{mzPMUz4Q}=r1)YMs3lsE&1**M%*=vBu|$9 zYh7h6SW1<;Kq^}-j&#+FqA)8ieR@?n7aES`S`8LW6uG8q*jY=oaf(%es6@I%dfSVn zv(Q+tv!0P`aipl>G_}#;{`_XeZ2H)iKp&6In|0H+DvOqRPau;W2@341?;6!1H>Whr zkixb|{N33VN6J?^43~`ijdhnLHSRbGOygZCg0p^-l);=pddu-PcmlIHC*5^vUC=R) zi>!`gy4|2`jgI~{7&0&8&dU~fA^6nDqJ+7m<2{rF5`>wzjSb7a@6n=mujsgn1#fr3 zs8-oAlpXmbqm*)})}&0flJTnR%KFMSlKFJE(pC-y^me5@*8&6H459>gn%cgkt~u4o zsN|y)Jc2TRcU1U$NTVxH?npcCl?Eg{%SI6h5F{0&o z)7oUjU6!MozHHXm;@*f+O-pX{HNz>ZwPKaih52$ZQEsf;74w26htcrAd@hd4su8GI zXAc)@hU1uyhOY$d8UNr%n&HH-CHi_6zqye44o@=*z{PVb@Z)f1tb+>EBaciuR|=k1?2wKSO3I z9Pu`X%G~ws*J($6dq3@%Zy%(s`Sx&`7>9GCkCFXdrIF)ripc>PL}+D@W+M!tihUSW zdnzG};RxTDn*2gAT_M}aPkWw8%WL-J{=nhP_|W)odB7G3$edhaUdQ*KWAsF1T<27Y^XU0o+Nv?Zd4QAwryFc*e`}`OMFV zTp4=A{Sa@|i&K7#e&v@{Z@onC<2@x4Ui!%(Ueb>jqQ^Ua`W!ZXyr0Oad%yoA7YEc!`3B%a2k(zzCHOvVOdxy(=tOD!z7 zU<}4O;rmqXb1Yv0yKzp1y67DZ?w=0$PWyZlnELokolRpEYl_Jx_d0zSF@PHi|BQDs zxMC_`H-&X_Dw9hoPNk|+iqifgc5Pcixi_|o2`T>*>2q__UKP+xYK}bymQlwB0tt@eL?4@j#dM$gCw5Rfy zxTF$Dh%-M5F?QTUl~BZGXLo1jy?Hb9`_K2E0A9f=Aj8m<;h7}^?gwHhmF4(eD1~?C zM%Kr{Id@ejl#_^u1!NgEQ?KO&fpz36F&65IA^%4BLcL|sT87P#?MjcApy8g59P$k1 zzVP|+=wiUbQ)e*b43)lgouTc7B7UczS@lIk46XkERn%rEO1~R&M-k$7tAAUZjI7Sc z_lCS}*l`)_I#yBEt~Ia{NQ90pY%{DzTy>?dxUX!%CscQDa+z2K}?} zy*QwA)$?MWo-t<{)3+7-+66pesNYsFp$2kgy}JzPCsx=OQ9@F{Q-;^e^rh{-n|kCq zf#P8aHPqvtK4+*d^tv+B zjrJPI(2e$v&H}wGvW#rbyg~6>;x5q{yMZEB=+tKcWbf09HUnik7hFe?wHc=!v|;~%JfBGhLe4)&*LEU8rl#kHy a5-nn^QJw*l1Z+_Sd)Oy-h6BRN;P5Y5N$Z;c literal 0 HcmV?d00001 diff --git a/androidgcs/bin/org/openpilot/androidgcs/R$attr.class b/androidgcs/bin/org/openpilot/androidgcs/R$attr.class new file mode 100644 index 0000000000000000000000000000000000000000..f69a8e17560897ad1adaae18fd15a3f75ac850a4 GIT binary patch literal 358 zcmaiwPfG(a5XIlL`$yN+*6KwsB6v^_2G2?_g@UjsROvmt8`hLHDcRKTsA1!MGu0k9OlKHP>NSvbYLNg#6AJ{Bb5Pbt2CkTT036(JxV&TPFV?$y>LNq}`Yxa%}EUvp`Z%<2qla+~uKfoVl zoI5FOjLn<8*|%?I-sji*2Y@s5LX-#x*3BZjlxC^4^^q`BXVr9;q|x{&vD&&26+(L< zo+ap9r1F@=E|(iJs@m7Yz`q7s@DqNhlxp zCxpttPGucsv>I4PgU}i&Bd@c^Sh_nAYf0#gY$EhTIF<8Nv*PC}B^-|a+y0zTzqOf5 z0mR{7!2kdN literal 0 HcmV?d00001 diff --git a/androidgcs/bin/org/openpilot/androidgcs/R$drawable.class b/androidgcs/bin/org/openpilot/androidgcs/R$drawable.class new file mode 100644 index 0000000000000000000000000000000000000000..43d486e461eb753c8772c3c239c81b3a83a13216 GIT binary patch literal 418 zcma)2O-sW-5Pg%jNsXzk^|M}8upSJa6)ypyP!y`f z20aR1-pm_j-n^O5ulElC=hzS65e|(lVzZQbsY+AFLg&_~yvV9}c9dK3Eas&Q&?XEP z;z`7%&_#SZU&yQ`v{hy_fhL4rVsuptU8ka4$<~Vp5d2G}ReeQhos3g%PfRXDw9t#N zhLF&oDlKnTk8^47-5$blYBEu#!YapqitYMARfOZ|KdfF5!aK9FnY>m`(4U<---KwQ zwX{hos!CP?b_oZ6%MrT2xAUXeKR=8xLI*y_fSHFbXXNf+T<1#MaG-PghUm3v*Bb5Pib|rwD@hfzTN()WVCk#^w?e5~2wj`n_X=OO{=-x2Li4H(8lj_yhb= z#<|17#@M{cd;8|?%zS>me*iegAVh_5VBIXTOKFx$TOSECbyiJhX%>x-w0O3;4^bs_ z=HgLAT9{dMo6KeE3Dt#AhCo9?E4C){!uW~MxeQ(cfJIvx6K9_?=?aku^-E=xzaj+3 zClk(y?Nl}ppxwjG$;Z(tY#HxQ#8R2mB@AMah#+}Vw zDz8-$S0A4hs}Pz)W2B3<$TFFQ*e4AB4&%PnG5BsgJKwK@K5D2l3rn`feEk=1@Cy|? tF}Bzdl^m#@zG3sVZ0Rr-0YDF1jD?jA=wh2|1v@3~Vvp-8uE(GBzX5PkVHf}a literal 0 HcmV?d00001 diff --git a/androidgcs/bin/org/openpilot/androidgcs/R$string.class b/androidgcs/bin/org/openpilot/androidgcs/R$string.class new file mode 100644 index 0000000000000000000000000000000000000000..d473cb81c8c6db44be5035f5848de2cfe8504c66 GIT binary patch literal 445 zcmaiwy-or_6ot=)g+&BG`~@qc1zNbV*4U7kkPuDK(3)YHEJKEw&CFu!Gg+Bf_y9hX z@$O<_V{FdNH*@c~Kc8Rk9{?`V3sE8*TbD#Ol_pi%W|1&6XVol;eKbDxnNubS5fIu7 z@hl=OOcLEs7c$NWHIb%IMl2MXk$0=*RJuno)$H3D*;wd_a4P4Y#~_<4PdFL9d9xD|%C^A%sO3SgGdiTks_zeO>@9G{XprRHgYIaOv)g&O0kk^hq#v3*V9-6I3;+NC literal 0 HcmV?d00001 diff --git a/androidgcs/bin/org/openpilot/uavtalk/UAVDataObject.class b/androidgcs/bin/org/openpilot/uavtalk/UAVDataObject.class new file mode 100644 index 0000000000000000000000000000000000000000..95af7d70364676903cbaee10411198d19f52394b GIT binary patch literal 1127 zcma)6UvCmY5dRH5pqx~cTC`SeYc(ECyLY?3*$?!sgtRH;fJl6cMUw++nG)jFPb-tX|-Y8@Nbv)=R|5X_(F<7fbN%xRi+1H?FWA=W2N` z|6he0P)RYfmE(^oz z_4#Sbmr+KQch9pztl&CF+=3czFqqxlMBPMj{pDw literal 0 HcmV?d00001 diff --git a/androidgcs/bin/org/openpilot/uavtalk/UAVMetaObject.class b/androidgcs/bin/org/openpilot/uavtalk/UAVMetaObject.class new file mode 100644 index 0000000000000000000000000000000000000000..7234b135ec1e4b601e8d271c48caf5fa07bd47ba GIT binary patch literal 1440 zcma)6T~8B16g|@xT9yi0KvYCl5!pqc@zolQh$c-cCi0OOo~G@z3~YCr+1*Bc^!NCn zPb8Y?yFbc!XSei&v}&5n&fLBC+;h*F?XTb8egJrcViqZeRi&Fn)fRqRdMYeNyc2To zta$kR=(Py>o9d~kg;``6R>meKNeq)uq%Xs#46akIobnDYdfaaoca-u3_e%qz{ZLE4 zS#pmUGA~qJSV&_kj|ogN%vPi?_M%o*=mTE$1Vf>sYTP^GTAFh=mO~hSJb{-SBuKyZk~(nmCK= zG-Dt1rPfO4aD(B~p|3@typE{bHPs?Ncqo-`x3!|NTaRsPs@!UOvL-`2h}uF^77d`I zTBx*5h9y2Yt}O#Q^6R2OLe{tK*HIAK;(b!-eXyn9QD?&Dz6wu>SCOuXS2DhnLm$Yt!N*+?6n$Dij&^jJY0c8<02%sGbYp3A>m0eSv`@jJ)uJaT zFH05EwA)DXkjE7|8Jro+5{lVf#kDv)hXUrPkLfVq?eLb)ri1kz3-1bx=eYTkPDu~L z!gT86TRnWMhi~CFp&B+8mT@P>UxD4le@1aL8S7I|U<)y$+}uUfX$Z$cQi`kN62MTHGEKoAzkPkg7KtO-*~Z->koUv)?*s zGHk2=Pg-VJ2r=w+)IP&pv(s&7dv&$j)EIW&PRAFk=$2`lew9JW<$DZ~2C0u>HUUbe zAcb2D(aJbvIj2ra(tOvn2jy127pK@o1+$38APZwzfsCkF-Bu7ooTyaOHaer>q2V6z zL(5=DtB%gC9(PS)2b&2AV8KBY?y*K~c4c%Tm9BA^U4|hc%RjHW+oBJb|oYfGY09U4wTBTG<%eDz~6C8@S58U>)4dIU(Vi4Gx8gysb1C{7`(N4EHOzk&7B z^U?*9=ST;}QY0`kv){=joguCDBWK8H=UDkdh#9QXKN)0O!aOoq!y*mg5rbNKoTEfB zLX%wB+PJ{_1RSLRj6q7Uma!qklF&Q2JBGiYLIiyI3@iQDQsJs!5sKQ<`Xx5EKa=NL w$~7Cikr1a#e>~jfxNVCEvp8Np&J5E9&;M~G?Fz;YjAPG-z1f|;QZ!=dG&j0`b literal 0 HcmV?d00001 diff --git a/androidgcs/bin/org/openpilot/uavtalk/UAVObject$UpdateMode.class b/androidgcs/bin/org/openpilot/uavtalk/UAVObject$UpdateMode.class new file mode 100644 index 0000000000000000000000000000000000000000..5e520fa0eb6d9ad0cf329fa2572250588a3e365e GIT binary patch literal 1333 zcmb7D+j7!S6kVqQ0yMqRN-eF{OSM2R5w-OK(}AH;8M$@O@?7jBdJL~-T`Q-vY3eQE1FeF=cQ*O0&t8JJqNA7CJ zj%I$4tGQZb|4?r@OV##)=IEu?fiA+wFn*{VYqF_XO0l;66d@(I;7`VGrKx%#juys33MX^(;{_CYt?mSm~0 z+UnX3{e{5?I)3Hnbsk7vsz%e&oUTnDw>*42IWvsZEh;4yEK9dtZF)zpSM@bu~ z{un8UQT1ioJti;TaU*yXU6sC~6!pV95|b+nXSh2c2~Ys~Ns_x4vBX=WvwOJTPv4|c zJU!aOV*Ry{yr^fm%91dDj^)))^yO00B^$ev5F*R0_c@Xj!)t{jEO`$3JJ{dz1Uz&( UA5lY`djp$1lkyp!;8}L=7v>5tU;qFB literal 0 HcmV?d00001 diff --git a/androidgcs/bin/org/openpilot/uavtalk/UAVObject.class b/androidgcs/bin/org/openpilot/uavtalk/UAVObject.class new file mode 100644 index 0000000000000000000000000000000000000000..5e228155303a29cd063056a485473fdd564000c7 GIT binary patch literal 2255 zcma)7+j84f6kW%5?8X*pE=`&XX_}I>veMQKv_P9Q#7R;+4w9T1 z_>|5tJo3T=x1xuNphhm`24GkU0s;aMRcmp@72&*p2M`p|R zm1_-CS$l;9{*Spz>^C)ZB2Vx9#};dkpPtyBh>m6`QpO3|?M<+a6c)%UPb|~6zNH`; zy;`iPV()0k;fz2hS*v+fQg+8J z!xEPBcz{|C>jFLT$VA&Te1cCoA$z9XlB>WYy!s0Uo}q8VIKYMP zQTP*=9zMs!UqN)>8l#g3C_aln7+3dEG8muU$E~>BaKL_)uoqZpjED6i-o`lQd2J{P zMpzJUF{=K`xXq4K7v-SyRPc5OGt@(17I!16bEK-iWsQ-2%*FNcL3EP2mjnEPa90~Y z8|cV;n+%l7O0^Q7s$z%n8|HrGOHwI4fYHJY5sVQ+`Vb9;X1Uy!)7R{#J2 literal 0 HcmV?d00001 diff --git a/androidgcs/bin/org/openpilot/uavtalk/UAVObjectManager.class b/androidgcs/bin/org/openpilot/uavtalk/UAVObjectManager.class new file mode 100644 index 0000000000000000000000000000000000000000..f4a6dd7e4e5820644e459a4aa5652e5f2a69beba GIT binary patch literal 5422 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 literal 0 HcmV?d00001 diff --git a/androidgcs/bin/resources.ap_ b/androidgcs/bin/resources.ap_ new file mode 100644 index 0000000000000000000000000000000000000000..2452fd26f12793bb5445461ce339266070961506 GIT binary patch literal 140460 zcmdqJcRber+c%D=GpSBdWRI)}kv)@0HX%DZBeG{!h=^<=BQmnGH)WKWj7Vno-aF%W zyy^43uJ84`@9TQp_dmbK<9F8CIo{{{HIMN;j^p`CLHZOnAqEx(3ZorcNjPp``sHOz z3=B^!3=9Gc3=A71TQ&I}VN$j@2l+U9op-kwWf$&exwO7=?xuMHGcT>6kv}V9O!GdEkiwp%Ny?<$?|v)hLzm7~z0dOKh#YX1 zi5!nf4th@B=qkIf8og9Q+LvGaK(c`-_L-;rQ$6E?nsI0SXSVwKN_{Kco_X>w_FuED zXnL#-Na>lZ{6 z{%sY}%T6Jju!;?^ie&%3idOn&Mh15JHdck*2Ur{aXoFo zXD)nZYWjp%<>|PB8TIInfo!B%2AL2hlT2`dl($L1r)KFH>($v_< z*6vtj!#`Vgi=zFGio1JcpBPl9~I+NgaN^QrXP_BeE!~9@)$iw(B_HD5N-7odmLEIZcVYz0)Up~8#51zUB ziGmlKZwJraGjWtCgVgk#;ORWk3pJj3qoh0MNhZ{LGxrz?NoK@jOPp)H${+VD%hQ@< zekS9U)A){dr*v=1{jI;fsUs;EMY-p1aizNHdOe$@-Y1r!u6%kygD0~W*yUuFNZjwkPrq;U(T7;_<4KkO>wtqNq2nI@9Cs zUHs+5M&hjOW*^%IeUMy-bGl2~3zxZ?Hw}IL)3>%JN^(h~AFI$RExy~n zRQ+UeCP1gm-Gk%o{jSZXnDgjn;!_$_QQ9T5B@OB6B0&|Ev|B5Ar-p-1&$G%4R<_Q5 zED<*&?dW%Ie0zWOWhq;^YphMHm;0p|o}*;Sj!mYLE$f>ZOxBq+Uw=$#ef_5DL1fAF zU3YV@lWuQ+%WPLev!*w$=1?hXvA9L=8TUcCbRyTXfw!A#<#_QT*`GtT@%z=rpLBOa zbo%D)PgR>~HRq{*Q&`KnpLpLr$3}#1B-4#3tuA_`Q};x3K}nD8-^994cf)DWTzFnM z(OfHg8v`R-Ry`YA11t=@<13)r7?_~h{_y4ua_ip*?>}$g6?y*@o*D4$g69SJtsp!} zFl;c4Fl;f{Fbv_H9)=@4^)W2qyBqMYA>3mM*Gw@CFsv{vF<9ZVC58#y|KHvBW@rTMDL|_h@Ebb}DvaCk8Ce}G_|6bMOJdx?P==mR$GB^?z>D1V&|x-2MNn2N}p02rfnjyrSS0kD>ANs9)kb8fmdWK#PH;Xr#L(x!qXC-KJdhbR!;N*dH;_D zVqlyOYqKORp1dW-$9 zcmJ_YuwJK-um9(ElKyq~|E?Wmod0t>EB|9V$o!DGBKw654*C4g18H9iKK%1Nvd2{a zT>Nidk##(g+2hw!$o#0 zH~;jBT>D?m^PlhkPy77a7x@u9ka;3~!7Dku9Q`9l$alz|A&-Cd?Vs=d-*R;FyZ`zx z(l+9w;Pn!6?ce>K!QI~lxCIy($dd%FB6#1>M$b`C-@@p|W5cJWY^DZQmaI=LO#&3; zB+uiL;KGm2OWhM!g5~i+o+xBMyK+YY$Tmxf-+tiqYhlRIPHWR^`>5ls@EgVGAC@@uo(eW149){cf(}I5ngqovFwx#5-ysmwG z{elE_y1bctsbKQDdWli%^(eYmw-&e0_?;iR+f}qZA0KZ~AYQRv?s#jPbHwJA0%Pja z$7W_WQf5&R%uLh!wKgJa%K^xSdCqXt%=)B`Q|@kWA1$|&lar_X=4CgaKc}axtQ?gZ zcP%HPNG9yLIU)q2@$2_pw7ZtC9jHl4O6s-|)}^JTyxufw&f1l`_HM_>4n?*%MRNR|4AFds|O4a0ZMDAs$ zb7!6vfNO8@)sbs9*A7Ix)acZCb&s#U-w!*K?Yao<%8833?H1hMOGuTxM)x!rx&BDw zmDFB9Dy6-h-AZi$vF@Z)cIKZ5gH4a^_}cc!kD&KW1i{1`iMHrp2rymoW6K z#k+1mw*st_9&S=0p0H9CDoO%Ih|*!yeR!z!XE)fPlhw=zZfySUI*;Q))lB7zT=YjJ zuL~_o!o5UVYpiAH1h(f#)U(ot=aGx}vq$$Trp2UxH_BW+pg3ub=2!GL$I^2)w`qN* zr&ENP(~dVmH1(WRMRiKbcxkjYs$-e{7i;s~T%-x~WeK_)dsRb{B8BJ#k8h*&`EiWM z_u_H1VH(2oe7-A%QIV6)Be&*+{Qc^f#7fW*&PS ziMZMMtbCn7dc?Rnf9LJ;b9_W_aHak<9m7L?4I@d(ukN$;v_8zuh~i`D51$!YmOuCV z#>BBrxw-s&$;3yDnv09eNQysK-h-7I`4ts6Hr=Fyo!v&YE{4@RJmjaMTI_F^Jt-qZ zdoLb;+<(XQ%GHj}?rJ z-rLyNM8wCt^^0^bZ_n?nj?XPE^>(I6{umm{Az+YWM5EBW7^1ML2L9k+Q6X(@GVO6Z z^6OLW%C~QS4%(MX>_{IT)*%;mdsykP*yVNV4Dns;<8_Z=^7Zwt*qw?~(bgv4GFWw~ z{#9ra;;=NBIaKLrZf6%kfPK6c>^}+$3hcUNc`|Eibo}(h2Ul^P-zFDyQV?)l>M40L zaEqP&lhmo>CdLv1z)kbg@p&Mu9Xf8KR*{K9q+$qU}R+E zdn>nb(w3H%m%sX+E)DWM87xy=TwLULUc1I{83PfI(e<`iPRZ>-+Yqt~l5JIKcV1kW zed{=^C@Fa+#Si0nV<`W4a^Vd*jlZf`s+gy-$r*h>OhVFSo>!gbIP5GL9v&WVcOr07 z6^kVUMHc-9WllM?w6uHml!r;B!!FV~dC}n)k7qg7*Y#ey*kyCB%ykGB(`CJ#XLBmf zYHbGhxCOMwR9kFHp2xxbO##^rF&P<|naw`kzO1~OmIq20{!ga{2L~z9AnDP0A3rK= zk9gFwT#?qAew6=kV%4eW>2I-DuU=)AmPQAjI-XktYkGI4B!#m$Yjhy{H(Oq^H=HKH zNDtlV^7AllAFSg+>38Im4uAOY;kx$@wv?3A8xfBh+;iuCba&V9iJc5fU~O&9ZhOe_ z>t@C0bD^-Ry}hdHIjYF^e17y=0fVYdMjX7%q=eU55!8HxpIqv<;Lg!152IoY z)g#s@v52i%f4iJfRTVFafvB+P#$ym!8yk+>T4^ALLL1-jAj@vZ9d{P{c-G=Ije$f2 zb%f3yMJod%hb3KIU8uiTa^vI4BBP=%H4rkhvi1_l3no`o@YkIfh|qw}&$HpLUnl)p zstjRDJ>Gh%wTCQMii?WS4YxF5AQbL9dhb(H(Wg(;2M@$QymgYs|EhwL(mRF(CovE> zAI#%5t;@^I3_u&d9$4%>bx|;BvNf9EzhB3{c|#)R zkHH-$t9vk~R&4g;daTUgHw?tKc$!AV#bp&0-SYOQQq#7Nq;Q#`rek3EJC+z>8KPG* zMn*C)%B`5Y{&$U(TPJNYVLPd4cGJEXc70IE z+W3*@uEHJn>SS*|^<-pb!meTCof>8XaTT zzO@G{HWR>*@W_DbSXiH0I~_if>v1;aT1Z!5 zsi8ru4_R41dVACA>cr|!1TEpJUovc?w?C(;sp;NUX>HEkz$>tFi0fMYkd!0}iiwT? zB3m_UspgO6(6j9!nX9Lf(NIy`)FuqPa-)kjMDQJK^gr#bFk;d&d!4oZ&PgCURRBIR)#)_U?#*ravYwtRXHe>{4-Yar5{p>>l!6 z=XC)AP1rzeufV97m<+3D^O_Y?Z_Gh65GjA$Fhj*UpVng7g;+AzYja|u736Qqx*(NMy7BL+~D6Grx{x4FErv<&G*kVC>_`= z&U+?XI^;mwcjb5-p+U3nVpv3{U}ps~|rot?`QoW{-~ zhUR4Op{ZqM55WdgvFC(^hi`trb8)tXIq%xZSZMBoW2Am05z}t`Y&B4~C%Sgu2rM8L z=JDhT^Z4mKZhU!pZ;Gdu3DoFBVB4_c+S6XX#Pt>xhn-Z?)Qo!> z7zpZ#tn93+x;j(VkNaqU;>^rUm!01)>>Dqu{oR!AfZ2Ec;#UIin)haRM%Qf6)qFgb zW=}DHr=mxnv4qx|Xz$C*Gn`B`P08K8MoCEtg@vC30{!I4lMk7h)PJwxrabq*a`x=m zilf6n_Vwp^n%MD9Rsd;BpV-f`YE@#$6vg#eH*@|#lAdQZpvGH8~R|<#*2~NJI0xe%{G%lQF*4=$sv(w1dV!=&-LVBWd z2M-z<9Zi5e_AOFPC-Vh`%f062<`Y5jmj_!E6h>tU!uTO4=M~%CW6fJdHqH@Dip$F9 zGsPDD94C`$xLD8rQ{nV?*O0U_aH$)J?1TEAC{li2M#jB>fBe^g&z zUwS~mSsW~{i-(tSeIwq!&54L0#CnPL)0?T7&sA1b3_Uy;Inqu^N%6rtUL7qN>p&SV zQBiGe?O*u@F94$^fByVg{=fvVBY3aWu`&J2moLLy#bLG4^%)fv8lW9}{T=RUOG}nm znEIZbKYtR_oW>B%-bGwPK>>%iKYDz8+y!iEPiJTH>guZW-cme7nxf99u&y z;a;mNFSHr)Yhd8-a;a;vMklzfNyW;rM229)aP~Tm_T|sx;mP!O$jHj7z%osBB<5vj zvxr>?-`a8z+U!wY`*YxfDb8eTX}NR}iVJ9I@ZDTi!-C!@&f1Z@=>%7~+Wkp3Hs=Q` z-A>gy2qg5_AE*2=Fp#ys?^Zr!DVC^*gM$OA-Z@(nE8`}dc(_V=q$ngL#JMGKC;7FDi%XH^5WlR9Oh!hAzxkunU{kqxc$kUt z=0-n1$3ET|R0yo(4fO&as=AqJk)v{lfb)121frrcQ&Pl4M0Dz!@V{!Ep8Eaz$Ru+wH{W+)mwNbGDZRW3{HTVJ?v z!R%mf6W3Sl`i&ct>XDpDpzvTmka(?1hs_HE->=pi!!t%vO-&M|S70?#lfkD7B0!|; zrYLf_8e(F{(Bq^ENEq+|NHzL2S`UHz4TyIUSgs1kPh>~=itPblq)Y4|Qu!*x!SN1c z3WlmI>EkzF_gWA(%rgPY3$Bfu_-qV+yHuN&JtI7n=o z^ExiYBRd2-3}$nEq0Tf4R2WRw;z+IT^tZRPXsRG&;Nn7H4Q1$q-c{q(uz}bV_vv(x z94?M~GkE7eTZ_t!gfxVY{B8m&^mhSC5`J-!vKJ6qTXinv4ta*1?sy#Z zdF15gvdV4Ts@$8)+8lj;5ny=$yXVy}$9*DmW@2K(#y>sZm)8ejxBk{9#DJ#bUtaOM zZehfGBQ1jr6a8M>?m5i1dl`K^XJbu?$0kk z;6K$K7YSiQP!OKn{w)CIW~Qd0ee*_rYA1J^TUhjfsDbc-z`7sI>wayo$Xi{te)6kG z>du`zYfgfItF^GZKN)hEZY}f!?CM<_sx&Zrb{!qM%tr%>w8CG%G{jKhFfp9xpCJ^6 zkbEzzc8?i=SYY5I5-x6TGX$@Ji^O|Ga=bhmCn!TtTP-GAvy{~`ebc#G2a=8%wY9nc zG9dyvr%!T?p5E-UHx3vmWnEoLuVYa^)VzDw_X?Yi3|en3Ze*W+iSqg|*rr#cJZ8Pw z>M*vccQL1-ahN@fdTwrRtdsB)p+O5H29?=O?OSf&5`?lK1A=bYWpUr@PMkv|V628p zo~WL^$Zgj~Xywx>o64aRy-Y&;b=N%mgZfQdV$uJO@?b_1)bX62OgO*=#F>?q#jtxa z)kP>`h(3UvMAvzqL6FR~FQis8Kl2T+SMk9g{3>}8=i=%*x$0zCI&jwLCEr`Q_Cyg~ za3+wFp+DX`f5~%KSQPB-xo-P3cgu_1$m^3vC%yx_Ny=>jfpGyuD=5R4u`=|4RIUpN zX}fMOy=on@^kQ-q!NFip7elW~s=^ z%5vb{Idg%G3Yq69L2TQl4l6OdvaMg{k%@`&XgxHp??#WZeDm}={ujEL<>kJ;&G|?$ zkPt^nl&8PeBL>;Ke*Jn^f{<&O1Q==0ZFQxWk++u3?`!ToQ&(=i#rIJ+St=pYccyx_ z67d~{{UH3{DmGvb&<#e&xQflA!Bjuc(a8l94&wr>2EoC1&@H>I1$8V;1S1S{#Z9o7 zskGEtF_-Vg6&O8eX4f>5y%CvZ_FiV|+V0*q6JZP$vv?##G1|_Pk=Xe3aokUoOiUPV z%XoQtVHTH`wpx~EfjD&5F-5@mch{%Qot$F6rhv#&)x<0`+jQu>FM2-`owa7He#usN z`11Kei&!ojm0^}UVasj8OoUW|;=YiCL2#dV%>Lnat(u32$ZeTWQK}>%*R71gLS^ti z5Oex)sPL2<7a~a?Ff3pI*B;}-+BR^TS4cL$8c{HtC$O35h;E)b96WlZSJIp?km|EG ze>t8w)N1ARwO(SHf*g(F`^UlO=@U3X$kW^X=;>1h&{+s_gRaQs!|Jyu2x)?t{n**z zMbwVUftWrpzEO?IepQ2xYmgZ_^J{kN6!~gs+pOMm-K6spjzn;)NSAb(|2;5Y8s#>0 zARn;AJ;TFt=8X4T)RU_!utqm*#VWjq z^?cn7;x9T(r;*Is*8F38ig&=Oye7^hGowzW{ccAi4%={}ww?Ymn%JnN!+ z>}FP0CelY&*>BxS1s?>#cUPB^#JTi2olawA@Qqkro)^gZ#i>NIFV}r~SnFo8)v8^n zk*QY1lx!E9-Rv9I{BCsTsxOv>P!RDBduz6eQunj_>icD6<*zu@(@jkHrS+Fw=P!n@ zO$yWpr}~qDEl=U#pjRxnv^_#Jv#)YnE;y>`wJ!A zYZDbjse|4#r6hmy`4Upabo8_|o=&YfK}i1W`##3}C04#QqL#65p<>C~5<+6x9-R0T!(rN zhFfU8jT3j3rTeNqNH_>5fTRyaMGxr10~FFkA(;&RApPLawz;99k0=bOm}rucKYR5Q zTXWb0DruW!Lt>6fV;Gm(*@XGY-10kH3ofyjx-R3&F!BmFMS3>5+E#Ex@=ja6zp?8P zso;>)cJ}ITrc`>6=wgs)8Yae(*n@?8FF(czxt0L@1U)ZsTtDDY^xd4KDy?9gLes-mFZ-hRR7!N*s|Des48=-|OxVs&16+FqMZr)j{T9*T( z>5U3UGC2H>!J7@gui*OHt&H9V>?jK`^}ehuT?CVYmR2^n9z>c52v|ZeeA%}So%X)m za#*>H^Yx5jM*>5=#lZrpj_W&%*~>OpbTb<&xRAc+m~{R0lpgH|5gKB0r1{a^ln>b4 zX0&hKo?xj_GB(+8`xy6jc6ssM8x==)$u3Me#xz+SorEYhT{*NKhoE3K1O>rVG)*%z z8NGSBYq!K2&nS)3F~+A1!}ng)MSn*UIt z9+fJHSltQINpRgaG>Yy4qy(!g;IQz0YjNN#4Hi??7TX1e6FjUNOxW z30S(d6dTw#Yug7ZMen~KEUaaewz=IPcdj}j%v_dPq?R^Qy5>;M7YoV*GO>}&Y8+gw zL5C|ZM2>wue)5+uUy7{9CEf}+%29;8=&Wl!5a+~GQBz}PV32g(T2Q3=Bw^;iYF?9{ zf79|sDT@>i*fs5b;~x;J;RU_zYzVmVhIcqQV4NH`=oJQNOTK(Vf&)fvG$L4f(S8PS9iBPB=tGp3E!1V5X?+G z+(-uzrp0T>E+eJh|1LYDP}KmtEsZGUpqJRT^#h==S_Y8U52{=tV_W z7xcUfLg{E-_gJcT4Ldt!+?InGg(e*><^!K^Q>h# z=KxBV$6SEQt|&M8+z*k{9rk3?dbX|VMH|)RQj#v0iGTCSmpL)3W-CB42Ha6^j%Kmz zwxzc}$I#HwuPW!lg2F;B^IjILa=gEIabOV)xJXDED3&Tt^>dPW7e%FeTWx${H_vx$ z-NcL4E;Q_TlLh8vGPhcJE4!S7&XAEXM&Y{vW5WEEx7nr?bUcGuJ-y3Kp|zs)ad8TV z8y988DlWC;h2JPtJ@k4$oo7FaRr7#7)~-+6u^FlY5;0Z#YppWTfl4}gYH>VPy`MgL z0^V_=)J_Bc_fbr#= z+Z*d{rKnnEE|~s$nNq|a3xldA_S=zc%%9TxCpxd z8UZqwAXbDdzB-h?(x=*fug}?>zj$%pMC8xa%GWf;>|#4ojTZYsUn+E7>lL&_sdE|# z+$Op50&JiSAxoI+)^)@)hiP1|AA@DccsHaQ89!goUoXbc+N3q1n@X*bDB@wE zMoF7SEIAYI?w89OYgHMoE(T@BO!-UT&JSuXwM4bXf4cCbn~7aGsgV3g9KG`zVt6DG zE*`VvCMp$*4s~sO=NNi(?`%^en=2(P+O{t)-Omf< zD!=E~p9TPsdv&LqSzYl3~VJ|H#$dXJ=8AC2Eqcr;M7~luz!%&@9_SKAq z=26+EllUH0^pXV@g&!ta)YBR&DkqwBuSx3%r@r&3eL;6qEx`6jD^t3b!KC>I zhd_7P$9hAj19`%=5CUvr1x?K?XdSX`NW!kZz8)K2ew*997D+eJN(MK90?pc8YH1v{ z0-4Rri`FBCNSFrM7Hvj$rsdAk3DTJ`+VtCgT=x&3lK8ddsu!5FtBCDx+VltXV>3tC`5mrTz9C=sZkb)ELg$k z3(R|2^U|=SHDQ3ob;)()%Nd4mW@8P#+Z2`7`hoi&J%swXk-r&Dd|s>^1p?xB)qspXF$$B`URUa|6f?d|QbFI^%>>mueh zVek3G z`8}!ins-HDdnFaKWP%M@dr_QgOGi;2KE+pdtN@}xW&0{+v3vOn|6DvnSy$dqA-JrskQP?PK!aAqXe}K0ZF(<7eeVk_R1}-ed1O1`5Hdojp z{{pvcUEDp|?9Mk6j1N;Id@nKs%`V}-h;@w4_!C+k~#PF*Kx>L zxoq{D^b1o`qOh?b!&$nuJdy{Ptz3&0Mgh6T>uhX&z`4>a72Qcsnupcd9F$@7#9JKw0BMz??J-nz^ zsG-0X7Z!fC{bF=-GPTgr{yMf-$W>zE?~pd6g>nsqM-u1Q#56SCfZoD5=xY<%Zi9x9 zo*?X(*_rRBTcs9m;)S;@Spfc@_^{)B$y~KHN}ZvQR)u<`%zHT5ROGa|S!@_dZEg?U zNGRY0nJsbF8pfL?N6xZai&Q8#DsXB*)?ns&qgV9okHeFZ8mL*B&^QbQ!W3X z+VW;9w0TPD=~%W{4bvNMLylH;yZ1_0gg;EA{V|lzd#$G*lKPl)aJ2(BIFTCVmXx2b z2uTxUR}MD&oc&0Iq2BTulK4j4aaV6tH7Pw*S8u+D^xV`plDS%+*ZM}4I#58sQm3?e zE`lpZ=3AX=x%rZUSbuRr8X;sRE|ZC*D2$Fd3~}%&P3EfS948jW&RItqWuJ9&o`)`S{-DpE^>b9^vaRoFBIlZ#9&Ux{;#sEzAgsVS>Hy7F?UUhs(q}%;qcX9A~R3 zQ5^PWNqKIJn{VxnQ9(hH&@X4#;m(~Z#R&6z#vFYr}D;pz##5vV+r>cOgFJJ^7}QjNbBb=l*oQ=%&5-eS89hSaF$% zh(MgU8c-bqy-`{Pp`rLl1dc{!WM>C;)^&u2h9;+`UPCgY>}c*P>3Sx@o~GcVl+8k{B^?r|j)l)qOI{qyBTI+{-PPIk!v<%Gb0g z1=M&f)4BbqC7#z>Ok}rNegh~q zs=|pOqQdnM4!2xr1(Q&z@I9|^;7}!9XUA{@_AJN2t}TT}J2#r$Ly%IT|O*2_31t9oTJ^AF?L!U#fiWNiS#d>P`Ko zlc1ok`RSe?Kk&t3Acu7cE3G|KIeo*?W82YXD%Ru{ADprY9(|HxY%#=tu^Wbw=ILj7Ut(1OI@vi+WL?4CQhp-R*_Z>JJ$aSFcWG z1pWK9(+y;sNe!}4?*WoYY7SqPXw1KI`LZcgitfwEJOHQxmcwpsLJHE&)->tgA&vgy z`*%nJ!`$AVC*?+C8#ny?8S^(1`T(RSlMr`t$ms$L2r)QyP}U6dc9$g^NNTQGEHLQ^ zZ=Rwj5HBv&bpP<_=WGUVFL-&V**sfG?C$O^c3Ra3EQ$o2P<|Nqk@LFDtjfs776SDy z;J9^uetzaG7Uze`N=@L>0&x(as-XUyypf4X>+<$`4Yn`(=*H6}ABjqxh~`ilO&2;Z zs_Qrml3Z1*l-KTlJ>`^Fxx^1n+I^w616YUV=2?)cvj^baTd#FGyg3zuB?OjB5JOGY zmV|$Bjpi|l5V0OLT&Ec9og5ZmkH-0W;;nrvJ| zWaMUmZbKt2j0&6yph2Bv1%Jq8HF&ItY?x)w-;LFdg~%2k_3q2eu*t-HNbp;{bGW#6 zV1V40L`?D@K2TIl21bslzP=dbqQ;;9p>G3-(Yg&ZhzumY4?)l2@AS|vFWW;N|Y ziv(mHkh1IZ=g;H!krPpiHlPKz8PBY7B6qc(O%vW4N5#4DlU(qXm(#(TG`Ula&YQ( zObjFJ9Yk8zioghwpZ*sPx+ZOd=|%M}eqh&Qf|8%)@>dN7g`}+93bXs}styh%8k(Ar zg@2cjKmnEDr#Isr$6xUjIE%-Cd)EeQPK6RLYHpT7vSv_SMJiVV;<{k zZR!S-bGu);+-JCOB>qe^nZDLDzRgYZyAIDRf;+X|T~LC1RaMg< z7o8UDE#}`bO*+%{^Rt?v?2T}`o6(|Z)$oJ2BtxV^1HagGYqWrPp?q|v&q5WbMo`;g zfhuf5LPFV4D3mDrAp#b*3TAf&H-5EP!ft3}$L&|mvq}&eC@M`n-+g8Mrv*0zbQ$I4>LwitKbpfC z#+Tka1Ue)Db!S_j&Hw_24PbO$!hY8UMj1(qLe>8=VM8BB?7Md~Pkw&94gA-0n1o_l z#JV2oUoO_NYP$HgS(aFRX(R35;>7uO_p1T%+WNXZBw9O~mVx1;0OfM1PTK)n8RDUa zcCLKm_BUmJj77SDTYDFhW7H_|8!%_coy~zSfo-$lA0Nlpq7Rn>4g?U8$7sNk5V1lE zEdLZ6(=BJYtp#Tene2hjZK&NZTvfk4?j_GWT>k#^C-3|DGi>7b@4o~paT3rlHn+CS z3=OZPV!961OEe4w^;+} zq#H!Z;F*H~V;T*=;Tnwhyi-gjvGd!=<25@w8EIFKgGaoSo)*M@u)f8H&6j{GL@wlV zYs&JMTCP?mIhh-orCa#!8l!x!@kJT=j@=H-@~c>FQV`%mPerK){nPLzbng zIU1LVlq+cZzq}$X_Be9)7L~z;I0I+}2vb2-mA-Up zYp%v`4P#I^%G=3;4jLw<`?t)3O92~$&&IcxfsOw0;|G%MK{x@2vDV;G-v~IeB9i~x zmuSq4fVLqWDx65I&4N1%AQXMAe@kntGGI2y5AptnS#kJyzu_&HC8#EaJRNN~t*;C_ zU6tf;SgEUa57{!*`$>1y_$t@05s=a^z9vps9W}gYM-=#~JkcdK#oAqk_?VaT~pF_E~E{9qC zrR&j(g|ydbs?Zc8gesID5K^T_{O<0q%c$3x4I<#WDsC^_DC`#;7bqJWzd#|_WX$0& zfS{3ZdEu+!jX=ng0!t8YsDQf3C5D;kCvYh8_VD1;TB48yRatzN6v0=4cTLR^DN^2~Bu7Tr4bbm74sN_V;Jfyq2AMZtRjbV! z&HOHer>ocGOBRwC!x~d%C+_L+IJB(>0>jPC3P2)}v9Zl(ztHKOrxqU1OVdTXdw;1m zqNDwThTiA6-A5-gNT{oTyYbH9NnEp`l9W_HZrK>Fl#-*Pqj>H`&1x6>hUnghJpBA0 zkO~O4S6N?wKNFlmfWRciNeD=e78Wv~HStQ7xb0x<_f?x%IbxO}`$jDuGC!-CfHlciI zs|0$tad!91t&MLX_ESH;5)#idpxw4MFU9m2>TU=UF$o9=q&Xx=0|hzppg(c8a^xTv zXlAryF*K9BW90K^ye_&P?oJn5kAI1Ax>0D{uB51l&u|%*nr%7%Jpbl^NFSJf)TuBTJLaL61RCt zlAU@-h)FM@gby2UvvuF4UED;d&3nK4YSPr9)175UUNXhidm#^bKSfc-xgVVT zcT0e?2E<+-iI|)GD7P=uy$wExo4Q9Tz-UlB;0M-gicOz|0t&y;dzkus)oL`!&iKX4 z@x0PhNH%=r(`T3?u+He{=o;I1Z^pH204dmgr=D`okJR#YyK&ssNVAh$-&oAYm0ibR*12I%Hbg=rZa`5jcI#g;SbyuVv#M;t#Z#*Nb zTKz(5VSEXb_spkhb1SPph;CE%xPTzss-ORq!}_z+1?n`JCZ62YJ9*dHUG4|RJ9D&g ziv`@7c7Ox=pS)n0My*l6yyda%h#s<3d-4P!;&VY2xu&Lu>4+S0kbpPsc2@L2n;U=l zTcq+rURcL+JJW^Htb(*CNRLQU zSsOdmk3cyq@Xfe32z!tFjQn4$hE&?0J$pt%7Qc5sW$(|Q&8-2eEO1MZQL^EGTcu}w z4-6cjfIH|59> z5&YP2n(f_`6DKEUv3?`2++ZSt*6MuELAow!cvuH~j%AC7q?J`3WTY6NtOx23r$D?D zjoGRFK zOs{>=DhmXa5T=cNL6_Zw5UvY`nzDX+#G)543J?%m10aIIf6B?hM{_iKyZpK(O%O3p z!GXwx2&qtqbpH(9~`I2$;m0`w*ZHnu%`5TeYXf|&`*Y|)B$!wX!QH4 zhVsJ7?|O|=OY++oM5aK;1JVm}u&8C6lAQbp44*F)xaJ(#U*uZV%VHGkh^Ga*Gn)^q zUq)$5sEasxQ4$&#g8xBcGN8C^Zfr0TzWHS<2su#4k!NZET9k~9)1V}G*8OERz(TNI z*qB=0umXhfVmndy^~{bpFIsO>t}{ol3is!OZNJ`nw+hW5*7X zMz&q7-tET9va+uLU2_4?4)X7EyUWBB6usbskq`}}lj-Ko&{4MTb8J;fkoyMl{0wAd zAj>5!EG%RQI6!ECfK@o(LvR+Cn&!DjnI=@tI9MF&{3k`Oe|ta|k@NbAYB5kFn0arK zg???``z##|To&i`smziRRmkV|g1b!HcZ?T)reRfkP;&b8X@JK~_m=41KwSb3Ihk9c zyjn*$T~gNcmI1mU2fe`JFyIr4iTf*v8cTivF)_qH1Eo(JwPBh<&b#61+t&$W{4>T8 zE*vm|Isz*2faL4E7#D@PE4eNj;8>XkQvgJ;25xv_}sTEM`q#d0*Fl-)PH8+ zh(SZcs=_ z7O-jO4u`91^JS>eqsM~!o05-J4Jy+8{X*E+;V1C2fOd8t{fSUYUOuG4GzGl; z@^JOSEj*A;*?SzC6HQO(Upg5R7o@2*sW=B-y936C=@#e6qg)7{;b=kp^Q)tF{7`t# z13CWyCiCFn0J=du3LGZXgyap%yWTjcEEMT$!e@7&h~Y z7wlA00FQvB!32KDbjS|Q7svtK8=Hb2$^;r!PWgyrc6X<&9wk-_gapqCFVr5zcGe`5 zd-;f>sHuIh@4aD;Yk#CXkUzfjbCu-ltHLtN{Z@SwYcmG!rgo{gTTgy<3qO&wf#g)& zIAn~j7~pZA&PO$*;h;6}#m=G7V){kj_V)Fnb+1_ceA77?yFE{t82+hku%o)I&7`K4 zJZ^Bd4!D32AMrmO6}`87&taqM5%_N(U68G&jreoF z3AXVYH*RP>_PhucwYVj&^z?MwI66?Q7_x(Q8!ZbOl-6Wb&-IR-B>BYppzTmx)!)B= zBgy6KQZ7+E|8N1AneAI|lrqxL=yxTKgZJ2*Wb-)YLGatpJ!mo<7#wWFIlbd~wQme~ zyPy)*YXF8G=|`YFEULC&%TtOlF-gIBEo|~f`uh4Cu^ny_2o1NusMU?5aeZU9doS8! zm*`-OsP;QB{GRj6=k>Lss7Gmu*mQ19&KnaM!+1Y_k*mGYv4g%X8g}dVxLDK7qes$E zd%6Q>*Gv+eB^nzWg`I=_{7xSLbEIb(bUdkA?++Z8;}R5X!@=441PlOR;m+!mvZYNu z7emS5<_%nB!OyG04R(s3N?Ell3@iG`C@DJvPWhs}T7?GFR})S_ zlV3V0wr0l}=;`-TAAH)5V%7eD6a$e%t@6E}e=a&y?~DcR{l4gt0kgNQO{{SpIFCVC zCj!K0MjwJ}rB`So>qYP<`Iii#BnTLYW>>mBBkEs?_g zp+zYvcSH_m<&TSmM66ouD#F>6*lt#!wPGk-YWCeK64PN(JnELdl;?zXqsZ}55RO*zLBGYk$FfWgbi8p++~IP_g7x|YD?Uv#&$C(T0HNpJ&ujM)rD3H+~v~n0^Vm z3Ofb|NRZBr$7a?}Xm5i|t|(*>gLjTFj*dtfUsW*C@MFp5&Ui2ze3KR-WS5F~vkKKhrN zyR8j&ly&b#{Q{An*{U}*OJop@f%14V{0|3G9>KQL-)51c817qzi8yVyWVs_S8GR^y z>>&wJck8DXebJ7~ome2|CdyEYj|K(>^*|Bg1904sgN2~s;fG{kfA-Qn_88zOY^{=q z$58}%78Kw?WB6tMT((CLpULHAy4_1g%@xHn4c|glqEK3(u>&V_)e!s)<0RV!Zptd+yC&@kU`1 zn1tNZ89D4~u~Xd71D*q%HPh`O?d>h);Rd)0j#>i}mm4Uxite7>7|4gST`QD@ zxs3)sXlSYB-nv905sr)ytkU&1fcqmmUwAe=4m*zEV1Ms~ZXawLu#u2$J9Xy5j?qN$ zc_WOMKVFC7{Nl=R?y}on zNQiRXcqgAo%f{BhFyDw4gtN4{Py|2{{K#1xx3#;=fIyB<6&(!J9>f8Y8ajz(#odWk zmqalkyJ$!MjUv)KBaq5_bDu+-5c3)hjhJ~~t_u7o1aNe0K3tX-a<-e{iTmQUhnsl} z_TnM4?>s%MMMU5zRqd(`WaX)S(e6j@9Dx&M3Y-$;P(J-LpZ@vHIXK|p0)h1=AfLxz z1qeiR%*~k@F09Z>fHA|~e_V8MqHGo_Ba7d~b)R>Le1ur%EGeZlR9KKBe+XR#K){=g zua4zf2ooFvophiZts5-g19&GuS6YrCcGdj2wWe|6&Y8?bY2;Z%`Bq@V*dA&^o?qiU@aaYNjG_;ryK4#MqQqz0I#d^X-+&`T6K z(|z}5EF|jS(3L#M%w8BU6=C%t;hTN5n|RbIvR^L(=c{LFk3clA4liH5YWj<`n-dXf znO5iB2(oEX6pjB!ceJq~6f7W{jBq`W6ES1s;|vFUaH?RF@@SQEZ`{9Q&w_vce3&@+lYLJ42%U8 zz}cW`NZMyL#3LKY!9bkp)FILhX_y!FpU-0MH?;`_DWO)~>jE&0+1-sx2Mtc)21-%m zg|Bb6&(QT=tP^>cl4Adr-0|^`4=PBZ+a72-&VmV22Wt)x=|LG2iT%HWdhaplN+1$M zIe!Kp4(9kUISH}8DzTvVf5f<5eda(3h3O#$XIZ9&xA~qO{TWe{l4?#BscD_;`hS>v z6Q~;7zis$xpdHDk&_Dz33b%?%Nwbt84a$^8kp>zlk|vePSd?25ASDqPF{>ed&hw(n`PNi^gI@46m~Dmk`5)>Dy|)4LD>bKe`u zKrb%~l2u@Jl4kqEhgB^>33tP=PwggT7%I5ja+TDLjcr_aQ=@S?ZdYuqNNJqP(L0N_ z6KA^9uX&koPr2dglP4FoMrs3QnPKB&zb-kM`yzdf*!-2D0|>s0on(*^@}eqCdY8~3F?Y1fA?$Wk|M z-69>&?Q7TM^tg+!oA_TdZ0k`V2eZOk29Pr*qih$&=A2b-x)$vcLNjBB}RUU}?lsC`)X_RiDA zpVmn8ek#P=h&(PxVn~zu`g*9@xFS?SSq8`0`40?4{!*S4SmQQ({`}Qok;?3h?dSR6 z@|N`Xz3o-)uaKRks6{ z=Gyq1y}w*bU%ze+m2S!LqeS)=Rs*uhW zx(VeE>hj(MhEFnUvcM1)7r%)~mNU8{Qhx9Zocu5rb7#wC6pmNMCfxe8&!vk$!6_{i>m&EUaQ_9 z$|qu`>x4&5ZL{r9MjIDF&vugPu8Zu!6n2jG>!(pOXPhYZY)G%O-GRYCety21Jxdf& z^&raNYb2@_S9P;kvu5HYM(eql9`Ay8?ED@?t}j_Ny6or@@2gwBpPZQFlVUVu#Wlpw zM>#)^ySKR74#mM9hQ)i4oufd(T;H^Dx^Q%-r2${EnD|Sn%4yT5x3wlGytDn?YrEjD zzYggzl6EiUAk|^SH6L2rG_!O=?WB)IMA(f;Nxgt!!R5<(Br>($SG#>sAywz1{n(4U zGoP!x=^L+WWO-2{w`Ts<#b3UD-JP(cJ~A{soE!uwyO7v^g}y#}f+9auf``~Fk2$5{ z{Pw5R2Dg0i6gco6k?rs01jP-gKk&2SO*aS-&8XF4&YIdbjYw`u()wY9g&R{}pAeCnb zy`o%b(7aC_8e+~L^aT@w5>s_;(khf~cXC-RJNoQ0Dj!ZpNA8#=DQO~?$H$sD(cH^R z`4FCVo`8X+O>|Y`+=xi$_}&nmmHsaPQ9h)=(w>qwfAQi|ra}E|fi%xch;b274WhZX z?!JPxOl--$07VTA{7T;3!zWI>qnZyJ)AiTSrhAsZd>P&?(!8k4=k1j5_AKs+Lb15^ zhb68#Jy%Te1&9T`8L$0~wFjO|wph1LPb%+mu>EpT&Qe(EX{9FJtRt>#mAKEX+Wy33 z0c6LVXz*r8qh2@Kmj*H88Y$L(Bhhh(*ox8y{MrW68mjqZH`)GQRC-dX%8_%=Ns|4m<>|z(D&umV~KNk5Z8^`k*zfp6~X!IjD!Y zWmMi|={jx}Qhi&ZY#md*mNAz_tWFrLOeQgqxLdley}f;C@Wnzg1T3!T-PWz;KArZ# z_|4dD(0yli<_z_GyZ;*Wv=|+BC1*)0E?RQtmt4YB3B)3mXKN-+oaitj#nu71*oy{t zGc@7C+V9XSAOPkmecGe*y+JE@fO&Or$$ptIqaT*d5Q`NRtuz*62mM}>04EFo-kY}T z9UWy32I+~|aX#TvaeFz+)ZGIY-;{WnG11#Vm?9=l&#%{kHl!8{zL+=meZ`%tXQx)L zVt0o0hA=YG&$gETUn6o}W$a=Ub#}Wi{E$9=KH!|xr;w_SsK((%d$Q~|r=VRjq7o5R z*nL`K@FkgtRb*#*iCq{*gA%`qLg#&7Sq^F_SdE+&-@@MMMwesJ6vrms&YrYL75R^aa$_xl;goo z-FMvkThxxv6LhnR8}Af*UVl5&eZz*Es0a#I@dOvakD@2L)88ag<7dP=b8~)PuEU(9 zE%n)ZnexXzb=@r2&pT7T^u~UE=(uAC-?PgBOyJ9{cR{6T&1k+*ft^|4c7mn$WU<~# z3MW2Qcn}paQVBEi_uyu+MX*ju-9<|c)>0ev^?5HzNh#75u(w(D-52ZBT*=yhSYW$e@!_WB^vY0!xb$&{4y2phUZDBaC-I);2h;JaMR>AmWj>v{SoF))d6bR|zCs0rzz`9)bWc(ahS_Z|WD_h9jSl8@j=lM@ ztPA_zO%2;U&oNVu5qeQvTtQqc|E2}D@aQq3T45?K)s>)31MR$=0>;%T`PC z+NrNOBhTs0hB|X?0qOB_Cpb*vy!5A$Rr#jEYU%yoUL7?5d2Djr=ZBVmPe&jas8CSY za1$fwtEj(g_g3#Za^%Qt;Q;~8-qYQg-ugC5!|i^G{En0NWe#EShaDE++(qQLsOwcfE;uCTHFn7PEa6VJe zA;b86R#4w?6Z88ds*;ovejP(y&Oc64RC_f_)KC^Ggm1C|vZ;IKUW=?~6giog`$9Pt zRT3k!X4|$a?$_mG{m&?H9Ar0oFH`wso$}+m z%jR1RN8&d3883~$zwVt}cdE9iYPlE9;uo*y3wnJeDX9%W&t z&D3L>wh=DBewIWU+ST%>ALfW@bSWHpxoP-&QNyGON7t%6lTJ63f2raX1~Gl-C5(@t z$u4Us2=D#qnu_UAkSXUIFrV6Iy-hrvqrSH1?JBQP-O}E(m22pp?5kOe z)|bG{X4LWSrfni&K-IzByV_BmM#gw{dLo>a*LA6>%yTq$W^<%-OMUKw#r_S;niO|D z%>TTDcZ0O@hruW4?{6zG=G{$l8dm6}-~MbWen?O~v_Qtm(ROm7RO)j1)o)3eIYYcD z{r$B|1-~O_S4@{1tlcegA!>zm*7#$B++c0~sabq`iCDXWZ?eRfHQo{YNibkM#O_iu z47?9)HFNiu<|8Z526}%{)bM;%XM1!{*Mk~|ubU??m*!=!BzvQ-g2}eECm-Csd(u>o zm$S`c{&Ydfx?^{k;wP)n#u%p;4)ITf>4BdT)e-zSeg&xAq zn@3H9XL1lNyPw4kO@d1m_O-08{e83R>C%mcf^*jS?GxIoG%X+L8uJy8OAKoh5hpMX zw1CtBh#6+038ulO78WrmLFFjXcFn3P6a63_Fy}ylyRg=-cfS{gUmq9UKNpX9ux)KL zKX!FV9%{o|w~W^O^EbJb^gPo#| zLiImN4E>q{e=)5e%O)iZoX`K9WIJo=vG|;pxZ(!nc=K5YAeNcIFctsSOY3iLa7Nuq zvSAPmpTusubDX`7(1;RCK|^_`^dJ3VZo}F6Tg|6wHlN=ua@uV6=3D6ZOCJPy0Hg&W z<;xWw#T2+!X%5tfWMUK!4uZj~WqXgA!X4}oJ8$mkg7P(D&VwNaaidbMUiY?sz2%!c z^VO#Ln}6?acwDt~zTxjx6*JL@bMXRu6CgeT_>N^^lf>adqbnyJT&W}Yw@^QT?reOvlEgrD>7xJ`_ojFy(oe`$)5o!P4y zJkU$Q*eke|iiiHKwRXIUFQ?lB_c%E&srPP1ld~iZSX@RK=-bGMk2ff4$&ObuHGe!6 zqU8@}%ql5!H1VMmIIqIsPmc-OhmOFxA^#Am$q=bQlw2ui4uccy>O2zyF1eV|h(DDT zWE(^oBbq2icC6R}s=drOC9jkn*dC0eH3)P$U56A} zI!C{EV#d2tO6%`>x>3VHNE99&VDDW`MXf|$hqu3d+sS=)+mj`FMVtbW_ZFTz+z?;` z>L)-kv_Gd`lVcnP33Jpcly`coHaR+e_1(%Su7_F81J^2f8lJ1GTY^4!>o`}CE9@^p z@VyF&?R-2J-0_nYt#e~dE?&GSbuH^0TJJNqrT7r5^7AeX&S=I1d2;aZiGD=SVrW!gh>`W z#)@6Ghb?3L=pKWYQ084_oeci*dCdd=Sj(iEf!qu>#4P1PB`7MWTnqZu)89}0UJPHN z!5{(h2zZWvJfjs1Y~XZEj8p5Is{qr=Kt^IU%^`GC+2Q%Ii}OP zQzBU+2$ph-7MT&bn1_*^jfajUu@O`RkW73geU{S$eeK@thPMK$h6>iTu zZ|{d-D8ph)8SntL#Da`p5Yn;>5WTo1yW#-;;+wLXUf00qQupEA5777`1im# z35yDM=E>{EA1wfzX;UEY!YL}|!UaOX^10A|N=V$s-l6$|kdP3li2T21t%B^Wx78$2 z{n`m<(8Gu(8q9}p(jqcz7CB#$5d-YDa3OLF7ap(P$mAV}ICA6-P$x12fiMZv)yR|v?ZW5;!;jxR)KpBQxF|Brppld)En5SD~A1T9UX76 z;)-S-fFlDy>fknVLqfgq?9e2H)8SNFb?V-$$u$EJRYpc82E=EqDcp~JFg_#SKhj@r z+;|567Cah@F(bigR1-4n`7j9vSL7jf7cmVQf6zVHvWW@$^x>p3tQS#1uS30u=Q8I^ z@w5kpkKuiTrUwNbdLa+2&hOthfcydmp8`y!FfIZ^_qYcW zdJB(dp>?JOGDoJ*kIOWg9CUzJ!du&sx3=SIGdOKO6FV1^G0JNw0f;UD%>qL80vVYw zyu}q{Pqs84D-}e2~0@S`@Kj9Tr!Oo9el8 zhP4?ni&7BM16eEMkyXqpfD{8<`Ue-6sbYn4YPGyGAj^0`wo9QLBq(fgqQY<5B+|gJ zL@`qX1p_nB(_0-JyuX%+LNjQd)t8>GMh=O(8OAkkX|4bPtuEq`1f@dydtN(mw9Qc& z157H2&~$z{HeRRbj%CWr($cptPcHy5yt1}-R@bsq|A4;>v5M|~El$mpCroz}A__=F zVBnmBU9cpPi@gp>g{baO!GN!EBP~tU&bEDrR=4Qd1T9Uu*98d0W4~?z`c@elpNBBT z09}{%9SA!|jvxPPCZnr>{`2Szg?Fd^S_60Ii}>UC%J$-tl1i{2W<5|^dfO`FGBN(8 zX<;0+^YIzLH6Y*t+@!k!o;L1=3)(@L{H>4S?5GT2T79w|9Y3~!2Od;8ziyrrdo1gPU9;pnpGB<6*T;}S5$pjtpIAxbffVeucjnrr%ohHxp` z1m**b!zwXS_y4IumcVdnk(_$gCdcnA!3qp-H1Z6r0c>iI!439~=%k>FQza!+0V5JF zJN&CV)9=^ME1G>+X@n7mRqhzi3E?a~*ci~F^!LxEoQi~n_ygpPj*^#s7q@JqH6ok0!2AHhGv4(pI46Tru4AmGT zutS{?gK5uU=~GTRQ`~zgPytm4)q!rgBYjcvnw}uMV8rLa)sX$$noR8+rZS* z^_w=yA;iGd`o8%*#=IQ^T2z4`qARRAf(bY!C`-$i5B9Gj)5xm8k&W`gs0^7vn)zT; z{R1W-)C#vYEV#s=D3hKY&tjw=EQJyPo+zNHZ9v5UA|t%8z-V8t#;|$OTSx;QWClDC zX|XCOhGD9MvI750GD$GTK_B!9mp*@fcJyPW_e~J9ZY1%6 zHNZ=RJL03g-DtaBSN9;QZ~PW6dBwl)l82Cwbq5^{F2};t^DbTjG7e%C!!0~kbjzGC zXea|dK+7C6dJ?08{`I{kBa{cC3(j}h3Y93NA>|h|4*=#)LLCfOCp0PfT<{M?JPtA~ zud7R?`AGGnT{Kz1wcxU2Vq;hS`$aBew_$;7R8745VJASH!vux!F~gyp%)*$DZodK% z3?h*4k7qM}Z&Ql9b4QVz``@=Gav6G0umzA_NF0T*kdcvrT9TJ6?m1u5Zre6}^2tJG zIgMjD@FgJ?qWPBxd7EP^Nm*EBdaVL8fU0tG8^J|j9|6vpBFH&3K<8RZYpWR;aO5>H zJUo2!T=~bVjZL|k*uFJJNI2jb_qwMHC?Z=**^b?dEC_&+@ zgixHFDOw7w2?3GO3W6G(m%ix}2Mj)m9|ZX(>WJOmN^vk-$GxO=!J5Xy!}G6qJr?#F zTqzv*@Z9UIInxM+Jr&btB4i@*&Qnk@!NWpXi@1PKMip!o%gF<|OC;+&`n(o+~l?-@qwM9)VETYyasGApVAfo7vgc3c17gfFpXrJNr6JG6B%z5z}^+ zF$AVXmMQ2m+Q(#i;KH`TlLtnV{>ORT-Tuh<%rUZV{~j>T`4t$D&FQ+qn?`oPcr=fTt%fAjn?F&3&HG6xVH2Y` z4)vba1A*1>?ktDORR!cy+%0QFax+{S#Ll=whEZJk9ee3MQTdEE3~>z4S{d%L;M;L? zD_;F`dty;u`QOS_#eM+NxCSE7a5N1TsLkNtk8+aj5+s6N4h;#u1@wNi5iU`ipz6iO zm>|t9=*r@{9U3u_oe! z=6yw#_Wu1f2sT$38oHuN!=eZ1bxW1EUT9d6qDQEy^soapC^>!^u;aRo`V!0E2%8CV zx>FUcU$zlqzsh>O5eB$t7GyEfBhcbv} z_*hhM*CD_{M-?AGZwXcvK`3BXAdH@}7eSZ-!i4n{^co|749dnrkNK!NCK4)pz8ax1 zYQw6mq~Xl;=}91+19C8~6uys6(9P`~$~QWnWL4)a&8E>XM(YHfQUMnL-h=(4#yU6{ zLL0k>t3QrvPq@rN$BSM9%?d>_h`%5({(5DtG-L^oK$G3+vl+IP$TZtU!swh3c$n*O z4tj_^^lU4Ler7tk&k?>+pxgj>J6WSE2t;7-hcn@VyL)PK6w(cvN^j^m059V32`g+_ z6ab+-^*pGj_40-S`;@i|GsAP>)&=+TMe7eDeXWP}Gm(E6TBVzU^@is74Z2lXuOr3w zP<~)(Qhvbwzk2109H*NYK7?z$iIXCvP|F2fe}D-g%s%U4QfskNFcBu35O7ve7YJj; zVo4;OHolAhAXLE?cQsZ9c(qguW60CMM9n2b)QpU?WA8=>cJP&+IEmJtfC-q5UZhL{ zk5q(q$p0GjO)lXXkX9@Bb>t#A*8(mo*YzpCmKeQvobn4vvuoE5vIY%(ghh09B64w8oBIlAcpgO5loC; z_2F^;@= z`TF%4*c3}i72(ttHaB8~;(GGZ#vnD=XXDPDx3G;!L=M+siY)YYJ9mCrQ!Fe3ObNXz zHfT&t%v`WUknDg0s_C#tmO;hMD6W{k&{Ch(IS0HJ6yiv?(Kx)o+&mf(jMwmh=XYFpc5L zer!rw2LgG5BK_L8)V)D1!^$^A@}}M$`2o%E1)ZcKoOiSR{s*dZPn`l~C1^kN(cVoj zrv-C>%6aG(eh)o8ru*}k6- z(+XwrU_o|)-;;!+c0#3+bU-?Nd$IrlzNoz^@l_qgD=VwN;TH_F1v`4m1Vvhu#QsOJ zoPpGoX9x|1H!}JIa7$9GA8&vb0Yi@J>gsvn0iXY~tVH3=4+EXMOvN5A^ zG2ej5dyDb(43v_Nj@N=asClyS6#bybUahBK7L?oqQj!d? z$5xEs&x5l*8%6}My{B}^azXnCW;ZX{-49H}1t07Ux%2`mB#7?Sfn9)=gL81O8I@6( z?BNwPQ`7Viz9m_0-fzsdT{}C=}blP}~3%|81!gnrar`SUXhZhSfx;vP3Y2 zEmEU3AZb5zu8<+s9qJl9Vv>P!da$Ius0{QtJ9RtCiW;6$UQqx08v*B|c!%R$Hkuvu z_Xxz6=^oPUlkC;eMBt{3efRt9*L!L0^3WQX1 z?rE{OvrjrI1|2rncR&~9n9j0_M$#pC1W6Za8`ND`O<0AYAwj66^f}Kiw*)rbs4E~h zrh{?__VDd^SoL6g@${yzUtcN;01%i*Ss$q$sa0c0PLrAGw+&!3FvYQ@67trCB(MDWSYRxrRshNS z_NCeQ_pVh}9boz9`UatleWzpI)IBH5Y4c z3e^(zCN+U&GqL3Dl%O^Kx9lz{$;$ks2*}Svud=8p0tM#SMH7n&8G33cKgi%uzF|o6 z@s5264IeNQL5RYkSeT#1dFT}ZEcuUxKf{2p)E;I?$i%WNUQHCz*jMD&3+W0e@C6F$ z->FIGwR(ZIkEa6vglrt5a;XUM0Oomg?M^A=a$?u8D6Ryi7HHi`gtLx=FPWlJ zr-50~T%09{;j{i&S#vjlZZgYH4M_x*1Nt4R3s808`9YcTS3J{?c^S{qyAl#JWrP ztv{J|+V1%f!`*!J=%2A~w`S$aGW1$3&Qdm_#0blsR&?9gY-XICTZUSRHe1nToEK^1 z_hSX87)sKEAAzl}QE+cakUM1~AfmVxn3J65>@%_kn<+_43U$9B-MKsqNc3cQ|6^z8 znP9YX<-cHUbZHPIU=ovmRv%D96~|T$t0;B?z!L~~xpZUm5CN&2;*RA82#1~YhQbLo zXxOZOGI6|#os-kb+>s9VKWzXgoJUTakYNdd*{j%#Rs=KMw`h|8AoGZd+S&=%`>UYT zZOi>VlnVimkqGA-+h<WzU{Ib;5??wdba}FwLF0SyRy8?mR%*PLaP* zbPa;%c^jRPJmJ7nY_#)GcOH{63TnNq)1^)atbou#>SSPlKv63C+m;Rq8Gx zN*R!w9~m%&egU>w1WRGEPG)r|HgS#lJ=&izw_gsn_%`#u=~JS{kn$<`T^$Bl0Owh) zhyMZ+IT&cvHAP1|#5uq;nuJ;pp+PjJYJ?4o@7?I05qPMoC!&Z{5F5+j7TI=TaEaOZ z;M?9X;5=MIaVGGZhDJjda$M5iV(bKjE0#@Lff=pBt)X;I2tcOTMVP_yeC|CS z8R-gMJWc=1^)cuV(s@3p+ijOA7u5d-RDlyG1j*wM+h83K6#z=Y5?U&@f#PCfJwtWB zZOD0RCg&Py(70g1Q7Iz=#c^Pl6qBWZjSJ`yXpkHlXBf*M7>(h|T7loeWT0lvXfkH% zOi6ILZnqkYL^0{-=gu=+41W|1(467HN1NAP1Qn9m-o1TS{#lOrOGN+z7G{>bld;TA zSq&47W{m6dv<3i8!>dm|jgwGZI70!Ahiicm0_~61y9gDimnuIPL@@CXh`GJu^|N z!wU%R`K+l33W|@hH86)~hw@`4b6(3oPKq(g#3-W;cn}qg*=xb|bV3s2%EqzeR=rXVvn4bRo zo`v5pe}(Gg-}`NbP&4*Uvq2$&X(aA9o+jpSe~sOgt{02co#Y9o^3DG9=5nEz!mybr zZrH8U*VlK#^5V6h{h#lot!;~j1@Cl5-WvK%ZG0MmVHY2 z?8=T{I000R9lFXV+vd;R&HG}v&uq_99D{^0EI&8rg?_s!t^t(88m(Bt#dKwR%*Hr^ z%*Ftv_=EFBhngasfvts;9vNo9<`4OZJs<0yZ1S<=7T{{p-p`F;aE5I!rYtWy_TorY z&SJ4b6^KF%C-+4Io_fDiCXf6tkWA)`-IDrc*z6F<2Vp>R8s|&?v*L46?XeEQKtcEeY&4WXEyz_MR?Y%wTjVK9zHx>x(zSG6pO3g0Ywtw zPc-9+h+vT+CEV{zWQqL6ac1D$YnC50=dvajDsd(Uu(K;@cGxdvyGZ>BefHRz4cdPU z1O@n!kV_vbO%Q7Mo5WBmx`IdfXGxYgdvyJFf5h%t^Dh^m^Hs>r`9j0L19#s)r8zf< z-(z$BbSbXQ+xR26x3cc(?{Iohc-%8ZEO}SQlN+PW%hoIP-kh3PQE~s8(=wIBl*AKj zH(fE~J^2^!O1&j|dQ(}vQw7-fIy3tF!*%8@j63iu`-SzV)En}TtK;{)-hbh~M#7#8 z-5STKf<_ut@$GTKzBQ8@A>|HmwF%rz5ZBX-iKthC|i69r%VLxX7uQ$GC&U?*RP4NE(m`B-H>Q z{T=Jif>wwd!01TvGG6=k(cA#nXO8(Ho%Neq*Nku70!6Qd7Ux?B%|*{ggGpQnAR(GF zZv4Ij;E&cwk2x^V`Lh^?TbijKLYI<+w?_Gk^B3kTD_7p^!|{klC}EQ?bK#-{=JPNT z^#Fm8+TS2M5f+L&n#v!_Fm_#Cn1g790*}LF3g-#UU4^RcXMcZxi$As27|~v{!fEQE zOwedcN5^_{3X#yffyauOgU^?UE4Z_G-GXVzCU|J|#x%FGiZ|R9NKa?N zglj7~@53abPNW$*tpWJDTj=YD8t&|`vJFf@4l_N7J2-p%X)Z>=6RjzrewWeVUo>z6 zh*aZypt!jBI!3JcKFp50)g81RiL?b+3xpj13Hw;L4i_ zB>OtV5}-_&d3fA0h?MBq!1Ed|9xM9_ZHa+iWdO)3UDRC@4STe<;-ysg5Si!+?(LSC9E;F znjXWv0F@895UKbLcszUlTzy0pOO$-TCWwz+-z=I*5%?51nq_cY>?-0~atfT{wqX4W zV{N+y>*DKc(-asr9`Tt-UV>Kktc@(sOI(bK86!5$THDW$+qI~3STws?z$Ym%B$-`6G ztHt!V$fC=2#S&^BI#}?+v&Sw@))nJufU{WPG=;*YCRjTndSXg_wTlxcm@HiY&Hxs@ z@jL<49105?ZK*@|PgDzGJUF*7GXpLriFS8W6J%AUn3fbq5xZiJE(BX`=i7_hDblOtU; z7dWDlv@nymoq7YDR!M0!>~CR&qSGuC5QsDkeh|Fq2RjQt6gTkm|K2~*F2WC1Hh$<{ z;|C#?{`3F!KmG5$@c*Sd$t}Ht?hunRF9@rT@i^a{5J;z&3MznieUse$Yy;1oJ?rdL zePZU)%dlBFwwjxBJ3S87*V|1JUHr76Nl#C2a3sy(ox&G}NGKV?q??(dC(=F>?j(jW1$mrYqGm+e>sDz3G4Rd=>KL67dRo z;-g{NFU_)o8^s|$&RVE{f#4*^%eWntr`P;HUw#sY_j6XS0=nenMGnu0TXNxuvG~C& zgcAsvs{g9qf)m=oL7IPJ?2F%m^C>)dpImRx0)hGg1_Nhyb|R~>LV1pjeRh4K&+?W= zP>CqSVZH&LEw=h!^6&hflTe23($ZeY1U?L71M8Ko&9Oxj@o5mw8wDn{hjTcfGg#aq?a0E94bvZTB zco|*|!eaB?<29?IW$3(K&?zMLyMZ@Kqj{7{WKfQqRv7k!Ur5FY>>ScVBGYQ@)<*wK z^jV;>2>$!OW#BemLahzu`U)&|R9oHGI?}+3aB-oE2}^~*v)i|CbJd2?H;-2ij^xP(3Z!5D>=_RNe;!=E(yV25-H&Ok$3?GBsdc5?n<%qAL1F)q=wo6d|9{N ze+pVk?Ow*ri(9bDEA@By1#pdKwcYAU67wo2q(UYQ%US1iK_aXUI}pa{qM`8haxDH zn6AjISt&mlJazhYVtgW}&6mo%e=ZftUscivRULs9NT`%u@C2@TuvraOP;iq676|wC z4~Nute_2VzFsWijM}~Tv&e#HFDqScZ4tOXNb}Aa9j(z6#BhL%Mp;~c8c0+Zrr+C*| zFo;lGYHG#&wwUwY)t@3)Dy7!ImxxWJl5yLIFsUE4VNOgd* zz!~BSfgzt-TL@x0kvs6YgP)Ho^k8V%b&;D_FLnn`d!&=FFKB$&C-^mpSqKAh%&zD~ z4+4J&qzxp^$ET7;8lS3h`{wBn4qb<4*qCDF!E*sjgU0FADto_eA`L-)D8H8Z41@;Y zIaMfkNjHR2q-O8+RJ9@5IB*>6YXQ~+02OJ$KMK> zXj~#{FRBPIkdnC?WM~ZoEky${SfUkv=uqnuKFP}L{!cei$a z*ka>GRj2ByVq!PQUM5Wot|MsZYGTaT_2(Ld02ho5nEb|wP-P;VM! z6pJ71!h{7bHHWJ!SLo;j{W+JOwytbsA#DM;bJ30j*x;PGqcC=n1L3P!9x;T~g&6QQr1Mb^iY(H@3FE&n;ud>swbEWPs2F3wlo%tMWcvHl+GxNxrS=#ECqaj300RC9c3-^b?Y$sP`7hW23pnw zf1>^{gMscoson5+B03NdPVuO^2b=!(?RvsT1{?`~3kJ+(jAAdEB^tD%*W>ByD670~ z-b*KfU>=af?Uvz)xMGO#YAk;JjB2R10xlQdb@pU4_bF4SUWTTt6>R^o15?qXX&(qo zVrkfdqyyOcsnC_`uI}y%>}PU)+pQDePHSzTA-vYbMt&a=+mSjZ744Ho6Nczm|vdDih&7C@VGhb1< zXCu92Xy?AsgguFT?_nP(C%|U?I1?Na(p$6V^^edrNf>vv{FDzt(AkKY(xDM046n%b zA=As{AeKxE-Z!~@qxRp}+GzB=THQezm4gpT{-`LZOoOoE+HxjG7o4riIguLqTRsLT z=O_5K&08+?GVynq;4E_9`$s~>%1~D-bPA9FVz#u{Gz38olzFTAX(+!?4^+M8MI&S} z12d7Af4Q$)IQ=M16sOEFFfAMDA*(&4F8R&73)RmNvRpA^h`5&{FaIN25B<¾q8|{@x1yCdLS19 z2A#z=3&yE=UZxC%Q>lxtx0eq!`GO^9FY z6Y^}U=l*^}_eaQBnBLO3&3JPi&gk$F-;Pmc=mp&NY#f1Re0B(MLQI;OjK*+R0gX&5 zBy2SCN9CMJwEM}i0GNfTi1BW0VYs}W4OWC|%s5iBFZPpPcWJfPJ69={D}vtZ%v7bx{G;D=Y#G32E9!64#c zVo@a}mwNUse~Re=OrzT|ct-mRI_J49UdaM1mZ^_VItpH8q)C*E&z-xMLBK^i$iYU* z-z%3t<*$l`8Z|lPH53wuiQuAA04T%`SW|=sJIzpIEf$US7T3+3m`U!deie95Kf^2dG9etTSKG9*(81$1h#OQ1O}(J zOJecH1ab2uqjHcwDgP%|b^v%Z@|XMxE}>deO6puxb1tZX20`$t&5hEY*9ilQYp5;Ah!35@(1>QO9Z)DU>^f}9^NW2`z}2976LqxU-?8~mdnAysRE%3^ zdjJ9>-*J@cp68OkX%_-kK(xoWegig*jLC(a>Ji6~&@r;WPRLfNA5*wB8&hq1V`cq8IwA2U%@JqK+BH~xMcjL{jg6brFAQpukDWRT6dwo2ts#69 zESti3aX?}Op3w{(y}?;6RoY*uenfrOfbE$YE*bE?=iFJ$1pQ$SM`yDbD);5&*5VD` z0BNEKRWT_SU&%V%QoewHDDJdm8yjd1O5N@oiGG`{ICAYCMuhpVxz(J8!{) zVy{>r^D4@!IJPGWtSh^=w4uSlo`!JAw#dNYM8iXoTf|r4I>_;|_25bb5pNu(BWAf5 zG^wQKbUdXB`gj7?Bo4SKD=W9qXddi>wF%+|kLz%DaIGmjLnUUoICuCcAlNT=tt&8T ze2BBOvT+t@m;@7Gi@7A)GN%|3kHn*oKVDP7ex_9WIL!!RLpy_OzA79%bs zDyy>}`(Vdwi}{_+dP&UwY31+@KX>e_d5;eb+Iv=vrF!A=xz?!{Vq(5{R8`Qgh`n!y z++z^sLiYE;Y)s)Xyb-tgR99EmkfDN_0rD|7m&fsZ+M&l2c*l#abrgpQ>P)KK zv+il3k8(rHY*_qm>)lv&RZ^az=F4Bu{u#SJ?fkKHZEhZ(S>KO9Q7=%CTZL*A7H6*= za`<*v!cy(l&5fyIHlNDxp-w`39@|g{`T`L)v+l{G{C9ErZob1Wx!qN7`EnKX2L;8F zOLsqQa97n_0YMEY&AWVlfp!A?Q*bexm0gP^338Hy&oA&`_V?a-Dr+3C*jrgv9`?^! z27GAu%%Rw2kUr45Z+H(}0dz_dFN)1`SEoea@PU9>q#TxI*qJpWms_?EZsGHv3)8o^zyh9uf=mK+V z!~JXU%p-aA5>bBxP5An@$pO@0l?OBZ?>T;5RfCw+a#u3HegxVms{G~4nGIYVD zg&=ANysp^(HEDyD)wj3Scid{L4yNA~&F25Ob4kKdRf?>ZmM%^oy1Kdo!Znnd!_p?T zHQw;|{^FzRTL+ZqXC_ywTQY_ppg-~i*vhc`Y@t!8>i?3CvBZ;s!@qf;Fw{_^A_)!)vF9VE37?a{6JpJM#!jMYphhMF!s2TETkjVb9bUMh(ac( zqtAjKl~`qzCU9S<%vUUNsJ-ZiTTe|o%0rX4hwzV`i`r8?`cXV}XrRL_~P_WDE=pa8+x~u@B#C^c%Tid51`1p(ol6B+UJCYowm)EcVS86kV(jg0i5> z9nG_6WzT=#yQkj^W3~wb0yCp@ob-{d;n+a|c>csLGjxHNW_2GqV1PvhVyA%hL=2U0 zATXbCPdIs?Ct}JR4EdV(T6@)|%&K_zE(r(VaA}@EI3Q~h`MEYh@`*MQtiPOrMQH7D zFj=)~(Suv1j*auqM4w&yedf|nrSakhku#W2Ph1}QmWu1$pLAefZ4R#cxP<0M*%O7p zv#F9UyJsMIB6G--hg&+{D<6@mLiQ#6O3FQEJOleEVgI0-DMtE}6qd2w@mZ*|EQIsC zU$XZNmE;*Mvj-F+U#F$i)U==@7VH2K3H?H+k#pD2pvv}`BF)|^1=Ls6W-q>?&2O2f zD4zmHssc6Tn%>>E#rR>$=~eo=7DscHfeNlgA<^~ogx`I~q~aYAOg}#{Yt11pEjeXn z3qsDSYE%K%3Md>v51Br^EAs45qOKbp6KQx`=zyvmqdchH+|_T|e9!7OHt+WZ^mq|) zX`I-&?vsWRKiW=aqNG&;l2A}QW7;&&sHNp-0R*(0cDlIizGiQ3ZN00FznOfc(MHUl z)U^mblCs9-#8Sr!5RGeH0tqbg5xamGN~o6n`OFta`_bdI!DF|p?fO-T{a>am58FJ zkjWy9n5%BSoGT}{l6v3k$zhoGdi-i}$=Qlt0#+;?L6Xgmua5&!`k{%#74T%}l!G^w zq0Nq|OK)%OYjA`lY)$S&rS2}{Q-C1!0Sw+%k#{v@bgh*r2~pfU2C%Qh%a;TBfX(1fma`(Vxc zbk9T*4y@p|ff~$&Kx8`QrlR&~tqMD?_BI|4nbH%($m)$|#ZD;#wBVYb<=Eo|-R>FN zfX!$=Lo7SNX;D_*{;Z#DkmyJXXP?Y@Y*x7m(hO-$T93BEQmUtDPNc}_-uzi}F_}V1 zkQ9FT(TANN4XN>+;m1IMjHi21QN>LNITds6+)Z?@;b+>xXE!!J(Hd4(hl6;XaIeJ{ zZ(~iH=yMX?0cj`zV43O!Wz35OGw>!Hhu$sh??(R@CUK+oqwz|BzPJ%r(B&n&)u99w zm>jTsIpW5Jz|sA%LOQT>07p0zrcc*hAXHvg_VJ^Oy3@YBd*>sl_5_eN0GQ)q6P*$w-nyFdhJj^69W`u+!GVm%V>~}h1 zFMf$nWx{BWY}%(z@OX(&og`U?Q-X|%Urbsfpoi$zKlW^yi=jJ)jYbMtUBRuH)^LFU zm`vDrQ*-mHzk#F#`QFyhF`nfw8!GRW2?A9fX)o4j>uZfL~WJFWBX~ z1tl!OsD#QR%K$eiDcw^b?!FUr7>V-O{C)13gL_KF04g`si69yjN;G4zBDQq*6)4S! z;t>5(Y3%|?!9w!SVBSquK0R5b3qDi9kGISdKe)Y zBadI($|yL*xtE^54!a_tAl(tWYVSIPJHCoG`(!1HkhPX|W;H&V^CT^_|-=zz#s5gbR&-9r#el3wmcc6RN;v{Wz^;esa< zV%ZCywJJEqreXkjX4Du<BE#K`9RT~U9gf)T!T%mTyQ9jGgYwUlspf4GOez;#| z`u5(acB_NoyuC}CwEH`1PSJd0tSwPimxA2^Pc}Fr>HUS$fgdw!I<;q+|I>MSX9+U} z*M72-YBM_6`BtBo@TSbk?rq(YNh05k$h?15>EnTW?SB7+8wHV58FOmxT#d`x#8w{}i9_rNL| zM~)<6Ou9Dr_ef{$-nn0sl4P>sEs0dc%a>Tw+@KGbbabTdw>1vZm~{H{)!5ii#i&uq z0|x~&GEP^1jc!u^wO!9om5~KTz}IeND|Ra06N~ayCBi^XZ#sH)O8FLc`#( z0&|yi8UcSNm;mfCYnlK8YxMsaeB=oMVn|LI);#0{Ovn|P7?S(_`#bg))9Vw_r;;`T zNNJH<+K|;UY20=M!16d1S7K77eawL{6JM5;q#WCzIdigej0t)Iz6ufR>s@>wUUU{NbRq`(q4AP|^e?wZ5IY?yhkNdjQ64bd)2e`XuQ9s0}r|oB2l6 z^@KaRxz&MCRqHquzn%|C0i6Fz3@tSsC!7EqADO84@zx37R77TGlYeEW>hyDyWfDjNq~pO5>?fqr#$>h9mS}TF-$72pUdX{ z?g|MaiLWkg$Kf^EZgP8=?>jK487y@VaB%v7m=RbOmd?irXe6Dde)zwmDE&9=rT-KE z6r?cmB8w?}@aPc@>cal%XluL7aHW%0wV~bOz=37s;9T(39i`IVBb?seZ!##SxTODo z@#+32THpUnf6EbKZIOdA0L1pC3#YI0j^Uv{55%hkZ~u$d!6tv%340{Iay`rLS_=ge28!(%{-k!!zV}9gkO9)SpqUu6HF70y;{p zF&?^&2din9ptSdC#tY~eNVfl8<@<9*+C#|#Q)6xiX7a{O>3WTyQ&@sjxhXjp%lLJo z_U4*o(mwIe;I&OJlY8tpQ>|8o9QI5!I!1m?=i0-Q<5ZC1;AV4YL9qWq^;+`Fug!mF z!qx3rmz6=!_(evA(41<+1rToVO8A_&>G@gjGXrrc8yv>ZAkm3&Q}zlq`b}Pyy7zhf zn|#pWjh64xyWPZMB6xz`#F)HNYIDE&YHqg@hmsk$9jbzaL zO(ynw8?@_*8}&x4*}0YKE6J%JJ-(n*omx!$0I_F#XHJk|kum!@t~T}3rogZ<>)KkQ zv*cBqNG)C}2%oEc_pM+Ug+M_Ot*E5bRPHf;4mzSS>BJNk) z6EJ+^l!8X%&jEV3gbeCW0HNvpqXuH1m>J*5*hnVe$`7kn9px<&+7PO9Q(R2lcy?kz z@at$jC2|G%%1sY<8{f+Ke0bigtAwY%uI>bP#EQQQ^a=KgYXiJHD#)Mc?AF(Os9_Um zxNiv~?U~cnF&e8J+5J72B^QJr{Fe)VHlMbLsjgPAUBW2E-`X9Q}R&?b&Sp%%NuU4WTRBe@!k6UGZ&qE;+*L=1!pS=F?~~*256;T97l@Z`6{;_Ig`34hhbgX=`g+*K(9)W@cU*V;Wwovs^Gip&frhHyj># zO>U33e&Z03aeuTO_)vH{B-meZ?O{g}`My#iufvU9_?llvMwCQo@(9jd$vC`&HZ`P# ze8u|}@!BmmbMl(I;G9~cnUJ}HHTh(zJG0m3^%_^-+ook`Bn78E)aNnW=( zbVX+-Jc9=nsi`tk@_t7hZ>`4F?`UhZ_Flf=1E50{l)FM6-M@b`-*A7Jw1t>QgT-Wf(o z8&m$JjrXpz7?miXCQAk_@b&Mrr%gMy{)Iiydo}ibf1|s8ZqwqY@qdnccQ${yyShMd zZ*RJacqVNS)H0UqJb#&<-jyF`NvR(a{wz_o`yu&!>KZMftusa6v{mz{$$sxTgdZo0 zlHY443S2v+GO!~gvtBgF^yTDxuWDY}?^En_>XU}ftTUrbv}u$J+0)?SM$X|XM`98T zlB7R>_z)}5@1MaqO2*Uwo}BRgB7AMR_5x3eoW|6W#ZM^@4j$V$bVNl?;}b$Wp<{Oi zmlu+CuckY^@4o@y_Gg(AVmCU(6=g!YjP>H*#dZ z1yvu9;NgmH+KIJoVArjoAT}~_SakkY(sq2iLk`;76~6ti1%kz^Xs3o<+p=#%2Ft&1 z?WS$@+lGREJHY@M!K8!E&W8qm5`45TkYg0;IRhB*OKZB5w^_-bs#!?g8uI6fRfAy% z`M*KuXJuA z7eS9B|6)N&Sj2sgT!bh)eyDdLUyXnIE4-o5E~NbahL{XZck-HlLCjHp+MR|OfbxkS zaKy>g(Q&~KVOZnm|L>O!X;A@T8bT*I4YVf5QR3_mxDh-zADTfVjIVg9wqj8fJXp@?9-~+G&D&RJx~B5 zjvhqj7}Y3IDut>*r-ng25(YvDB?^R1lC~h>G*MT76)~%yQhyg&H_;?TNw*PQSI*sx zwC5f#hJ1+T$7X4{@z0SF@0Ubl0Yc*Uzk$IGqYOyLlV>6I5!DcAP|4p1)*#eY^Xmvx zkUHVXkfI=jfS_Jgsi! zf#Lb_$|deL z-G{7|rbOIjsduLpHr$kPiX`6v6zu?RJD7oXQFiq}U7)cHn=eKn%LxJ-Aa=M>zn&pN zAq;d>MI@{wL8_Q|{%UzNo+_$s=#-P;fy2BZ9dE6!CW&Fpfzr|yRxy_Bd;8kH5d^^T za(07zppvQKPssZ1kcL!tAHZM2VVA+aC3RpT52kR+zd?hJ!e0Cif3g~FJK&|R@k$Uq zAm}m{kKGy~RV+2y5>^{Wi`vlLU0U5D6Vp(6{QWNS*zM&KnHgz!tyv761@X;}_*0jZ8xzx--m zvPvlxT2P=ElSN12$@*A*^nilvL0#c*P*5kX3KFmt;iY|{%@34#D#4c3j3<2!g0aNP zq%00+?Uqd!slF&Sp>6U26%6KozfMABOatm)iFyPBOw5!Mbicl%?JfStZlHMp*|5Mc zUNcM2>!jQQg!jK|iC58GcZIM)iGG8Z*ACmo_w*Z~Nl9S?{7Q$&ML&H0bMwDvWKsj= zFAOIyKl~}|Nh@UhV~+0usK+jjP3Z?n0b|q{*_cR$1vP4XINRcl7x>`IB(Ot~t4GrO z@9HhyUc6J40jdDIW~`gS2GT8l>fW<=liuQUl+Xi^JxO0gUGqK`oT=Z)IzK)jA2?}G ztD{rOa{COP7%`)?Il@butf$=0&D*%_(a~ujF5D2y`8QlsKG^LBP1o-NyM?eyi5@oy zos10r8hfz&`s~cS{5BJsIm8x)Xr!>x#&Ng`5@Rng{fP%i|1#P}&Eu5+1CsE}Fi8>S2pR&b? zmJDGZ3}axJ3`*fMfAUKnpd*GSM~<$M|58)curL|fE~1=G%shy!qwe~pk)61oyL~DY&pu#r6UZXMSSH{np=Az6)W3^+49#$WDK7C2-v?uU9Jbeh zkA_Gst`H$8UJ-eO;RGB;G_xoeJv-(ls4c$Cq`U6Tn}ewI|Gx{1+%Jblc_JacJbemf z6pSAEUBhNnp)i1q0he#Y$KN}7Vc_udA2*$`GH`sUv)A6i;TT@SG5Bx9`M;q6C zF6cq6lDlOs?K+~ND-bVHb7N~$&?=RCAZ`46-kmC}dcr8oQW-P#0K!Rz?;hD`7B4l`nPT(9gu;ZHo9M-8kNwD zLMUlyV(AA%Pl!UNRsanEF)%@SrMi$FlZ957Aail?sZ*9|Eo0M1G+@0j)8aW+CqMRY zctwN59jH8&T7oE$Zb6BRas zqxXEX#_ZpqG==xy4$}m6h;U=#ipPbDAJJwrB#+KLfq(_g2*$ubWbsBb!BQ^sr>6QZ-haV|#N(N5e237|96)!z0g(28)8z6S4P@6sp;)*$ zxli%cI_AOZMUNWBY-ZsWLYt78ng7Nw>GI%m%;i5ghIPe{L!%Fhy{E$K; z&hcm(J6+g9nvxn zhGn!32Uc+By5M&+^m6hi05I39%1`jo=Ji|jy|XZ6y#Dp4>SSB`4!6&&HOV4Ug>;WY z8q_<=&M9poql&{uiuOF=wAYrAk^kD(o(&m(Cuv(GZ&Ra8Y<%`pZ z*=?vT0^cKBG!b6!#>oZRlt>t*1x5$Zfn{O{ST(KT(PSjL<|wEe%sC-;#Oaj*fG0}axK~X)ZR+cLz?c&= zfYy57Of=XS=rsrj9GcfVOoVh>>vf@kjK@T1PiWL=tc(E& zj8H8`|IP)|Yl@wAb^X06jGm6V4`(+aW(87YO4@S>hpGgA(UM;Khnt|@LPA16h?x@g zcmTVh@vM~qy2PXxj3s6PT_2T{`4OH4BXlBU{wVHBy9&_( zV&4leC=tnVwpofj6|_`wPFA9G%t#v;3OcaTK)eU@mh}N-UkDWF#vAQ(zI8Q2g%optRw^I*g{JJ>HOp2L8MKw%{|#(d~b&-rU2UBMym58QBEErAI_N~5=MN0 zSxsF^wIv~cIXPX>FpgnMk)niXz){p!D5ZYgfeK~FIbn`5G0-DycKf9(1DFQlFXX4t zbqG`Qr@XROLG=Si5>)8#t)IR^KUHXpOQbY~?WPd(#M8KBL7LLqxygvz# z^``SfTv4sBk_7`Xc6GRZg@^C5t^>1n4N$#20ys<4EXvra9 zXS+WW$N>pCZzrUaUQGIZsk|4I>HB@iHxqunf5F?4?rb~OXif8_Xu&D7|j9sDSy<$-9VL5abQF$KLsDvXqTCaYvd z9D&&7%Qjp93>+u%8jeU-8!p=8IkXsM*jk#!XCKa&aJ@SLMLrZA??J8zK_)Vg<#t?x zAkadP3LBJ(wKY!wZK}^7hGg4XNh@8d?Py~AtnhE1&28A502De7YZ@W}c{_e7J{)(C zs|G`-vw@?O<4CnA9q)1I`T7uH98^H4<ii5^WgKd6N%_v!qW*{d}fDB5c;cwG%XGjlw^cyV;81Ph{v9uvg*NAO$Mr4As9tX zxs81js*^~JbCIo3>@Owg3L{e43_K6o|5s|hxdw=xS7oE8E@bL=YZS~rPyQ>WM~%5ta$ARXnHYHc(Kj%Xeded@ekF7v1e_n5f_u zH4-$S;)4Dy)bT(F;3fCj!JbgNy8fgFYXJy%H1SbeDoe=t2NQ#;-Z8efLeOGunVA^4 zjtvrdlvd&0tG1k&duV1iCM%yW(84C|KWT1!>H78|=e>t#E|{CtY~S(7I!!0}dPv{P z{ukuz$ZN&q$5AnkF`$+^km~|n30pNWjl&j>>q4xCFs-g5jv zb=gVr!s*0Zhy7JjhaL2`Ue7vyNB585^vt9fM?9~%CL{<}TYB|eXJiuwZqC@rNkm;2 zNGy7YnZh#>-c0cgWn$p2rxN-UoJuRwF=cs+;|HtU>#goQxziq(HR@=-`m{>hniY92 z39{}7+P3VvHdL!3#=)zk8G<4ViTgC;XXhtN%!t^UZnPS2s`B|i_W<$0>4TgzSo(l` zp<^B?`e0+h1~__@1<$rz&iT1^)s=R`;{)vO-Su%*KjyzKT(NytmHZ_mcywS*5@+p0K)qhMd3~=EkD3hrv1+wgT&u|J~ zPI_Y|<~edmNcO8ZzAUuLr$M#C{&bc3hs{n6tC_SSYg8Ne6@=}<_66vj5atISG5Fj1 z)FwerRv4C;-~)-cI8+Cj9at95kjfF3NyMooj}K8!tUrKfwDq*c^T0OS5T7GSmgT>> zTM~rN{<^i-a`Zx>l6>W0by99hqTw@*KZAv%D>fOQnq{>WxV>FoeoSpf>iEf%PWu+t zOF@qpXAqKakQua=-~DOT;An!gks-hzNHtAfwd^%zr3XuVoc`2U<{i3k_CzerBO$vg zS_EU@XIhXKYujt{l58|I=6(%=f z!rOCZCQQ}kW?rv4;F+Z>m+#~BDVpOulzE89ctV|H86^lCxAIu649m!truCkf;h3BV zl88Ela7?&irW%ULMD&ZuHQU<KJTFh#&{5erdY&P}KYv5rHfsLN%lu z`5krF&!X$1wOPkkoz~M__VFkD+=HB>g~SXZzd9CfJ{f)f&k3?h?G5%Hb=Q2QQ!J)2 z^(n7ctgwgvj)eDqT=4p}+L{~UumGaJWMctvjIXSb_c(~FO7NKYXqH8E7R$N`ISm>I z6#fV;EiEE8Gwq{-6)1B^VU0Yrk8ti_$q~UAtx|Qqh~35TC{-QL%@z~N73{e%dgb98 zKIgsR8<;NlB+uuOdb&UKO$?Zmwj$8(MHHz)t>WVBkXgY|7T>Ly zXK>`Ab&PDCz-7h13=3wVwePmKN;_XSd}i_cxomE)T+QIS*ueQo7XGH?r;J#4j2?wp_u%N>dg#d>gp}BI!K)&&;mrIDq%(mM zE{GAuq#oQY4M7oH3*=>u5p)TYNn~_%H0kZiqKvCUU(XNZ>E5{f;<|ioZb67b3HzF5tK&zcYOE2r8p^}B-c)Ey3-8*<5^?Lt=F6vV#PSzr zoix*E^_0#Yc|0$su;X_0uZ8;!FY8BH4K3tQp#ZM_+Qris8{idSnXJkw1kQpdiuy9Q zRdy3;On|BHVhRhemS-1m^Uc238z?uw;yGuexbu5-5W-J%xRu_5iI?qf@^+WdZh{uu8)?f7DY*H*GCb(BBy3A$Jy ze5wlH0(TFr^G2l70L~}y-Y$o`ED1#(cs5o8CAs_ zN6+NMoG`^U(r+@;q!-E2>UcmL+w$sx-`52E(zb*bUejQSoZOejYi7&3tu?0m=7s8^ z2Xp^}1$fbT!^hy^f7g5KJva2)o~|)}GX8R-j<)w2&hI-63eJg}X2Z)u0>=@6hy)}a z7$yzi9$~OTB8_;uF%+`?ix)xvEAdl}%EZDlWqKLJHQ;Szyys8tj%(Xi)c@JWnqZk{ zUw<W_Hm9FJut z&Mz;eO~f@mCMG*ZdoXN3HaNxmbc$8l2O&Q(=eL3i$7|=kNtFqh3tTn>fiM*uJSudX-w(7ahZ*H``qfPZEp1qbD1NG>Rf9tVh?oZ z*mCXspUvcCz6PJLPCSNtSKDiBhYHvl7Qcu|+aB;Dl_|yDj@dvyUZDo)LVS zD?j``DY;KW=P&sqwB;{QALst#`M{##|$nu!eIWF3|T~6KihW%?BBo ze`CGhbh&rSRoUzD#@6(Q;G{D5B(WFM+~}>=`kRM*YJYyr>Nz9Bq-a5uvVqiQ(`4NN zG%HCfK??w^lv;VGEj>Y(ls%vxK^)1Lf_!`fG&u7Z((i76w!pN$nGy4LA4|)#-v49I zdtqOH;zsK&F{U||h?MAq-AWVp6Um|eF!qh}_5BNL%$uq+?d1>6>bzZxg*7JY+r27# zYxzYehV(7Bo?=iBZn!L2d=JQes%At&Qql*^V&dU|xq%%|qfiqiFGyd%hdW*O*y9)_ ztSNDh_nJdmddWU!f0De|9@~c5#@o9&)g(9Zn!Q;Udob_Nv)V%m8^u_r->w-SExK3Z zeWbuq?D20L=X1rYt8dgKm99L|BqpVjnzwO5lR9-3IXo$ZYsOFcs3^~kH%0iAKf?MY zwFLx{Mpjmv0xU?U0(!O1;HhwJ+$co0-D`fK`>gt!g{byC zL*aiXuV;;}HE&XuZna?1XBF>0vde$DZGCc9_m5?<&xeg#PyeWTq(E_4dhSL0waLE2 zi~*|(`!f@vNu*A-b%$XKXbQ=^ovBkLXzmfYQ%vj)D^(^XLTY-9!CN4S2;y=wVKOnu zf1cEw_0AvMu|nG1lFch#*f}u!n1lP;XVsRcFRtF36D?b~C$u#a0ifK-RFm`xx5@*) zFO3hEq?bQejgh@`&U=$$pn<1rOHMbp(jMxRKd`$bbBYO{v@3wb|3HU&TigiA*APO3 zkdCsrN`M6eswBW?p%!;9Kkim1;s>w!XsaupFGcg5Z)6|qVe=~z*3Naw`>$tTTW!c{A5@xMWw`s8uGij z`>qMxRS%WjJAaBRwDzHSu2bCsjp+&ZmbU3O{r{NzS(t?DPY$wWaev^kR`2%reV35rLFpI=jT1Dj{q-#w1$%A4O#p}7lY&$OJTq?d~|EwnY%a-%M&$qu_Ci3oh zXLP=X z`03iIlL*n!*{ZrTdJbzUvhvY(g4A6|uLXqc4upH`<<6&@Z6BLga&`2@&~m<FxP{ZeiV(&No`G|J%aKp8P1c-xr%T za|RoHGRC9&TD(a3Noj#r`}Q+ee)$FP4)YN^xN9-%>sH0VqFQ-jc8oC~ig=NuY$$+s z4bmg6<&qk(bH=*GbqJTFNUCFna4$yKm$L8Q>8;Tj+{PMH``ZQafA@b=fvcTOYi^i} zFaJXfIu3?s3O>t;&DhnSbr~ zH8)N9E-Na!TIE;$jFo+$`>xEi(D}EaM(fkuOb%2g)@)EsH|*#<^G$k( zanD2Z2eiUM=W@5}4%y7!7iEk3{n!{)xB8;*`f?Xg z9b(!W9$x#tkcxyIEf>2CDo0tt?CTvnZa-eKV8++Jqcv}!%U!d^-r&a8^h58iIglJC zGH`dU;Ez2lVhU}NAu3*prw?mAy>|1r$ zr}g)B4|KtZ8ySURoddjqu~jY>rmt7o^T*alLopG87?9owF{ZHCD&16ic^Hc`7T@gH zl0CJeOv+wAUg&(Yg;1=u9bBd)e3tumZ#fc1=zqR!2f_ibZa8G#kmlsT6QiBO1!;A;FmjE*hzfN>SyC_PrM4 z_)rtqJLTy)Vjg_I@W%gMDG%_8 z6n|Ktf%dfk%tN{oP~*`r8TPzV^ta>=@2V}k2NP+#Bp+H21OgEzMPOj4>8RUOC&BiR zSjvtAQe&!;5~Zf{8tHKL${K75FAU%3hTm`Jy1|Fki&VP|*DT z!v06%e+uXzt`Y+>#!)eVBg~3N*AO_uQcUJ|XB|`Yl@|`&`Z8T(@Xd`q?DvZxe_?%> zD>q+HoKsS=c3ujK6PrdnYFMioGV4HF87F#i-q0x9zGH_DZ%Qe;qX1(Z*|n)wLGF6E zW?HInE4n z6Z(>UT<7Z+z8OR^sZ}vUT5ldhvx1mNfd;!Dp$2viVrYqSvm5{2_b8*&{J3m!Z+BL3 z%TXB}%i)gvFBAF?peLs&Urp3>fdV2MP8r&o*8+X@Hhf8~D*l!0R3B6ILzrFjY2IPq z|4Kjg-&1JDDUY7bh2fN@rlzOR&qgdt5>B)qx`Oos)`**e>luZ97cg!_)sUG%=0E7n z080y25JFWYyPpO`uzzTBtQb};3tLb94%T{M6@a@W3s~hDOh*g*w z*~F#XHJsY#^6%|v!$h!Xd?JLZ0EnT)_5tB2@v)gTh=%?8Vb{VC-m<|~r<9LR0gA~lfVnSxwxl~6(XJ3EI?cHAa=o2#&o6~G1 zH)3h+H;=hO(?Egl%9WGf19~|zK)_mpot4|`Ic9K%LD$1@{(`CKo}cpUGR*v)wQFs<|*m0mm(53A{5OKueiE zbY^6rMp%6>cVFYDS7!ElTVsT_#i>zEW9DvgedAXC@)?vh3ji-n7M8WRm;!2q-qsd$ zVUv@S3%*68MbU~3Smk7-)Oj4^>z`_Qd~2WbAu2_fG-xWpFRt_F#EWmPDE`vEX*v7o zmE(gQ;w;|F+72H+noDIVvl}d3_*fqPz{oAz&ee>!i3=hri=yklhNHYiIswc+s8_24|GFGjfEJwAes|xlDv>zs z9a8K1?Bv^8?$$ptOz(DA9N~mQoF@vc^_4?F_!y#Hj_$Mv(8|b%%IjnwgT7ht*HN_* z*xKDFj`2}6x8k0Ox-8BT44eDTt}ZqU;TRoYAOJw_Uvuj0~woP$Nzrf19eoE#mASQ{d19I%nC{b~U489O)#Vc1xf29Xx| zn#n|NzB7yr^f>tU0jPlp+zis_x+PXIRf0HwaO>`)n4LmjDY~rA*uca(Vz!=-WDRQ2 z&`oK0*M4-=!$Wu9dA~Uu1s;DF_%e=-5!FOMg*GaCZ~x)?8D#VOsK>T#umz`)jgYt* z1L9?*q*5^jQ7J%NQZarMG%tztU@UL<;O(vXyV`!|JJe)Hw|z7<#+HKeJ&s%=jFob?T_p^zhl!|_j|A3)DNZybj z;{*T-&-IpaV4LAs_Bv4@LRds(V!X*<%*MGq#72s^eEj^Zh7yD4^>2C4XYI@%i!;g-5achSZffT^!1EsgRr)2tJC(>=jIRUM)o5~X zYhJ5TmtsL@7xerp9i_t*Ni-5;pt3&Z4WYbZCrGk4q->Mbpic=^oL9XyKeuEwMOllt zASp|Sy+ZN!kE3~cdFjV*=|Ik5li#e{h3Oh=Q*UpNY})ImGNpB2N5vlzd~e)7vak7-Q%(mE!yWLz&Zr%f4;mIUvXaq$%ayK(!>iNq><;$Qi&pp!+%`0UxUnh#eU ze(CL59@l(O9u8@w1Hu?k(9+r}1`YxellXJW06Dt2=wj6*Sy;?ofTio0F6y4e?cdTH z<|L_0CE_Qie%#w>6;;7Lk)U`>p9aHzwaPaYE)`lIBE8Y^^*O(ho+QDBVdgykg5=7H zE!~kH6KEfvHpaReXP$n$ef(XN=Z}vS9Gn9pRG&W+tK&b|TaPQP6N4{E=9y%uv^S*8 zwWjpHXrFrsn3+IlJb#Zu=f;6$0jti>Pxr#+_ig;St$B`h#&B#DS%XI{IrMnN&WSIo zE!g@gOHz*Ko_wJZP=(|AAm_$eK_JiwJd)r?36wyC0=`X3$GVcK5TvNw>^UJu8kh+J zfiVJHJ_FiZQ?Jh=CtXcZnSY}$*|b~W*93t!&wOqv&IB*LZffYP!Um&}Jy8ecvFcGp zWoH~_14vEvZ)?5B;KA{shi&iQQ;lkv)c7u2jqqK)XH$F=`k#1xY2+w9dEG zf;~ij6_=VmwzS=)88Hd~h&AEJVAxK{NblfZ=uj`*?8+a(DW5y1+O5j1T<`WAiyF<_ zitxW2K=*-81EEZqR^vcU9yR_xHvI%WXyRp!up6n-_w|QN1|dXoDBpFXI^DWsfa3x5 zLWo7xT|65%e#GVPhz8bNn(?iEjd?-5Q5k2iV$=Pq`Inb&SZbN8o(tgNaLmK`Lvk`e z+#snV%5n4aX(iM^A+cqKpv4$s5@^XW`(DaMScu(=k=`N@j~&lKt7qK-pi2SQ`XPwu zu#$~sre}+bP#EWr%0x-02IFb%NO7svtxfxZ*zrKo=yan*V4b50Oi>YC6U%7S-}R@5 zI5%x-#u-dfG|W!1ZQG(dB%5Gbnu^*trspewkpY&2Khxkn#WP3^NU#ci4?8mpAAgWv z!C`dGq_>g zA5(PGGoNTu!~*1NHRGxEL@xxH-0q%rCJ6aqaVbjs#>mo2w?e0OiEurE&OqC1Cz@S= z8@LguGW~8aMk9Kg@nZlslY``U1H}QatN&04z!1WhR=>Y~)zYAy=Y~^Bh3@I0*64A5 zAk_3pSDDfw4g3P^z))Y;{Ps8sj+wZ$Bu%V@9oVJOZQ8nTwSbJ<$K`d;CY#sYuu3mI znt}|Hy>pXdf&T9946N~VKnbBOZjOV2abbt= zl~0Ew|Nh2)#nBLe+$ZVLa|o+sBV?^2F4owvbjzzHS(v_ zUX2X9cx;2<7S!6}*roO4dBEFw-g!x!gLNr*U@|=eEu>w2;)@)?5+LS4VkR(UKp1s% z03-`hY*-?qqM)@R{d2ypsN}IOFSUay0ukV$_hxP?*EF+*P7k%nLEE` zG^)ODsO0B=SqD`W>IjTGD@zvWF~B8%f`4c-uLvyK6DUmKF+URM7x@HS7GP(4sihn` zkWPAjEFGsjB&P?rvtoAY?U6p*U3o(I(m6-Y+)T5|174Q}cVV*;+b+{?^AO21s0B$u z>pMJlqVb%AdHx@^On9W@YsiTLGT~ulzesKEv>V4D(5^@GDU=H7A$UTgvtN<2Ic?pB zC#W?4eN&-R&NW+UcC8}6(wh$eQP`a362j26WOS9@&_z=esR>shFvS+2DF7#pkfKHM zsH*e~eAf71sN`uMl{13ZiJb!im59r$;`zzJA=_fX?wNQ9iGM$O5yZhZta3GrZsoOj zN$2MmrFeA^9s#8xhI8oHHxKX&^a1x~+$4-P!J(pakIBr0wbsZ&%1gzl$e${MB?}1+ z#c3M@g4HN|e8G%+Zi*+?*_eEJ+%@%Sgsb98UV-aujh&O*aS^%7I-SJrCq6f+oX~ei zaVn9>7q30SD!248r96{~dWcP9IfbfW_vGEotZkh2+LNDdHhfK(9NQK+f&`eiWy|(&JIi2@hc0y@d)VZ{N-f6t z%>s2fs~P5J?=tL=*f7~I16fM;F^;^0Td)@sc)JHQ8R1;x+L-d%HGg2TWZ@+_&qKQ< zyC6|-anyemI%dMVBS#%l+tQTN&xS zZXI#AQ25@|YcrR+qZW!met+}*h_<3Jwu_kgDWGPFGaL3vqDAFwXUBhU^vHA34n_UD zO|h!NMij&eYTU=#M7@+5**b;aZM@#nHQIl=8%fHOaQrVVtSuhBobyMjeU;xm-2Lg2l;ZPWR?u;jsRH;c8caDSpywjN{uAt| zRkM$BA<^`4Gcw7a&%U^tfa#o}T7d^XL2NA+X6qMRs&6q0-OtOD>B}r-;Lu(Mn!?U*);`mmKmO@R6j55mh=D*t=mNx<1KnQ#S&dI^Z4&uk>fV4Ov;gvP zghA#fGNqn>ca)1`mW{l8Wpt;uXmC6S!gN}?N2o>!kML25Fo_oCcskGA9_*E??j3P@ zE~>`oqY9)9%zToRFw>`!;y(NMo_1%v;nuv$E?4zaw&~Wx&veO(L3=z63I{rVk*9m# z^%E+F@1MLBrrPa#a61+a<_Y#h5u$ASCkx>xQ{KB00L)F%<2XPgs)`-OQ zAut)&)Ia{^F}PjBJb4e_90{i4ldAWOX{D@V(pAP&+FXlpzkTYh{J7tI{eqFHX>+%A z3x*A7BrdyL1x5Hw9)bbEBQWuV=SG$-TQ)&DI;t}bQ7~`o%j+VrYWPbir1_`Bdj?-U)`KVS z5t>-Qv|H-*%H$j8$8Q^?2uMoSiwwM>DuGM;5KRD5;3r%hpV8ezh(KtpqPZ_6bBRDw z<4Y1GSf=94wJBm`6g`CBZMyD!?=o-T#H_R>2fZL{h@j$i03rmSjt#`<37}>>5tA~j zSu#J7BjTwU)qmUH&rMYoRH~8@cU0y1La4qAx6c9-MdW4)DPQxdG?{hLMVR(u7V)o z=6J=~LJNWfN1}5VaHFv!L&P{#Q7FHVPGh|@?b9l|I2-!z|6*jb-*91K^tp)7%!X{9 za{Ef)`iasn;rx=aaE9tUY3KkZgjtF*s>RqkIppp06~DMagqwBA2tSto%5iqkHbr$= z)9!5vDAa*;Wq>&|a}7vEJUtYAvlpgQ78+D%U#o&&-7m0!slhP6X8rnOpShc4$duNt z@tTg^(92EX4}+_=qdgiHs3sGv2Vum(NK<5P2UrCYJPRW{GjM1+i}=Q`BgM1O0zl~A zayno89}VhcUzB=ktHm4?dLEMfH5*kfL_#b!pSKA5;#{hbQxchw|77ifJ#!@3? zpOGlPY*K?ko_VfbwFzaIi?3fX)6Z7cDn=MnMtsY{=^Uke9rM2)S;BHzhmSR8Y@)7D zsCiYHDilOLD>j}z3ZE6y==KCm$4e<$XKwTiGCj00N$&q1%X>z|T8qpeo`Gd-Am#*% zol};$^2|jz%tmzb<+3?r3ca5WxGcRYlRGXf{B4IfS5<~;aZOJns!lrtjXZuH z9{UNc0<)8Fwp&|u`utNKhhm-DuoP-b9?y2>QIC)BGR{)!+J(mj+Yfk{Tz<68fncVG ze0mj$kni>A=xzN`swlIpvpQ#MeD^LxD!GjKvOQy2!8UgDpDaDvioCLUG}R8~+K2lN z2l4a;EZg+{$+0HDJ{TO6rCG3jZV2hLcwiB9i_zA&>#Hk6+8;jWr$k=&zwB(n<9P^y zJPmr?2sYG!0_dc^)@~KmomTJOaDB{9AcV>%CM|7DP!_uG=e zxmeGtS5!T|w!H9=m$F2PinfQx6Tlsrx#`8Be+!UkO7ew2=7iBqv5}@dL&h@ho2U1u z-+jg&Ts75ohMj03e60S$#b6D+=3+1c2T=BsNdN2~{)jv+UNu(v$AuBCQ(d9sK956N zyU~^eY5%=h$;<(=IjQ;6RZ#c>jTG2QBXE;9`?5?vMBE9s4IOhBx?a<^kB_mf0(~Q* zaX~1Cq%+^q0X7?bm~1dbD}q|~M2k~s`wG9WuKaLv1Bz7GC4O>A>+z3-e?KwMGVo4u z2(Cb^c!!{pk_F~32YFCx+nS%6{ci9Ll%gkZ1*3W*h{6K>Wtw6MCOZT@jlO@^{Xx$V zkZ|`hHhM;psKWwV6DwcEu|=)=x%XSn_A@glb}akc?P*{!b_7#XFDYwc+PSX2zBib! zuh@qiWFH|lAd*-o3@8h?J(!&>EIZG)*p7gILc9#7wzc>U4T^4x=ku@`Ky5ws30 zl&H>FZ(+GyZ>VV;S;p=pt|X?-7M`~zIbOioqw~BwOSfYY+WlzLrN9j~?6J%^x z$e&21&OD$NtJara-LNjQ#_fASyR{P<0}wz~u%)a=sd@%s@I6AR<(7Bdzi;32G&+^H zTpEnx&D64S>|EVNU)8BGwVrnl|BhasdG3Mky50A%e?BW7xpK14+4}EI$iq+=Q>n$0 zWHZ+^>{`naGjvF6*bi$gH^7m0!ZIb8_Zez&G3l|_mfEWr>e<&;1jH?!?Eg_*`Yp%Fn!x=J<}M64zU(*sW$kEqQU-RZNHSbj0c=VOPJeFUfxV4$?C5wYk1hN=kT3sbF|yWHX8RurQsc zM|*M)O?%TZ9_C|2TrTD!G3Hh?eigx@-pC=`b3qB0R26^)6NU8`^i`)`t=eyFtifCQ zBG7i%dfHUj<7T12*Q>^@ZjpZ0^^0xfDps71#WBFm5RQ8L{GWV~8Tav0ymZ$yg;1sV zw3t=3_>`QJCxU>5O_D0DfP%uruaka<{l?_|(owNwP_MKj^SU%xOYsbjd126pZ>(^D z8N>RgbhAg%-kKrZf@M5DhEQ%7paySfrfug}TVx+LJbM5hU*Vur&$ASnH_o?YoG=LV zetx!(4w0HF$x)h8=AZQEcPx9zB!GB`L0Go2NZrw#UH)V3cFWi=dUPft*sD`!KHMc_ zAa2(JbvU2~2c}kVVZ)-2akuPmI5%V)hg7dI`M zvU(HtBH1_l;J0#Qj+d&2;^G7nTyt>3IaHgGD_{dGm1#Sz_WQd^;1u1v068z=P~DM3 zy&#Lh%0Zut>c1eD0ws$J6Is>=936!N{53djXy1@lGthuA)qN_pvDU+gF2){!DT2fq zpRV__B5bk1)Y8T4Kj(`Mbtq^eh)y`>ja|e4y(5=?h?hoCXXBnc!guACZz6A7 zP|L5YU9;Ox7ulLWK)R$$LPSJid1Q`3mqZM+$k1lz+RH+su6bp&bkJ+)YaoN)J8U~e zt{26u2H;l7v1ZL1oh7=$aNQ#w52R%MS_**?g(;Jbo12@XWeb_jhCUL>v17)|)o0gd zUS=4EO9ID*@5`;I2H5-;!(w4DgDe@kRKWrHPocg1u$F0ntmzWz|_~mTf z)KW6<3CIjPh2fBti|7(O)U#JS2d_GHvZxo;bUmtZyZ>>+NmJ7-L9%(r6fj=$RSm!)b>$Z>Oi?_RoKIsuwwTx;*Hfi0^#r=;XBQ&23*gziPY3fYS8C z2C)e%^R;UvMd6jS#vZbroNK{AG{y3!tSdW>hehSYJSFTdGSwibZK|osn8wR1MecxV zZ}BIOYe;zy)o#~%x&Wl!S_H;VG6_iYTA7MlACP)_a2NT@V6B@4Od;nB3?7Or|2UVP zd#KfLDPe7}VW8nL9L+Y6HyLK*-xw7&dA|PxGVZ<@H7|raT zkZs%@6W zt4Ym!a&~%2ihKDOZFa(DmzJAB58N6hJw}FCm?Uk&oRYHTYKs*1^pkdD!Jx8;E4zi|8B=LybfMs z9$^0y-DtRU*lQb4G1B7w!1yua%Ny1i7*m#TrU%if=)y(>z994jXmlvoo;kp#5n53s zgjRdR&HUI%Bd6ki_}Gd}ua{`(T4d0vT!TgQK!Y~V$Fs#_8+~=lGQuJw9lO`#`22Lm z^LMP1kEnfQi(8tJRZD@GRTkDsk=Izk9(s!yA`yZo_~A&DawaP3Xy`q&F;^9(9S_6v zC$GBR)jDLoJfTar$)lmRwl;M}YH5cxQgqsSM6Zz4`PEL<1s=PI4jOt*%Q%m<3VJDX zl+nHZB~0hjDY?@$3;p{{5+%u`Oh+ItXJ+DAueui@YA^*6!k~z+NX}`&dr?hYoYCne zRoinACD94*gS2g?9CU~L4QW?E*EX>6V|sY;PQCGuI?ERHqMO#eRCF&mWb4*X|2J3U-NtPP zYN38N@A&wjJ!dGY>cH;Zfxb8q#3up5KiII2yQkpO zy|mX0QT$D7MQ6Ubb0%Ni%~!NEVkHAmoBv`K?+F5|-MwtprtW>7Va%BjU<{!S%V_)M zp|<+my}S3)o&-P7ZYd?VXYJOPPY*x&dgO=ss$G1H)ICJr2C1nf^Iaa^T=BD`vKl?z`i=GuQ3S z^%<=298ZaDIhK5)X>4q)kdrQ63u5QQ;TwUVKJht#>LIdYbt!e;PjV#wM~I>M_4NfV zl@Y}iDO0z~Iy0>|?ubY#?z>s@9cR4B#`7S{tfQlA`k#0SMkB;^o6v>9$Kj_akOA$lFN1WWtpAH8s*+w?wr?+_|3DC@7F!?g^xr(04d!WOQaq^wMu!a zBj`C=;lLnh!6PEV5b9td)KbCguN(Gp9h(W#x;fA5?2&8tBisA#hIa=yn=iP3f6=mI zv-W~c(*`8s^o*#zu@XE1@Q&}{X9E=)by4BhE7S3yDMyn>Y7kjwMBmWM)e_q5{jU0K z_4it7^X#G7rsTe?I3-u;{OCqQ{^bIE$xMOvBJ~j{ys%%=p&e9oW3jKp`K~;3Z8$ox z)?9#{L-~A&ox7=XQLq2~NR%Xb55nQ&AZp{}NkDqV6ApVJh722MvrWorhsP(`&-0;L zU)rTU4(J;gm>C&O(=l$fWyQ+vsi$bqkh`fym@iF>em4m^$@<=&5nf^e=={S_L2 z8g%|=kr5n&69Hk9VW$RAa*wD91WvH3OAScjlAdlp>|bOB+6IA)5tt}ic9gdUFt+7D zLc6`9Yvi25eKI^?voMtYT^Eyh^8aD(O`vk#-@o6xfo_D%a|21(5}`~@GDIYqHAsep z28tvVQkiGUOew=Qvn5KxHgDsWp;ViYP$;F8^SbWr|L=L$I_tmAI?p-hIj!Gs?Y-+B zzTeOH^SOri^}gO$>I4~cL~&Fa9qIO1`nj9W&~+ozTiPm|J0U?M(jsaKy-_1YbWR}4 zNRJck4y~*4BEU%%^6F29?V-?fg+P~Dw7l!P!m3Y&)Od&JTmF_K3-u!$N8$HThA$i^ zRuZklV;?@uR*#)}xtHw?Re-4ZJI@_81Y|%%w8e&&rk3_s35U_byxyMh&eneX^yzPc zrzlLvAXal`R)&cb&l!*keeU-)YT>hxzl7j>fEL?MJQr4c!=rq|7{|Q~+d7!=x=-tR z%-&qqs19-vX|GFyX*)~25>>x|ktt9&oT=AQyHRQ>EZdTv<7>UqMd+K#@dg5kjA@fvED#*Kdb{P~WXzo0g&lDTVtY(#h14PhINR?! z1Txx(hX?<8{kkBq>dJc15T78XByEWhESbpWB;;ZZgG_$pzC z&qJ`NrEh{%vA^|w|MM;^t_voMsA*pdnNk`mWbgoNXkWpeWNUURks{&J17@h_XIH> z=F4!?!sJ(L`!4mKkd6|T1n!E<_g;N|2iPo!0>6t=luS|v1xr^W|J2nz#@UhjLZe2F zpd!}#-o~D`w~~Cvus#RZ&V(K&G|{D6T*(JNOz z1a%TI5E_%Hwl1IDl$;9%%Q^QK8~uVetxdlM^^>MTdMXpZOF_wQO+P&oM9-mPjc_Y7 z7DuMK$q-`U^?&>JZT)R#fv>HjX0RNQB7-aN3+XL^*2t}FpjN?JBMM?|p(q-RKMe#M zokg*qxn_T}<8HKGgdzhV_0spEhD5w@ZFybH>5t>G>-q!^71azZs*#b=W{A)1Db{1b zw5d}?_fPsS8PCAqmR7}3W)wJ0VnT&ZCq#nbiZIB;M3@GzKFbx zM-lJwT-t5B-Q>*m3uxbv^bpX|{yVGmQ!q+Bg(JjH ziC_-gU?EPt`mCAd|B`(%l*Hh$XUi5X1TIi2GSXjtre@}dT+VYE(M;Sf9t2bUn4nn8d<&hPiU?6n{^f+@J#Onu_(4;6q_s4$9%^F zg>nKmOI#4{L8O&=WRKchks;WKo9yjt&JI<@YH8ab%LLH2E2bP06h~aB@Z-lf&s8W} zP*a0~A!BJ6r55<+P78VloiBb%O0p1zM4R&?GJVd;G;Wu@Jd*I^wEph03affQy$1zM z35ZBKpRKNGedEN$qqpwf{hI-C5W^p5Wwj~lyKyW0U7A&F7Fw!ernJVgnlw?+Dk5{L zIR(Aq)O1GSRD|kI7Yuxj!{^SKPj)YuVfnSi@I99OjqhE-6j#4}H1w_eBt9~a4Z5zJ zI|w@~*Q{yZT4B?b{F5lZ|^D%EQeS$P^3Mc zcOgqA7eVSc#_5uQ>2Q%DgUueKp>IsZ@JOrkA7B7Wl{PXes5?6I%=*(+XHNgBMeBMrmmP-5DjaLnOAxfeF%7m*IKU3|!Un5GLA7lwK55(S zl6_%ai9#d}^tn{|ZT-&v{t#X$@%gFcru=jjQ9I9u3aDPad$U1_B%N(-)hW%KMetCj zXAuA_x;JSIr~%r#nCxE{+G^AlFFnpq95a5rF(w98>(kC170v|| zXo&(LqIb1lNd;US)WnIm&MdSS(MV>zjWcOXWT*&}nh%F+D@;JT6@DMvd7pxy%%JT~ zr9%HqZ#n_cM1iI@mWTl&BU)H6+6P!DbTr8=41fm}Wqw#%c7@n5syc)f{ErdfBP^=5 z>i7M_;GgHofkz-_9cFY35Y-`C*4Th)Q!l!Wjh4+-rYVFw;iEB(Yz!l=wD0_jnJU!Lhg3o z6uLxd4SBG;{~}=S1ma*+ok&vB)zA;c9*2*7kez*8>LZN%lga}3!fkJki5c?mh3x0F zu|dX}$DMpO8&GG3Kp|R+9}z0gqHwO77Ecol7AW}hwPru3nr%OE!c<-T-;Wn^8M!BH z0o;o;M`0EilR_-1DH8Xpi<~@ls-5U$;aRpYhJ%ZwRY>Yzexhy8QPLmnk{n=2rMk+ki1{|m0fz(6n1P^O zX9CR1?(5WPRFH+9NA+_vxJ<}F2#T^2rZ^?J#a*x_45Gp^oNjPUxzfv?6h4I?MEfRj z#N0r$?TD?jma;FDO_;3puXa5fdl+|$0w2#k$5mC0Q0O$I+AM@j9B)U4OY*P?Yq2S^ z1Bo`EEFnxyR`jjIjt9R@JQK}(f5GTDNh}bt7CHpuAfZ4E>U70)Gfds-Jw&OUX*IUj zD5(oQ9~0J@Lk*dgr~scBp`q`kD$XhtRd+Cx(pN~DXUudrE|HfJ02#DaSl>|MW?US# z*%Z^yz4-g#!~IY)kOR8$aen76U4|3Ni`k%KN`@>hO_doT0?_k_<+vIR2GbJB6tawh>bA>vn-%}eJrA>WFFYpM8Q=^5?%lM}DnL}B zDXj;G(SPMRqbBG*XAaJG7xARgg{%?QYKVK-{kyey??$l^tVmRhv=o!QS?}9iXbF zw2K{vp^EK!Ly%YDO}#ye0RO;gjc zzzLP4*XgRG`LfZT@e0!##Cw)!w1=YI`G79ho{&pfEmthL6SqdQGb=QBy;}Om`La$D zK9h!F$9UE~P?v>or><^#;MelR5MC|*{gS!N6W-o)7)_v2Bn_j9&Cu^BoYe6SZ%!^p zLc&$h@7ES{No+#Y%fYB^pk8m5Qf+eWOeC0Bu3PuhZe0Vs6LU00JrhGj2>JvkDcXk? z;kR<7iH*caVg+P6q4x=5+*%R(h!$N@f}~2N&{0Z)PcjiaO3$oUud$qSnN%P!Dv3Su z7!K&mZNG3C6ag7s!eLwsIDv%K6|K~Z&SMdosk%YGXgAdlMd&yG#8siA@mCY6r3q$) zlc25OAg2^wI(uSgc*i$HX-}UXq+xU5;K8$q(%AHXUcZ}b<}~_YD%K-nq`?nQNl;Ql z&LhWljQEo6@4#WAoo?f!{MS<*PO=lEn=c_@5Z@+kW$0syG@TYF6Z@j<#ZYm0>N_^R zUAtn16Mw{Z^nhr_*Al@Uq5+GHYUj?5z1UR(p}?-djBfO3j+p^rVn2o7qvTJatlIQA zSM{MH(R1D#2NI+A?8?VdoN3xL0n#~;!-&U?Pm>8UQYDpFy&R;E;- z0-(91v}%MkgCVRqJ!+-fCH6#RmOfr`36d4DWHf)#VEiV2xB+bmv_Om8>9uC=kMT6q znn%i<5H!rKRf8U4mS39!(a*{H(w~@b0+hpmxAprKg+l}mJlh%-+_?=C*W+$TDg)`` z0A6JHgbPQO03bpmM}v6UHmxG;o7uF+iXZJz>q7m!+n6P|uQ5nJ3;9*qY)WSpNg@@y4ob;>U9C@d%S5^oixd51pYxh}dWL=HprH6e_|Z69Q+I zxS%mRmMxL6WyDGTfvG|kcPKjpUaiE!6nSzL>kUN^_5AtR>Q9q_9a?wSZXmT6U;?qx zz2ZsGNX4|%{+Da#xQ}Nba-GtBKwAgTiD&d@@Bl_42v(s;NVb+y12zk1v#Hn=kBH#7 z$$dyk4tH>14o7q&tAS{8NaP(ic%3LKlgT-a8nsa{4K1Y&WIQ;~22>i=CLhLzYrU=) zx2enj*@1B-m|Qh^`h>pH*K^Nr#!ae{dRsfXy`hHHf`p-n=_F(px*cra z$6(YXU>1-Spkp+F3i%HcW`BciJFr^~jX z;L}%4VcE1n0~z2O5m1w)Leex5sebUlNtWn8XQ=IGvvt?wI1WU-od^H{iy3*r%byzHmeBA8WuZP`k+#F1aT$Ka5dGlsN zSRyz(P(TZ7oyxv+aVty*HtjOePFdIvUJHRZ?sgNy3!I%d0l@_PDD(dmXi=jkEI#Db z^I=Pk0v*u4LeEs4?OFavpcZYzhAJ$-rD@dnyHd37%aX=T6Nri=Z86UZ*hKBS33p8_ zeLL4rXZ;>pKRG+INUxzlZ#L|Rd~9y+kFDA#zA-}x^ z+=bJa#mopcnq-))dD($QwFT+gx6ej)m%IBO26^IkZUqlWGel_n?$Pj~)Uw$6ije61 z{hOTYy=ARPFobQge`3`qU?ZS0xIkLohg(=HUPbi?(GjP$C`==K zT}Z*C?1#iM%JjiFZ^_;94fm29xVB$0_+9yI0UGLnh z*H%;YXi!A}AaSwJpLYT~GY;(q21TGrED0Y~T`lATOv&<+<6*;9Pt%G!%csI<$P5`W z!NRbg6||B?bQ{R#zYl&veozgxMHirILemN~8Gt)t-md+d*b_Qmf08~U?wXdMM zcZ_)qYBY*tEzY>Rq}Y0* z(I|6&@vekp%rVz*owNAF*p~7Qr!hrX=so)Ctsf1%i|*VzObDZrBM7t3B0j+ivx!f? z)G0G#<3td9D9RpD@PBHs!B%P2LQhXLx&vT30w}qsT*_rr*3w!J_A*>4=gJCc<|5K~ zv}WMP-XYnQiP-O%4?Y?#gJ1dA@EwCJc(Ghgf5)S%kqocOAqJCsOEExlz!5;G|!S8~z-WDMOWbegYD!obn zV0LSY+q#BwNk4(9m?=wH_23%XvOt+`c;{bw9n3bWF%d8#5Fu(X#-W| zUiU7 zy4gmrOJ`mW9aJ=Z9mGK$KW4rYeok&$W9kZmRIAqXcB`2|Nkk0RI%=PQE<`b1>9Pr@ zEAR+Tmu?$&2D^z}7_lszSjtZI>@M9wrkl8ec4HZoBd|v>v&7FZK|Sxyn_H&Z00JGw z>*MNit+q{MJsBqR8yJW*FN&bem)l)uaeI9Jz<~p6*MEDYNy3w&B2)8taBAvGWu7!` z;Pf?@*uR~7UhE^P^}mwMNDm;%ZGNWhL2>g+f>mC!C<;QWM4bBSGL={ALF$&$4v3tU zHvl0g`$Fx6iP)^!&a?s_c3VX*Jqc?>pJv? z3op~_>GxW>V#NbQ9x*rM4Z_kQyGE&=-QHFJ(^BZ75g*)|)>T_c2bm_* zI%FzfGniuaR$2D9x3s+0N@s&9&GG?~7c4j@v)8*IicSy+`wNu9uyu%j!YaWfLjg_V zfL^&c(P&3CPZ_iJ`YXADK*A25qu{ALQ4qr4&9Aycub*+Wha3|}hh{yan3dpjU;EJx zU{WB~Koool(A->oW43G=XtCaqJ=Z{Di5$nwu=}mq@{`TzHU2m3zH{ed@=H@7KR?^Y zH*Q1|U{>F>u$b`B4I^qn2EY7)B8g0#mf{075lj?Av8bPI_p`kLSn^*Rzu6$IyB>%k z;fXsaHTx4tbFM_Mm(~^Oz}LQ#^Tfg+Ek6L(K2HVxgcOFT?7M+Iz@0FNAsV5BYUkWz z(YM*@wQMmfD%l^gJMQBCVOi@Kr3E-e^Z}MMl(V^#&a-UpFsoKg8;uw+K$tT<9 zusNxG?tNkLgoK=S-x*TIBcY+}-| zfD%rr$EX9sagrX2Igtd7!}`k;?{u8(+Q zWWcW<_iNz!9D4egd(?voO;yQA3E8<`z4rv#59xzAK&v{%AjuEOvLe3f)?*|+UDIo- zGcfc=_kqSNHC@6n2R&M6J9D1tDgoL+H!Lm~UlbSH!Tfw17m zXO7IOCuqi{?{|Hhw-67gUJDPnOx}QOmcUX})xTUTXzjfO%G9&|koj!$6a)Y11ap?VgB6OQY6VdJsoQG@^sV_gu1P439+hLKM*t z*I^s{F0x$|E~%ZD|6LLZ&ZAbb-4U&6dNgck$CdtD%1$6$F*>Y9NcGRzjzWL9^`GT7UneIUhnGHtDzJ8KJ<<5%7>oi@0Z?kJ zYuVF1tX0dF#TD5<-9&k-wdx+F(Ac^2Dt!k5#TnS8uejKig9~&B8e~l3jIa#Gs2W$c z4EqF=L6S9x`qb1Fca}b|`D%fXD3$(N>S=?!qmM!XZ6+Fga(F$O6CpXxpZ_g>>j3Pp z1OXTs`OQ(fzvuP18HGQ=u%TBZb=aLn8tOQnQSJvS8kdNZC1tanJHfm2>!mX zu!FMtSG9a2#vT#v+H}Jh6GoErJd8vZU)Ux8!>{U|+hN*_q)i1EFE`bMC^B|FBNBgo z`!;fE((|RJwFYUaUXvE@5pdrHr=Whfm_OeeKGVOS zbdCXhl5IxV%)yB z_C<1-#BNL;WoKvS#rD$lX#1Z}va)g~Vd0aunYhxwX~nk*IOe!^$AcYp;OME|`A{Oy zr7N)C)pxd%;smIgPK13>ircT%O?y3gfz!O+j6tFdTT5N_!jQRQ*8t_%qmKrvDT-43 z+ER`Xu`!^O#c;l4s43+p%=59&v4L2*8VOv6#<>trv zj8s)^78jyG0x>4{Z33QpI@>5s^e=EG?W&g~r!R+{2KjIbBwLs}g}1k@rC{a_63wl+ z*Bnm}eTC>lN|9LrC=pcxev9b7Ty{Zt7z{Z@Aqy&s!9=to#KQAB@%c_;q*CtR?s^H} zYZz0SS>d!x=qZDljd6C4gZd!YdDB(PC;y0N%SY8~)ArZa4a8nZr31*LGk^~qg@}K& zq)bJq@oV86`eQMejeLkKpF#`to|gN{?jt5LjVVRdYpc1oswz~Z1d&#t0c)&uTb1n% z@y$%y!2T&}G`~fS@L9-xNRUf=pKykg^R`ZE+@{TN(@pVb&u+Opm6uV)Qp@oqND}-> zYCO@=N)e<){r*k|A%Cfq8B}Yn458<|gX8YU%;W$&iznI9xz(Xax zK#xRJ`iL|k)YQsrNvJpr9_6nsd1t0y(NEt$bc%=l%LOR>YuS-bjeh(Ln|pd=f5Y%v zeiPE0>Z?tdS}R(8it?1*46ifS*Z3c8nKY^bess_=YiX_R%xF54IVm2%VdeD)BX0$ z+x@lQ8i}BBgFS=)I`sV3d9KplgXt<_@*`TVbs>XNb+i#3T_Gr zzNU3=M94!M-zjyu805rWjbrij`M3o#Rhv*5v(|I=Q&YTwlW~Sr6bOkMV;wa~&U}Dp zq(FTvk)0DLhBEP&7BhR*!-XCykM)tak3x=Xrkm%LrEG)gqCUm z$i>rhVxbkX019h;O+~Ab(cXafQwp3kpxFI>86ehV5AR(zU zj{7tN@W-;U*clA8QyYas-9V93L6(xhM-%=sf1y*49*>WFV?3e*A#CD)HEv3~lZHY! z2M`F?{t)jZSSTxcyjFxlF}bLSI!M0=@Hi?{%o8%SCu;jrT3Y&Uv82|NXb-wDO+7*p zUiI$d$1$Q5qTBy4kCmE3(Cg@UR+iUwZh|-Aq2-9SoP@*F+|b5!c5&G`cutr+o!Yez z4pDuMB91swYUHv9&~+beXBRPec4>xt*in4g$R(^`+nQU{6kYvEO@aEotA2c!f)gN8 zX7Hlhw{IV!#LD$3W}JNSQTC&dwt%%D@T3Q{D z>_aq5K$&pz^E)wUo$kl68uw7~Kyoi)C0o~8sqotZuMWRYEbb1;yk)m35tC+Tkb4F| znCQgjWvSBuE1$EM6RC)FhQ>)1YS|xM0HE~3ew>8AauACqE4Abyl~kUHL@CrL;rnQ$ z)`dfIpPL*$4f|QM`RJO8kdX{}AueXcoe0$N$mf|>}{W= zHe9}yRDp@{gwG`HC8V;kZXGmkabs>l0QpH>u*2K8x0EJWkpVNCzFJ*} zciW$RTi3$RnhoE$ZS~D{m_<1naF!h|RVZ$CkLz@-CspbLMJhX?xM&0546qo;^8~0_ z9vNBnE}QIMs1}WRa6XYvgVYoWa=P>KXsa4Y&BSTq#OLmsS9sjcBNd7y13A4rnW7{T zMv}MusH{XzY1+y0hW5fkAoeyktlpfyPms9*(+#yBu2ztfOFZB(=B%j%a4k zSdlhOas#GSid&8Rtudx(i;@5WOQYZi<0U_wEPljp@bmxNpX3zr!_MYM)|wwos{G@B z_n-dXz48C0l~gwvC@Z8$?HJDPQ~2$AyC+Phm)7eF@A`e};^0v>n_cjHLG$iMz3DI`O>9JFJ`;@`WD`u^?1!!&l3e6&rVHi zX&I7qC<`>gBH1de!~2Ze){>a&^jth|493=4HGZ!s6SL zYclOO8Ogj}=oGpOec+8sX`WC?1j<>o>ye*pH8S#oog@8_c-nq*t;nB+J_{O)@n87i zJj=L`SewrEfoyi7t*-|^o`V(P?JW@#TSdULW5M>w`a0=ndB#$yku-pd^(onU<=x%Mw>Ed& z-hJ9iX#yp~mf!+T;J0W$2sI)uAY27Y%a?HlB#VH2BT#x-Crx|8l!W635WyGCtvDBj z8zt(0B4lQ^+!eiy3#$wUM2a|+bSDVjh1(K7D7X}y0Dqb+VKqa#r3ThSSNGHBjF<9y zA`86{JlUkw+XMgc&6LKhlLWSvyXT5mzvx28C zZx_ZVKCP2}+UXs~asK9dK}2-|R^U*@yYK`K`spZhUFhHz4J-)vIcF;@=Dr>x!LW42 zR8>}#Ys-}N)_Ne^xN)%lyv+!<22lH;v84iPp;IhBv=AWb6 zJ@q~db646(o?lo1*7yF1TA10x>?lKcA`ftG{rd#{*nI!~NGT`?z74R#=<8zyyyxBH z^!2S}g{cMin0iB}aCVudrq}z&hqm_#JpAd>&rm_cSaP=)m06FDdm=2bO}IiZ}Tk?vV=~2 ztMo|ot^JN2+49V@Xn8ZYk?cG)7hoE^YWkw*{14-$haf$omZftuOapjM2H~#s4H1gm z?~>fLJbl1MJu@n{0%1{a-4j-I9xyg*zf&I?oTSH-^syv1IeN{SzZ*IB+b7gsq6ipB ziE6nho_|?O?{P}$%OgaxQnKrJFfF{uambLe!7DE>D*OIjWM`#e z3N!e2(=?st%@4Bug`vae={-*U4*f<*nlh+-UEx|UPQp$K%1v~1MCrEv`|~GR5$VdX z{5vP5XY&!*0<-CN?t?%>zqRyw(LMA>kN|ctZ@wh?_S_ZNkH~x?=i>=H;?d*AnR~rx z*s|qe5!hj`ls-SV)T#qE69n)PwNXZuy)U-$68Z;Ocht67GiM5czM|wDZ4}+l%%Q@9 zO3jKFj|W;?hyR*OFGsh-y6bWTQ0I~p3D__*dB*jaZl2O#v+mhX7;VIJ_Ydk>JM_(+ zX5+<>XDWDKpZknk+q~E87zBs1wVx04`{(Kk%Bq{jEyxIr|GemDWobd|jNL6ZFPTTO zB&36PsTH4I*&1{-FtA}N?ZbHcO*QjMo1uU1j${_`RMGcjW$oGzMXZ~~Et~T`>za47 zWy1K+y)3cc6c?*r?o>zaGNv+iN(JZcn`k3N%q6G6+0(I+a698~u8 zoBmuho`enr!r5wl_L=d&1s7e`5&@1qA)U*djT~b3I>imjC)d;X_VNDXL(U~K5rld` zg1XQ7>DZOQnAZ`l4sA1!uf2oFP+!?=Ww}vV-fkufgxHSjsC#390ZACvV@D6~$Huj*da2Dp zjEd4o^Yz&>K}XmC{1%lhsp{4ra_+8t<@dLHN}rkRx9WiZLo~Nx{Rvt(lKfxEODbkB zsM<3xPU|W1fyUZ8%Fo-DE?ZWTIq%-*h;w=fcfI>!vJ9g$j+)Z)N;8UAqWX{=;Jt(` z^N!C=EEs3?8%LW&FCgC+%BV3qDCt!#pfZ&s#WiVLstug2$L-ejOP};Sv`6}$;P)K| zG`bb{GqPSAQQq6C+tX#RjebM}kN{z}ymQM9ryVHy_ZL?qYBegRtJnEPrAW*mCUUF2 z@2DkwpD!6;&hCJ<#lL!0MR8v!}Hq+e!$Svlia1m6dG-`a)qGb(9jO0$(_A?UuG8e-o`F1W*3H8 zl^0UXYtpji`=a?S=jRTrC@oxY({k*%an27kZHoufyeC$7g%M~YVk>|XHlK4c>i47Qij+(q>ALmj zUwfq1mD4YZ1z;8C6)v*9E?9;ttE z{>Sa9RpqlfT^V+N+GCCH6%_^hqICD`JGeO@IQe07AdMB}kFTCTb^>*X8Z~QfcXOOP zIVW6u{XciHIB{Tz7Dq2%U)J!Iy1Kd$krIEOm6_x(n)=JV)7g||ZrS#bF%}-2^AN1K z=fW>jYpeftK6|9*?zf*V6h1lOab;)nUqqf%V-ABa5;j8iZBblV{PnA|m)Aidflj%q z6gPB8Z&%`h1Nl^q!IyemT)Td~&Xoa+vqwJvgxgGM(z z#`N-`Y*X0oUR2a^tH&LVzJ)Fp_}(}WoPcyw5K%(V$IqYlne43oBlCQNrcJ*so7c|5 z;_1u+cW{moJ1soCWtO_kLP-3yfW8wfXkf|vF}xdS^GcUvHwpD9@S_#A8lSYYJY0B~ zY^sFByZ+w>T%~$|XmkOEXVPEjoI553Bx);_BZGpH2zYzoCJ7h+ocXmc4P4R(S^i4z z=a2zcYh}dHjhcA$9vu=?Q?X|k79RanP|&Kl603%E!ZvB7H>Qs!P;snZYx}SFqetSyU%$+mjywC(V2jEm7@Wl% z-R|S|v~o^xcmU~B{D0!(j{uJji}k+1CA7#pdfbp`&YKvh9D+|)s);m#NPiuSBhq{S zp|59!CdJ~D-h%KllCL7|*DbsWlF-Gh(9)sT3TIJ(|%G3i%}b#YidN94El z0|FD>aYA+f9f=>Tt^+Gz?J3uf<iwL<8CD}9Tr16k>*XQBerQXr~E~HtH23vZa!Y$Dbysc-WUst&)~RWf^WjI zxxTX%keGmHQUfP9h_y7A^F{R2B6t{V&*M>gp-+o<#8MMnj5wUkW*OY$Tk54OKHwop zlUS%nbuV#Au1S8EN9xzZccMo*>s_mTg#|Q1A>q0osi=|EN4~^d9wS6YI`jDWo7vg! z_*An%m-6r5JK|v|j@Q$&H%j>Vmjql?8k`GGy!cp-vnk=kz9$yd{p@GEktkY-$;-6r zi%k9|qv74NBAWvjF>%5x>Ej6;*?_ory|Au<_d9Ewq#6|KtEs6Gx%bTS`|)~{W3kLh zB%=TP^pr6?<0HpY4-+VDpGdS8o!emx{-{S~P4w~Ij;DOv4p!Ok4-@jdVoq+y&Yf=u z#DL8A>|xH>p7pSRPtUD%Jf!OPc8YGu!Th~j1bk|7w8K!)kGoH!qv zRKnXNp3)=vdI8pS7y0z)(c_(z=3y5M-_vT)g=}UAXN}Z3-*fYi+n0W<0)l;g()AIQ z#f@f77b+(}GK8S#_qB z73C5U{*$A=X)cuYduLJLd6|_Cn`rc=y`o8+z7J2?82k2Km{P9PhdMN63D;YH7N7?6k>mr&r zY7|Fg75n@fa=h-;@7%`dQTvyjqxIv@>EAM+@}=SPV_PcCckkbk-*ETl&9D739?4r; zK7C8OM>*j_%BS)as_+zVTDiT<&d$y~-;CHc{^ut^b6Ymko55THjcX9OWJ>nfDVs?Yul>IiYLzXx3~we0nQH zP+Lpne({tgd6W++^WfW0rksrFV=kR%#C++U3;yBspWC%M$x2;Aqs^z4bku8Kxs*XP zip1GH&s43skC9aS{m8iEE!|!|I7OU9dLEOT4Shifn-@=+5dM36e{!A?l2|aycEEt1 z-C;{HP_d?|3DgQpft}3`VQ>`{Igzn9c4-uTM}}TXV7ojfSh`&J--u#{C2{pLqnbwO>O@CvbiA{QUQZK!997PD0%}l?< zWBOm`=ofhO^}@pR^B!+*o^F>{@b>MDpfeM8+@0>-xBoRvmA2#8Migl7E4ocT=1gO4 zaddw49ohm+OR`LTr`9~yX49@+ADd)1{<)a~fK1eS)j-oW(~U;*+-Zxag>Glg)|Kpr zgY4{z7a4yE4_93AjVEP9WHi4~iN~8oV+OBXU=~*ieX`unm7;9RPmwL!w8<*Ggrb?* zkD5Yd(e3}`WIMI2JK@dOwk{l0*b0b-+DvKeJWtb4x6gQbUH=h7&yMzuv#?Zxjm;Xp zr`htmT?@$2SL$|ws2zIm(X=-SV_jT6{Ox+eCo5w~(#aMnwVu!JwWqhaSk{RXy}h0l z6%~a>^)q`Ld9LpJSBDn|z78@E&IaZAlB{;zCz0X@^hb?QcO#u|?(`^Rl)g@)EOEK$ zMt;A&iY4po58K$dgtvy3X;LU7E;#E#wPwJGTVo)uZJtY%r-=5e%9-Rn1`=c5sR z@rjMB^@~r|nF&$Iam%Jy=uvSQ4(GH_H@Y9(GOnWF#%G`6%p}4?$G?~J$HH#D2}?e7 z_Ki1;ec$p$cK2Rizun6C)M`+{GV=%xXSXw+<8*gFcFdhw~%xgyzcUZ}|uspNC2IS&j3LL{Oxc-cRaJT2sDxNyN zuy>Cs2jc=S2i_{VzB{)2w}FFhubRKwbJ~YlYArQw_e=@cTXVkyx@7MRV3w-eW`A{2;=0z2Q7;7x=ot2B^ zp-taEqh53ywCt2;R z4s9dK_G@6EGesZNw}sn$F466$(N)5yu*!_E{>FJvj=58QXt2fJ&SvzgOFcjZhZ9H? zeOViFdV0d`88l4)xwg%)mqWX#bN{~X zNmNcLk8U^LK1bX>UHm%2xilE)aW8P`_LeoiZWyfl`Td4uLfW1n30H16YtqDjeeVaP z0NPf0v%S6N9`tZ_b)ECR)?3k)CXMJ+x2PLAQjdQ71kpIlJ50c$pq9I_p@M3e z>`K1ru#g<@JsP`3?++c&UHH1efMx1gBVAl(dz}YJ!Xm{y{{#wYVytPat$Esf4+}1n z3W{!>YSDN8?<5Z%-fc8(-=0TbvWIvS30Ev0FV0{(WqkbAqQbg*mM-=C7wa_9Dq9cV zIE&`W$Zb|+U@wM`5p^8o_O9HXbabrLj!j;q(l6!g+l`?|V~@GyZ@K;odi?Ok>Gx@N zr}cKg?QbO|vEJ^Wvm)v3GFlnY+<4HQs!S1CM2I=#$Sp%-;~|p!9!iX)+UxiIopP;lyAAyX$c#4sgBv#q7fT`I4>UC z5k?kt$kEMko^RAH|I9l`;{%AgxbUq?aufJVJuOd{o$Xo2 zcsL?TFAO7>hy5ST))znv)%=Uoiv#G}-R2%Tf#h@9#6mbNJ$g*LRw^<`GLm9uP;y5d zbh()$5g#%DvIw_o(QLhDmb-F!!9<336`PJLEiQrXUoOcIA*}ObHqx z{9@@f0zD*Ke_lMvkfJ-qMu)B!ijeo(=itZqf$1i@lRex=(cJ+g8^shRKD+a2LgBzUa5+g_t!frA&i5y*O zK3H6053R-S#LEDEjUoOL8xCNIQ?IO}|BS_@%2ExuJ^tv}E0@dxV(PZ(1F)Au3G`R- zj+kdOWpU?>OWXz-L`%0+AQ|`2?+2(C%n6=E2rDqEpz?SbaFaWC=Ur*#I~zKT?t_^0 z1-{AU^X|3;RL;$Ajy1Th`uz1`0GlInMB!VBbkm2!hBV z_uCnN{~a5;Nn3qi#tVq~f_xC7CmuC3Fu0sIPv^YoS!=&5?A`A7pg8==Vwl4T8K=ow z(3g8U^KImwJ$tz0Ls5#|`lNNj3brm*G%|AV`#$x)7>Dh?cXu5^t_T$5YxJC~lb%u2 z|Js@VxJU}5RKZ}aXZ--TUnxCMeJ>u9Q6f^xdGyCU1VzZTT3Ur(bZoN;MqNV9P3Qk^ z<{lyqs8S19XwyzVEw_M?2&z)8ud@G08c|*>n4s2r&PAx6pm&HsP@pj$sTffz+2@@O zHHF+r-70H-1>CFOMLTC?EbTor6YH;JA@aJ_?{BRi5l`p)xzwi`l|uPT3|zP&UV3m) zQfd5~B9RWKFG-PK;1$Xmp36!FgM{9`bJ^{1EI8h=a@(*cyI@)eukWR!>=tfW@d2nd zaOKkQ>pa0Hl13Dlgo1zf=%KK<2G8p(gz0l-Mt2(!xdxNEXMQ`HfY<62`6er6loI5OJHn9YqwG0$vk5ho$RyBex^2h9F>BcWK zZG%>}YUVu7vZK0-e`a!dt+#6;*C+ORt zH}fX+!X1?^CJIPNdEaPSQ>nOzRrS-#EzJzF=r&#>1y!4w6tF_JIqF9wz5{3kN-RdS z#i_YpUm=5rRlN;692e)A7Ir~aouzH}RlUq!%8```lu3tQ`dL|+HQ(?}LV{5W+LE{` zO|7`hx4Cw}q*ayKKV2E5QFqHf2V!Dg-X=yB4IBbyJWkPh`-!=slu|LcJ>Qx4fScuL zRXLi3dE}r$krHajPNFEe=w4OPeKjpN}vijcD~8^RSPE5gs6u4YI=Nvo%4 z`C;QB-+s$E0|>LpC`YRL($WE_O*g!c^El#q!5w{kvLRGuO|RHFMhm9^=l?N9%l^}A zuZ4||XL^uosFS|QClnxvnu-&6-7n$+*b5whmFi17(kvwNABC{s=Jv^H4Gq+m;6I(A zpiwinvM>+Ho!KL&GfY1rG_XLNfVm@6r_G;1x2$M+3gMTaRJa*PSxFrPPo=fE0(V$~ zZg>G;+E|bo>1lxoaqgLAy9#HT>iHxJ!HYhGgq`V{5|s@u@Uii-`c@49=1HsQJmc~Y zKy9g^rR8jD#GxMta zqi_F2erVT2{gbFIa#_5Wg>~NK%ygE_1HQefTZ-O7tBK#>g6j5v=;`Qq?{2}PH9xiI zmtG)J>SSc}XKo(FiGbHPHrQl+%gM>v@o`zJjPzD19qH8Ov6vow(X4Uf;$|=2j_^H< zx=E;Czh36%6<0NCnSH!Xj7%}x%K1w_xlxUNz$vD zTQGXjqP{gyF1YGTs5F12Dz^`*59O3w`u`W7?th~7{m=Bb)JDol#&iZiZ13HrseRyP z4f*%7oqbltPrOxqOC!4Ysu*2q=AU5;^AketT>g|c`0obQ{}QEPP<`KNrH>~Xw%PXB zeuBI({NB6G0ht?j?08``vumE}(=0uGeSCa&n>8^Uk z@fjC(t6i!Sf!WR;dTSs2V_sB{=W;LHJX>ez!(O*kw6=>c?|vw)w7#)G#bV5#H*{+~<$@qnlA_QYeCU9nCPy zUZ<5_5Zd|Bwo~fzyWxX~>!Q+}EDDkZf4tCFrdZl#VJ>y4Z*zsosU&*k2Ht6TScBtoE~q`fJ? z;o^Dr92*$-qwEI z&{NI{s!#m(VWV!!?!2j;blmDMpA@*mX{P*I;ghF#d`8lqY5tQB{4~s8e5FY$ zyg18z*`zkE_o?0L)^;|W)5v+0{3UJjp(hLCRy1uf;pvp(amRn=xK8;JEPrUOtyP@W zZ`r^><0g0eT9EPf%=lx4mJ??u!fEGSdC!l}IFV;%elO=CD)NA+bMvR7-s^X85SJsXHDR zbT&6HJ<~btPTrEDt$r4^58oH4`NziVyoU&_2wzvQ`OLUcTjSfv2CVnEetj?fi|t!S z+HddN(Pq?-lAnf|U+yW_)|Ic+JvMOEuK4GZsusSwq<8P`-8rpR*RA-e7CW_X(9GH8m_9+^E_${ zQ~hRkoyj>d@$;FnV&sUyb!)d2erR3$A$Bak20LCOLMdnV`-q=?A?+#z1qyopA!|W^ zOUaVbpZ9iIZg<-D_k|vvwobk6?Q^51cCYr~YS$+}{jH-_LkkZLP1Cl|UT@nu+aPRe z>9e=}Dqi%zxphXV{Rs6Xh9}lXwN%zTf3w%8Q+b^x{4wozr>*VR^!Qk+6N`HaKHWwXTISnvEgG}!fFp<(5?!Gj08-)Wql zkdUzQYmK6&_H_(nEwXuuqG-j^jlG5hk9b%JGw$2qX$AmK6AkmPZ#Q@$^){lZBP zU-2~`ot%_A(Bv_!ToXU3w`yycwh!%`-`Zx6#$vdN!`@Z)7IGFb~bNOPDq_ey0vY!U|!=|dXU4#6e zLz3Ux4$Hmf(4tbe`qSDz-}cvnb9Lt0w2OHAHqNqhg6bhy$Jen>PKk?qb#9xh@?N3Q zbCa6`kICojG#S*sOZmmD!B(erc8C3yV{~$dvHad{N4t#^Eem=tPq=5iY-~#D{e`#m zRlnae#s1#T!uid{DNA13UTr^BMHhFPwZhVKQ>^38?#~}T-rO!fJYMsQJkRihy^IcB zztQ!Z|zVt>~I0R{U48he%Ulg z`7^S+>hrr@o10p&_(s$qS@fp%!BM}h3|fCd8xIF>8`?Xz0KAP?2!NbF}|byAo#$;MqM)0ij_B6 zyA%z*Woqx8@ay&dL%e(0-)dh+{ubT$ypetH*Yd9l{|-^K$H~9AC}XR6-=CupW#>mH z5&3HV8E$b+sk)G>hgxrnx0@?}3s2hQ)mC+<(T=oy@=YRK~ zMyjF$={A%f8aDY6IRbwE@BJxa)pBku+5x${U%@>hQnWi(3(ipb;D3fQnW*UeQxw`5 zUrzssd{y*R#5TOWyktBc^axnUAP-qDcy*`;e+@^MRVGb&u&tKBSt*=IYw!o9E}?6wz2f zNc>P19o!7cKssL5!t`&@5HzUF55YBv^svkPTw|Gy^vMV)h!7C!RcZDbs*g-U^wRTnko9;^!r%Z&Nbgjp^OY)I@(qrOruLLur3oxUWjk|13#NxocX1FH(!Mx|UH z4-@7`D)jF-*hvgC0hX47k>#ka@BX|p^&t&_#aA0S9;B7bnwQA=&FPL*_B+U5M$xP2 zz7-r;AKSSZg(4( z1h!%S;`;++*{Al}QA<;G*LJDsEHp}QyfExc5yMgcplG1{^_OFS(=^UCyxO=k8M@GF zl9T(St9pwS8&*8HoG&AQA(pJ`7_WNt`d?5jKtx67Y7ZC|vAPTyl|JQ~)yGGh?Z4@E zUfbvvBT+Q$usg_>4Hu!NTGRC7=mP3YU;pCc6OH=)_M!zvi?JL!rQVUhZ+VTe@EPx5 zl!b!2OjR&ptcbqq3n#w;;<-V$tX+)MHH2fy$y8Q9&O5*9M(KnCHc>V?3W8DV*ROYi zjM<|8wPUz&fMu9+tV8BsD%%o1b1TIIWW$z5>yL8{+#+xb4DVmp5@YGmY>jk-ihjew zg}pth-;?h|ky6xZ%}>XNg;fh2^LDOo}~HL)w}!|b>L<^tpbhgHv3z&mTK|Yxp_l% zhgYwo$#975J4bY|u{*?p8yohyS(pLLhvur)%K69CwMRKCCc`Kvd+Mt;tDk>R)#TYj z?Cl@O6mG1(i?GUVQNS}mNe$wN!>$Z^pS7C})k(>2?Q2D)`usnxz)iXc5UX6o-@3pJZQjgB!d; z3R&i*$uwD!DB`QI)O?^XC^t>i37|je)f;U$!ah94rO{?U;pN}XT{=odjFl7D_4)AL zz1AE|%?44x*)q&SWE~w^)Re2y*Jb`N)4U!+4c^a#{`d2WjMazGIJr;I8dp~qOfK!} zGH@6AEp#*uMJQZ`5C)>_`q`^?wIOgFKD@4ZRhiBeQ?bPPt+LA^S^Fi`M&O7DV>#2G zM9G|vs9zU%63uYP6f5Cd=8WzQ%=jo?ot*ifB z!=c%=YvV!s|8ub9ejD3f-64%HXV0RH!qb!AJ?I1q#RJq_vTAEg%t7D91(TBBY@fx+ zz=MW+U45r-QjlO-+)6qd%-i&|FwC3|(+zNFJf=0A#7S@l!hzXTCRWCv{~51l$~ z+D!h28~pXe+hzekP3!*oWb`38HYI0|FCLCsWvh&)s_WQ*u0V{*?X6uNEvs*Nkfx1a z>-~?V_HZMBSsl%U;gE24Gj~r6P4&fZh^H?H8?0}7R7NZ@)hnMicf;yyX*&?dXfSzD z%-!jWKd*9syzSDDX;?sYHPzG2L^Ue*2|%b6G&%Ya=m{wm)=6jpbfgnh-}Dvfu^hC! zv1U=#tFF`5SaBSErhxYCbufG4J$2+_eUK&iKq**|9 z{sENsU)yBWwE!o(z7%V_GSyq8Sy3#k-rRl$cc!0a)XQ+4=vw1k{FkdXWJ1EP=eH*j zi6C~AzK$6yBL|oAc=dzNIbGDx{AydI&}4EvMdKNZe^YIgJ#>7n)zR5u9%!^lMhHl` zbM;aUai>L2Jjh$<6e+Ks0bG3l`MTaXA0HDB)iEowOjy;{Z7K?#j4~!0Y*hVgeNOr3 zYY<^OyMJGqT6V4Lt=YXADdn5=L-C-nnj2~U^VgPfZii&7JLSykjS}sMEn2-%--pcz z$iJrRK-J0nEDvr0CPmeeG5cBf>YKS*|B5MdmhUfGmym=@Etb8{@vS~cCy%2U4eG3^ zwljk!ZrP8b*{!CEBeSJxwwmRp zu8ouWK}{9c#{u+E?J463>x=$hiCU3P(Wsxr0t19jcvV6kiewX;!8zkgqmH)c|Ja$>PM?7bcW%(r7>%% z((F?9ap|GD#JuRP3r80{LcK*o!Z5^4MLiy3HyY2jdpr=nkU2k4-xGhdRy{aBd(lP# za$Bm5L!7aa`cew?Ps@*&j!=)4`VRW<1fk3YvQRS<5T?ZI>?Y- zI+kj+a|p5AQ}tQzrxTS3vu}L|>|2lMfQ;{j3@RcyvnJQXrqY($xw*FJ9BZl`jFJj$ zcNp&x`swc=*`J36+GcBZWvIbINW{~+$Bsry^YpVj_OWV6B2q{qlX;%9$h@GoYM+|< z(#Y_^q~#z{1Vag~QDP)NHZY6CdQlb!RmZ{E2xng)B=Su&BS`r>0x6Q#+> z5WD6d7!q@d1Ksw047&QVH>g}mM=JF8od;X2CnBY&>@|6^HF5^k*Bujz$cyAuwc2Wn z7Hxg{yBhQzUIceSYMGR&#<;lL*;docf78rfB7-Y!HRpWyEWND1Pqohz9C^}k6_jnY z0d|U^lMnjgk9M{lgwTB-<-VFuA)rN=4X z?9_w3$Fc<|dplWGeO@;spu^*!u|&ee2kdH{nmQg5@?RD2Lcw@bgFU9o<+e-|4Q;>Y zUb8XR`y=PX9;>0QM%e8C(ZLLw2Jsj9DY_2P*5S&_?v|h*xFl5Q4WdmgkSRe%Htx&Q zWsGz|YD_r)F!hxk<|X^~8*U^@5k!y2Ti4U#S{bm$o0EtUc#76K9w%tXpzC!|$t(*I zIO7R%hB2F8Kcvsx$`Qt7eayb(PH#s$9eoDXYbxyeV+|dQR_{;IPVLIJIh*13D7)%o zcJ~ARHHjMX#Xfs_w)0SUFp*iI|6cl7x6eApl@?W0$}GdiO3f*6dNN|in_e^GVb3#u z+fl}s#2N35EP}Ifw!Sy>GvD`h59 zwn}6t3Mrx_Ss_YBl$p_>q7;>p5Xw$cq-2jo*)!w)obLO6|L^-A?{PfG^E~(SxUTCr z&hvYI$7eJkL#uxC6um?6<@XXq8>Yvi+GCQhF$yM#Af)9%;@%tIFa9REXJYflysW=5 zgMgi_CdN?%5^|m#q?2F;!m&Z?9@0W0UjfDr(L<$?45Fy_An0V6%0vH^%Fjd~Kp;oI zo9!P!;SZ4)m@cP*AfY`giKHC#fbhot6OD%deA3>*fxvXI_^@C-=laddYVwH9(&=w6 zG$7gtC0pdxCJgmO))J>M{XyE*07(CFyUSZ>;e)&Q&`8Sy(MW|Ffg4+T``h+V&K!4ANH9m&^lL^4^hFFqdQf3gfqQ^V-=W7(pPspC-OL(}mgI^nYgzIq)S&B(tC6x7<%eb^x1a?hn=x}6Ra z72Kjqj0#j-Fu#R59tZ(E5`S0pV^@eAJT0=s)(^K&PU2l=-~?v{)Nw z#`|v}K%$OP%S{clWW(CSF#A)2{G}W<1ZnR{BmHZ)BnRye9GkgpWKbo!>zR47M#3%s zpKtnJld~hM35y>`#TecJt@H%BF3^<_s)=bFLO8Aqxf+UtkJwu-U^~#$ksP5#Dz0mr z-QmjOGh1_~<1$Yist`YRLTmf2G`k0y6Pu@JCPi4IdA6!Tf?%!b#qL`S%!0tp>D$^0 zDQg0WMF%lccqYP|DY~v$1l;u`LZ5!L~KnnT!|-1{?f!lKs<2zpyu?G zI4qNElSP_72rLMIBPSX0Y)hr>^VBPDwCdXRvp9FvMpg98H!s|9u(5zt^H%&=K!r!0Vwv^13Zu_kZ0pu8RST(7{B$rUa6iHqpmzdTA9%#z zZ)?-)H?uLpu*3jgNW{gVI=JElWmacnfU}X_#~VmBRUW1Eb;U(T3q5Qns!X$t9~r(7Np^`z zukgQFakp)1qd&cad@$RTcvbpg{rbxXjAnBRrcsESrkv0+Bqi12Ft`cwX1Ce{lMSkx? z^FlrLEx4jt=`EvysdttD^@rb zCz2$h4j~v3q?@9IW-<}|B67{v)_zL3q?a4Ix#iM_mxxu|Jj8R*IoX;`;61qW7HIuRVcsZU4H3Yp2RKLUdIR9r@e0Jo_|ukVq?3=eL<|~msrt! zBEqdPa|8RYJ&Oh`66vQ7%`y`hJ_L7~DjNn6fL)z}O$ia?K-Vu>lMafS|7JuWiwMzl zsmK3>rh1ulUNtvtYu0Ew$8H^c+ROQheYk*#PDry&?v^v*mnKe=U23g!=%lmiTa5w{ zm8q{;y&}2YbPq(`58;A0u2)y(jKT&8|DKKwz&f_NO2*|Vt}4c5{EJ~4(OE3+BIGn^ z98md!)zs98*vzzt0(Rg|W7%~w&_2SsgDpn{W7LY2d4u;Az@t=gEHhn1Aair~<&hgt z-|^ZX2;y9Ny*puUUv6bal)%eF0q>HNF6i?crHNjMKGubiKJWcI+i6bOcRbY6R)v$Xy5-FKu7X=Ao`glP8tgD_u44A<}n#l98`|r}{l{r<;!Mz`!}cH%Xk!&mUplgR{H zxFALpkbZEN1O!EJEs&ShN75xo7Lne`k@)wk^Y4cZHec$`(!72B^(~p|%$%$fwWq?; zI#wP?pT3I~E3sRjb?k=7&l9^HJt|)wcdamWy{;cM`=B|iQ23y;a;f&pH<35(wYDl2 z@;^FQFt6=TkMV$J41^~nq(p;>JHg^v&kRSN_e9SJtT=5*u+|k<&8hBWg5DKT-+*0| z9#4^)UEr{N0d%7suV!!4Sc4VJCZLq z?Tn#HldDAf@bh^Q*{@&v?yNij=6$Rur`3i~}5xnEJh zHF7>9;`9-Okv@Z&daV%FCY!@s5ti5X|GCNUmAow|_ofPC$mGFf9z#o}9ZeBkv6m|c zpUnM-1$h1GwujEs$G3WGT{(L#&s7<{7<F}};#c>26A_0l} z21)?9M;NS-NF$zZ^tnv`=8K^J6?!R#reI?oS^DM*d%wG${{D&TT{m~Es-4)u6l0oY zT^pN*aMJzsjlo2Eu7rTKFl)5#$KApS{p;_fpV}lK)13CXVX!>BP)RT@PIrE6jh0H@ z+RBWG?O8|WeXjIoxVF(391@RlfszIk4A-hf=R?*+GwQlNYzN|G&NLJic_ZI(<2Fsf z`E_y6CgK_&5s@CDJ`mV1<(KGwF3~Lcvw)X~{eg<=+n<6gwc@`%4(c3yqC7V0kxeZ$ zkizXB`t$4iiK^JWn>K7={rvT9l(%d+If7pGW+_gh=I>5&)i@psOcFQ%CuFYNXZkZB{Zzu_`OPmg z`9&1IqvHcI-vO)`3?yY*JtBClieUOh(rnDK;N($mlf_&q;EWL$Rt&b53pnKTbpGNt z{=VD;tai0eqbd?4N8gq7+}{31O*V~t9AcCAU@ zUV0UZAwO4|Pthy;)m;}WcnD-aO*J?sKK?USG4XJ~+Caop$yG(m3)0sg;ZD~z`aEI} z_S9C^kE(-eS_vM86Y&?BpIZi6Mq4}CRwdN)7{1#Oc{I!TRkd*pmk8tZ`*mX@`46ky zkLTEkJpY5^e6C<^u58TK#f zEg+H9Gc()dV?rhs(5tlvPlcU}OMrymnUwKnjT`6R@I=TPy$UXOZ%ea$Re94ySbd&8 z_wkuqX(Q{6>g6SxOc=G9wssxg>%G#lHX*I6XL)4akY3Zdo{DF()Dz3xUbo(y{CSMQ zXH9NjN*pwalxddEFl+%$A%UkOX{r#zJtB9Ch0VEIVN%q;s#_nt1yYD0FDDBo1uuEx zMb!oO?15dYB#ca%FGdU6`=*~d;k^D;rRlk=YY$|EOXcnlXi7l>C_Ow?FLBzb{IKU6 z{bPmqO7j#Wq#n4rZ`$pv5Kg%9a{nRMaw&t+P^tf|l%XEwO;}w03O9gAs3^1p0d}hn+eJOlmK07kA zjkhWDmvyv}CbxFM+r4tx{ZZt_pqc|<7KN{bg2Gcs*Bs%M-g^BYD#jz2-=jf^w%>}b zwdntX?rsN*iS&|vrCGGM-J|CVpA;DEzLhz|yz6?#wSsHbuc{KhZ@cv8QtSKWLLclp zN*g9Oy>_y?K5HAg&ui5SLGoHmzGPS2tiE~-NU4Gt+EDvsn&q#pNKSpz4Ofna)BnnH0|&(FO^R9mN2iJ-M?h`cWgUv zWN@up_~_=zfy2%h9mAyl&E@v<7RuO}T^GpRuQ6J1_XT3Fx?Y-Qh_z?~b?3;Rh1*_! zFV|0WjD$r|$ zELS5i7{dNZwD&byPf4zAW?(UPf1qiVMD;5+ch~b=ycN zi~lfhYmRSA@+rk-_I5Eh*$bb37HADeo}f9QDq0}C#5~x;anvk~w`IU9WrPHkw=_}l?O6B)?F*7K1fskT&UV5;g z@4n2UmeoBMq*E7W+ushyLhRkZYo@61wA+DhyP6F z)c%%qLl=y=kx}V4oPaklLghb=>01@ne37-`P)vj%2BbIq^{I@Odt&#zIfl&{iC?y9 zOrKg+EN-nGEpVy9L?F^!?80yMrmWtI_^@PM3;pDZb4XlMBHx8>J=J1(LThW3rNlY9 zcY)_Fd2UA?iU0+2gB|oq7?{;iFw~)Qxq^Pfc2-8XdL2YPq3h(dgJZ9$g~&FzDnRl` z#qwL&8Z`d&&RQKkZdw>cuh5j)TP`jv7f`Y7pw-iXTrFe{>7~281Z{_J4V%Uu|2h<~ zu*22<05b~#R)F}xqRK|Z>PYHMHOUMQXC@UmjS6mRa9wdNBsi17MI)V2ahi1g!4eVH z&*dQt_v&jG6i4p#@r8!Us7eIt&9^%)Rm<%wy^5aSS`{{6r(9i!jr<0*rBd@1|;5>03dn z$w`7CXBtX}S7TwG$P@}+VfDW2ktzF+Ns~jIX%*I=NErlh<0!sSgdPL*WE<+Kik>b|KqTN4W2|}8*Her0ds0Qg?@Zg;h>9LT7S)$o$2=bw zeeHWF+kjIZGn>mpiS_mMFQK1}T$B`?7(aCSY5T0(dIVh0P|Ul4aU-gRE9iGVhRzJI zv|t4xRo!FtONR*d4^EC2z^Y|o``JH!YOl>AE5iAXxeNI4Y*{L#E|ovby?I~R61R-k zf8=mTdkz%Vf>H$W47BQqetAQQ$+C!w`zV%3TCT>1nd~|CO`8O%)j9v~n84533;-XJ zhG5~7yBloP`rGyUqIyC7CF|N4p@=X01OvCU9OsbqoEm>9vIXYBWvSYj&1sT;5PlMK z`@Gk$jRu`o;K(Lw=g4tTGRyxR$YSt$1`V@1(2XK*-5L)vFMY?4tHNPINUO=Zf#_wG zdX0vT*`@dIi!qHsWy?&x`~GK(ZC8J2$Q>pq^SU4adHzwfeSVafe-hP0D=QWBqB^hq z<=Y0OtP>|@xmJ?sXpb$0pMw<+(ZcoeD#YYv=kl=@_hJlkFy;_NDm84GTy#HQz4hjq zHgC?{RTA5@Rg_CPTBa1&#RrEx5<}7f@?=4qR|{Ihu-d^G2RuPY&2S6N(x;;dOJ?uP zYGCfA;D%SwGv9;yK05v%QD0yN%{6%u>fj__!r*7y26&H7$)aQUe)X)`?NSruDk~V6 zw~9Nf*tX7PKit)Vg<$gOg#fw&Achj#2c)CK$7WV19QNzS9CQ77iU*o(6TkfYDXh$M zS5sTt4!20?VOYQ&?k_%COAwQEOr3h`#9<~D;Xlj5t~e4fTk<2bSF-%s*A+{dZD-3l zkV~t-d(Iw^3<`8-rnJm{(94Md0`?N@tei^bR)8}My52#Wr6eqgiQW+(RW%(Gmy;Np z5l%2D4b44a(b2+qcZ3tG2SkWY@Bhw&HXn4R^WnK0|9#r4i(8I;T^XdPlG2{$*&Xma z0*e7qONkILDCU?1pWP9Eq4S1J=0(+L9Pg%x<~&r@7Znv6q-%!hDw$k;?;O28h+>-P z-EjFR^OoAKoGz2{{3*3m?Qd84sW3|$Wof?lVkWzXb3%+u?{*F|VQK+F_eA8}9`tXa z3yiirX3a3Vz$Pji7qHA~ashJ|c#Y9{>OI&?5s4cis;WQObz~vpICYvH(8p&%szWb2 zCB#=Hu(p@u=cli44Xw4dM+oeQQlcG+n7hONgG2uNH&E700K70*Sl;Mx1W+T)wzgpk zn~;!@^CKK1iY8RR3THyZFX0&9_)^W~N9&XaQ7OWr!B7c)aUH+LU;l7K^LO!=Rjm&I9v*XAtO*~x4o7@+|S1OUh#e263)M9~6!zC=t!@}l;{z(ono z^zU!0snhSJ^4q=kC;vP;`0?vk*$4g0#ZGd)&Z6rk-E)mc=rjo$v#(0<>fbe(<-aRWZ`7rtXBv(*puwg1(vGTUw z_ALAL;TGStIPqI=qwe*%!J=!^tL415Ha0}84Vg6#*pQ|^B>?#JPn;0IYhzq?g^bA8 zO~!HXo@bz^!@++LKn-NzhLA?rEHsO#*o^ZBx9&WG)hWnSiCaTf@^K|!bA|8UHPM8dia26=oQaNrxa* z$6ZPI`NqoTYO%cGK%b63g5O_LTp(Y)UBmf>`VPE#EHwt?;o!X!QsY%AN;7%mMsAKJEWq} zmKNPuqC7Pi=Qpo?$9+CcE_*aeFN=ROUp{S9E9+tI#{^XA6%X%JB5yIa0a#bP$${-z zO?x_b=X7*J&#&A@B5*g!Mj~_+Hb%T7lvhN8cxzqi4k;D7#DLxNig)JcmW(9ItMTN- zr)jX1?Y`S{GAk?Vp4}Y{$T@8CnsvH7U1fg6-Q6XfPE<^+x9JLVQdU+3jTSZQSvcQq zKEDqUJ@iT3#Rv_V=CezL*jQCGpHvvY+C4Ypq|0E|O%(>;>pdK@Nl6!k@iwr(e@RF) z?Zw$OgBfH7F*_2C+Ilxs=2L_1`!v!RqwhE(&h{CGGUo`FeaCnnGLc&`F%>J`3s|n= zRp`t}F(;>cQ?@DDqfO1$zAL3Y+qxgJ^X3D)argY`xC(3HU->krgHc2O!i5W}PuCoK z4rycp!r+tB*wiEf4gw03Xg7I)9331qv1{T@OlB{`(sfi5eb0i{ANT6! z#AwSzqbH|&9?F@8ma&Y-?7pMD2*ZB6#xn^n6>6VD+%fU>xWq+AieTM9BW~}_Z^!H*IsfeICTo5Z#ag;V}0Q8`#L{Pk3@68L>1 z_}M-B)!C;?E}$k|OI4VErz}>#kN@{Lfi};4Yb;0sFTG}J@PaI--thj=qcYg_=%TVP z3^4l|LNC zKGnHqUA*i;9?}hOEqaT41nLZm8}DkScf{2Y{UuMxNBj!laD*Fr+(c`Iiyk8{Z56>S z5L~O?f?TvTf<>{_>_>aK@z;t`*|zeQrMZ(S*VSr81BNB!rt~20Nan8Odq}hutRK6~ znGb0L2b;BYvdfEl?a!QPM0I;_MhXDoDy!#bC7j;6t>#V9ESGsYyffX%XzvIv*A)a06D8W@R-_mA30vxh{ zy|g0#=CUadb~ZK~r+Ysakc|Avv25@rcvYwTJnpgYp1S7SqD)$+;yYYdo24Xk3=dX}CnvgYZe=r9wLeO1iU(GPwDh&~0 z+e)vn}=u*J7dNw0FEN5n% z>E7lb5Xjb39w%m7r$4P8vQ>O-Q~eJ`x5mZ*rl`oSiDfkU@7mLYY@0SU z;0z`u8dj&sjve7`V)ZaBO+xP*%kwS3$N%&MXqsHVCb)_{&*e=$4p#Wyef9WE<|Zeo3S~Fq??-L#m#_Z>Ux}SwBGQx$K0iLBcZiF z2Md2aPCKe7TSH*nX=zeGj{z?E3;aWa`Q5;xy@0|L9`iH)KB2F`WdU|}fL6q+0qLZ? zQ}=MnLvngRk_oF*Yrn*?uJY4@*W7H_GE)r84_~~#c`t&Eh~&;zi>D}_K`n^Cva!uY z4uj_mtnn&mg6#q9I0 zit}h7JpxKY1n1DHA1>e*Xanxeut^YO0^@wQ=VWEVT5EVA@y+hgkY5S|g$prt1<71K zeo9ncUO$HYv0LM6EDXLs@0|KN%wBdQE5~uR%F5QsPDr}EMk7x0^tXD2)7s8xPQ?-V z;`PUwq?bLXmZmJF88fS_q|#KZUVNCDwTv=ff97j!U31K2KX+n8QFU|eo9b%Yf-0`K z=DuQJ0Z|{pAX91o;C^@bi4k{fle0ye2{3QlHpw4y#W2Xjlsb+jaB^X_8bkCJ{+f)n z^z*Z+^t(hkC;N6nmXc+ZHS6d$#9{((cY!7&oNF9EC6+j5_fHlsydmd#K$lo2B+;7YL zhXvTW)wODSwlE)`)u+TxoE}83ZxIIp`^rP**58|(tCudD^4{3k0o*ROgwqI;Aq%TW znwLZVWS9=OqKJqF_*x8H7R31?rq)A^z;Gck=ppfLlo%~Xc};I1x{M!z@Vg?XlhIg3 zg~%a<)Fiw6Z8q58dY`@5F5F%_MN?L~DcRnsQvTDz;vi;Ed%<0^O}MBACnAN5A<*rd z19IduWT##yy|MfYx*R-^tCudFDgpukDBM1?Y_XJ{D=Jh?#*FWe!e4D?pu2eIxU-3D zdws9PT+*&;CWp8E0_i*HRo^ac4?bP~6ML|6( z@&qN0Q!T<5S|t}wCS()U#q)?!5fpN0LXZv0vfqAb6_j#@MOEE5t< zU$&r<{PpU)qXC%C_Z7?Vz{iQL#lmdufwI&yJMYt8 z8gJzZ#s1Mz9bTr@kXOx{oA^Es2|#-Y7b-M`zkm!Gk$qbn5<+w*cw2C(d0tulD5N8fdd%b5>zP7Z8W`D1F2aeDJ$j8AtDPPHw z%4@fgj#?oVa{b1LoVu`IG%M2d#d42OjgTJUtB_$5EzGfd+;jU8E7v?cZks2p#Ot95 zqzue_;`d;sPsK-l^YA?9%y8SOVU1O$;@9*e+mF4{Bs&J<@nk3*Xn2L3>;2G2s2H9T zS&2)lCAHvoEbPba=ZYpovE)}1!535Rdt(61P1NL7ZMz;E{24=t$H2J3fP`3*Ma**| z{>-F$%?J^(PJL)ZM{=cM0FNEBtB>LzM&4TWnSn9Ui|@r)RE0erYBNASMBen{JYfnq;7&5X9)#x((~PG*v%0>rKxm^|)q`m|K{hpXNjr#s37yxwfUnu_*q z?EJjHf4wi2j>R@~zgg@2r%D&S*$m(uz%?`fWS}Ge01iGHULMG+K($6Dt_^|7sQSLK z@6W;Q8sg4+`tGICK5m#ZsQuI%jcQK62W4K?}bc0o#+AvdU{MB(!6)RY?(!y=M~6NrK$ zd?t-yK=2GqJi)o)<;$0klZlSvOkF6<+kR$s5?D3-C1jJm6Qf=I!cKML$-4x^}mi@!)JigDi_$j+sxY_wnew(?H4x}T4JGca3oULGIG6Y`khOy@4OE(flk zDE$)7FKG+kSDYsU9l(UJO3_9&8Qma_x_!RvHwTDtvkv!zPThNJGdp0JsJOg--;NkG z>Oi{E!J3)538W&P9vZ&s3)6`Ub&9hkir`oG@h@O$(9f^ixbf6Cj{2QsNo!VJoQ~w| z<)HEf!d2VG8UqV-lL^*?Fk)b&DKxhWtb%dwg<j654#jkJA+L%q^T z4+eFnTdiU}+Avp3-majVEwA1ktWO>GEDoaBhZZcwK{+DPnZI=BGfznqoyL zh`N?>T{sD!6*A~{1x)ASo&=4#k@KkZFvcXc|3_@^86k5uvVyq#motNy<0s-KFM8vZ zgJ7VA@Z_82bNW;|FAZ>6dKD&jU0(Rx3U988`-%ls-Jj5ndg9vOK)}O*GTa2SF`6-$ z=8K4y9DcjzW|OPcJy5dQsme`EiL-GguiV!|gj z@7ZI5^~*{gl+uodmxh1pJblIK$Vb7b9=}3mg#PlPVhI*I1U>cI+ckUW=zU^RuOrYi z2!$Tw-yT=~Hi|iP&94JLG9=H>oZhwkTbHYj$>?z`O|AH}@oD>-+S*<}-k${?^U~bqUe@_AVWl6aqR`?wLEX6wfF#5R*qjvnCQ4#NG>&tW&6p z2=imfRCv=rF_%v`w``dtHlbBdiz=IfxYI;=qE~#me6!Hx*~HHVqe2UzQd{)e@eARS z>g_@2Sm*zE3Ax*Q%*#Q=#7HqPNd^{n8lMp5iQ?{}_9)6`^AU<7Zi2kqRWhfOXfsb} z1&Xz$VVoO6s+`($TFq@S7=Qq>tR;0LTGca1gC7!7Er*Qbp@RokCQ}sNv#T&{ZJ-s8 zA#!!)H!IU3s$Cx(`xCx0#qEjahJ6naKVKCL-#GKr-u!PYvE~Pi5z*4W9EgO1iXU+WQ^t?p zgFgMA4?IoYiLevNBlxy-*JwKTeHuOYHk9$?R8F|qvk~|&X6n!m@ZK1CE$AIYcWU^5 zRPA4W&e>VkvPeBFCgu_BPE1J9HM+3UgK6JTEsVi3+xVT9A<82o)sTrF^Gb*88Io;~<~1tgbq^g&dgXE}vaXB#)OMf8F)s-E@ald}n`Wr!8IrotKy8Gh@lDaRnZ>O7V7soF)45@8L%6hY#QP1kyv5w@6b zQqe!x%W>*EU&eP0+TfM(D-^+qcUE=(Z$vKo94&#Q&cZoinD@pV&p4izD~-RyI%jvB z%eORof^tcdq=?AEvd9{PE{O1A^W?y=*4+uN?j#ov@`r%f| zx^CS&jU}3baNQ#w52R&XB96p}x-^BEgM)*$aT{69x*nnlk)!%6m1j4mT&Ev`O9JcV z_Lb%zTjzeX!s5au5gqPrX^4o-*a=v|s!;`M@=#G~*wzkXP-Swn+Ra!jG7pb9xdWQD$wU_Wp!|NC z)!vO1AC%r|1jbJ)2}tvr9ocGrSp4PDz2qJGfw znb}^&4APmv$eNF)xwr)xd_TGkDr3>_m0Pm&#_A8qfDjl0iDPmBhS|R$+k6Po$fs!V zpDz#2Pq@&qHo#fLCQq2cQc+b^Pq0{*ySJLxq3~V7;8{Xms!|yH=}V?&ld2D;t+e8I zAK+!Mkb}+cVr>RJaC5Zu80Zs^uUh=m5lxf2qh;TDFAjY0F&GJ66Wj69c-wjef~k5j zG1yi>r62kCkMrM8L*AH=b&6?m?I326&0Nfc;N&qv6tF zt*$@Cu$b@rMvv-W=iH#9PhG-x?+Qgh6E-671)(EABjZf#6+RZ9pcO?@Xr*TyE1v7A zWRyJ$8eNrg@eKyLCif`{H(?RoU#HIf{oVSb-NvZS4f)4|BgS1je;sCWP=svi{@!hn#cP{z5<4@2ua*~0G?R!C+bOQHxK zguFjdHo-!(L(&TyL?KoWVKpi-;u!KL+fT*xe5;_!0s+WRRfztHHp>zLOkNaWqn7WDHiELvPa!clue4|cv; zF4b~LS8m8)U(M0S(eYod#bh05_-Sphi3Op#O@~a>NQsS!)qOzl9zs7&_v|`FP27GP z*QRWgt97MK{Oo&%#I98yo&8hZzKZd>mef1m9Cgu3DVG3{=?9ZBJ_0BEV|&Tf@o)AS zm=1aCE?xnprJw7|y`Ta)t+6i}%NMl5>o>gF?VMw5>C{K}H&f^X*N(&0P`{hEd4ANI zEdX70VD}zCUz`ZzS*WlruDqe-?vGCM(VV@Zr+&5-Zk4#)zPnr8_GNL0EyEFB$)=gN zsPCVOQ4B`Ah4+}ClKujn`+s{U;TRF znIFz<31Rzq^Ops$rUz>C-<-vLoB(V0Enl;#>!54kiWCSi`qPGXs(WRjx0>hN)q8D! zjF)Sd_#UTMt>)Ly4ZUbS-ea_8FE0aaKan?rd7Sx=@E6aYhwG{^EN-*tcopf7g1t&{ zPe0G=GgsseI_!_gGG^8|H#ahC!_I~Lhk6J@cj5?5W-H_+q@`Wg_2pdbXjzO@wRf-H zC3fNGfgcNLL#4Y6)mQWDdt6{SzjIwNj%&#K03>Um93}w!ERs5h69-%17)sbiII(` z5>D5Tj*jNCQKHo#c1|3=kqBxNp982KqB>RMYd zV$QWIIKJR#Y*jnXcmu9WAj@o^Q0o87mtZtPT(=2r7y!e!(MO-%py`utM78m1blb@Uwvmjk2&{$?AJ}(A1L&!&S&E?}y*k%2X5B;{KuXLS=ikgi-q7Y<vs~+Kco@pzy+SO=Iz(qKrnC1o7T@Iv}7^gGs00l2J*%x~Sk5b(Kzg)}qLwp^1JW!7lrsMhQ zsJSMeTa8MmnTxuO2=Os^he^X=U4FQfg)Dy{V>EaSP{jK&F8&n;e<~F33#bTA!HIyd z$q=all-w_D0D%+i>LMM|xTK@Z2mYH`fwn;)V+1COksbBD4vcMCQP4`3bq>49J|eFN zY!>>WzZ)Xr&J-9Cn z!w{=^Vc#f9hUYLy1$-|32A#J(7Q7cc@$mY-&CxnZFxz^V(j~{a8s3{% zSXM#~qNr=!9kjF5lB;X_VVMHxh5_bvnB7p9Qxy16p5v^wgFYI{HFU(S9=DajdOjT! zZ88mEpm=d`a~nb)4Jad`x`as^q(@a0wq>8%>9(n0h91Dp zKtpgzmhA+if~0HS(_@p91mBC{3!F_1(RoCBZpAW+f-ialw_rKZ_vrzeX&(VbqIUC> z?k4;$gOj%SVTLX(v>vBL4*(>@rj5*E(SpOOj#apvhcHL(LKS%l#P;CS3Q!9Hz^P2r zkjOAS)^dMeRz^Co^wiaWAvQoviO>=Ou!JL<9sw6Gp>XrzrDI7L0*U}|3ehVP9_&ns zbNqx}ly8sQV(zc>(J9vik4N9t^(7F>kk}#)_oO6VP4V!?u}qwkW2H~WqWOy}rFPdg zL+4WY4Gjoz49I+s?t^5MXJrOJLowAr+~&qd6UAumt8h7}66zCfpN% z@j$+4i4W#=hV1sWGb)A>7D?PGZ)-b;f1=q;HU-XIC`Az`Wpu%c=}>=e+Vm8Ahs+mP zSXcl>Trth10ovPmpN^N@!;n*ehY^^l?{ZwpPc|+tqI^Y!7$CQW8-c0ujqiq(qDz6- zu6;t+iHL!Kn1pGozr%XeTu`t){qeHkzwJ#W@lm%ugj5JlWeWPG=#o|1WSv4sPg7*6 zx8hDb9OCLmOo$1te_~=HtO{P>AuH*4{UK7sTLOF`xFvu!;#R^jtH85{D2S3QWk?<8 zsVjP;_89iV*X#>cTsh|@C^Dc)?fZ+UAt7IQ=f4W!bT)&mIyu(^L^T5uRZvhc62NDy zDLju0C#yQL{y z64Hyvp!JdO;l1!jRjqqb_8QtZD0-04f&Obh`R9j8HC9&9Rl?eWQ3)|uA-fc9#+s89 zC4C%(h*Lx`2iRZ&oah{8_~F!ob#VZN!QH zJ=H&Fs61UT$Ff5ZghC8}UC?P-8G9UK;+X+k#k8TJwr>~07XxA&%UP^W*jEAk0tBBJ zM5Qn;0z&u3S&Cmeakw_kJA{)X&u#cF8BNX{Cyr<4b6?Dt{>WV{`zg_zF&QK08d3lP z7XW7gp?a&JU;w`2K2A@lTM5g^7y>?mMVunP9@I@BN|yfEg?|LBb z`iR1Z_^|=5OZFWAJJ)X95a6UJi=qC64Oas(dqZy=|8?2t{;KNg&pji+IUG7wM!0t5yID;3tQ-fpIea|5S;tohm1ZIRF^%YNGe_ZoH)Bmsl1nY*(SqkRD7>*zTcd0Zxh|^({#}MSk zdTXe>3j1Z5DMg>pz5YR*iva3)irqyF(}6_>7|cO!36C%)hG`tR13&jt8?>m zq)0M)(vbAwTmQK8+xE*u(2B0dOXl7#m!Dw-_5$Jqa(E&Kx7s`D_)FtkfJ@>LR@%KJ zfx$8RyI8F}pfNLW)__tu-g{PXyBi;0O-vAZ$2>JBSoSj|`Lj zM)2ej%RS^W*Ku(@A==Ws!=7^ZNhrFU3&*^WVj~TN7+4F4B?M9oVOabJxtoWo>grG_ zItt_igu^~#q<(p150M0hN(=Ye7_$P87}8dtFht;-fi!^Gk6@_5KHIp;J83PP($PjF zeOY)#=6Oty+?SugN+UhOfX}we7DG5y1u_O?QNpE*oT)gl5WgR!q-2t>2m{9tV9QgG z=^`tzyu4h4RjXHnAEb?bh2N5* zF`Me>WRe{KtpQjamSj#(86hwzOy<`5H?Of-+;cpovYe|yE_)0lE5TSpy##_*IGEIB zDVjiso1^pqCM zm&S*W9u-E2fvRFP=)_d9e#j0BE8Brgj7w1AvUs!UCdwuPlYefZBo=?Lo@a zSwvc_3KGLG)j?W;f58G=TlOEV`s5B6|9s1HO#?9NF|1qAqIv|%8Wv!Yb-vk=K(e@| z7zp5w;L%`4b{Ljc$iDF@-15HvzNH8uAL|Z08r;qyC#UE56M%6LqbT&O|0LalcS_nn zqCY^EIcD^Pj0*S{97O$=fOJ9bHrWa+QBXtb667zT&7Fcg7^+SvQi|!IABuSFty|aH znnC6xu=^vE1>6g6J2EFn#>j}6FwI|R5I9>=j3Sj{@Daa)mh{XNkMOs)}s}h|ooGiCs z!-0zgRfx>L&Jt~NY$cvUCV4IzKn9SkoT!c9Ca{mt&S73nl#wY)4}bRc=>Y*pv?gFT zofcPDT3U+K%jBOaHzj)Fpe7C+;EZ7iDs~EuS+e@JY|(d<<+l9iz45+9%7GLV%1Q{u zZ}K+Qpx1D%KNd=h*R=$ptRoLzUuLTnw+lB^5rIyh_nr(KVQeGqpF z1wOp@Hq*sv1ckO1(`Ew5#K9{9b4k1`q_v1CWCbGI0AvZm)ToLkgyQP98NUd`Xa8-Z z_-sEM1vl$m~2-;b@a4| zWD2T`{(oqf{E?In=UgCLlYnC)D+B$7|JH8Np~Z$Mg@I5H9z*{X?-^=>cBfC{u)TwP zQtJ1JLfQ1Itwk;8Hv-Q$%t-+#1NvctYx7bj82VljlUzXOv-xV|dq+P?rVXj-Fop z!M~3u8tK*L^gjnSH-mmZ(n*?~Hydg>6ePF`@csA@E|Hrc>&3=k zX`^cNI@HLND}QsS?|hrLSjQww7&w5aFi4r8HR1_MO6!<76-1WJ4N=qNXJ||8Eq>YNg9{Cs!ppmMx-oz*ZV04lW z<7h#jfTY!bIp~LS5fS038qPD6fawRtbHXY0y5}LBSH_s7k)9C_3D622VwVD!jx`bQ zEz*N5?d#WvAZ+eaSGPx&hDDF2SGo*C8_TRXi5`BsytBtifl}a+3puW*$S<+{HL;mM zr@L9-*JZ8w94mpa`BGBU@N0xt27OE-O}8976Y+&A4O4O8)Z=dUh6Dxa;r~SJkOa^S zKZ^|R5eQhQsN&;Aq_L_<3kB#3gwdOpYzQ;xFkwA;*J9+4LD@f{$6#I#6A7tvJ(?(t zeqmL9Cc~Na>r((aN6SI`Giw$qL3nB+eIx!P8iVQb-SYtyg%ILW0TloSpUHV`B^W~} zV)xKZ#**9EBq>>2U~5ZLu4Csc5q*QSQyxIt0r3LXdAi!h%s!Inh= z;J2i03G!)`qQ71fJ5R7uX8EDk1@-eChkbB-9ftHX0sj)CWT4(q9DhQ!D&%sl$`Z^E zEKPDg;Q2qee_wd9nwa&+J*L4af(N;r_oEk>5JK#;H8SG|RthG4Br78MpnJu*1lWHO{A zwKO&1!x6}$xDT2fB=f$f9!ivzQOW7)>)#|jjpbBjfboEV=EbCu&f+m*`0}pR_ae6c z|2B*%lF929*MebSf&dHO)CTZMyPR_)aZD~2^(v}hdjlG_0w4@Z^cDhU0oy_4S2The zNtj8K6^)KVNK{b&z+rY9(6;+_EXB4agnKwl8^D1Zr!iE#4HqjZB_Ei`(>2=T*2OB;h!UpGTImSYI8!TQe>gz`btnokl%g7rbHt(Wg%GqziuCMpfp?C!L z-Hk9<-HT_10)wD04`Z|7=16$QypK7I`+suP2J}YIjlmHJ%Da}V5~cI1qz8>0T9>?* zc!zrQA8Y-DT!vb#j>DVO?l>P%{3a-+l*8}lL{<~Ya&O)QWX1a;_|dN2mFs*L8=9?r+>Xg2)P`F2RBv z0=_2&Ry%$?DM|pHehDu@fG_XwzW1S(#48h%ZO{uww*@m_cL#c8k?InsdUBgk-^G9*hT_M zL|&Onpt|=IehhRViX&PS?Ln7<)Z)I>vt*)2^G36abP+Hd(?NNP!-mM1k#X_zDYmbN zmXUX`Gv)d+1*n4>q-ry(dcSt*y9u$N6r}tjh|>QgfH?n!INSK~_Wt>qR=BZDA@aYQ zQI6JqG??dBatxiW|APiAJ{zkdA05nZGG)$D&-ZJPf@T zEh^bpijZa=LKzRO8Q^29QS1^&>|gK)KLjm4uU8_7m zu8=!6dx;O>)xugmlqY93aZm3DLJ=0&Jzr{0qNt`W|EC;kbi`^Rt}KC+vY$Nj%>Ze? zJXJ49Sa-;4@QMiybg>3YIgiXhWpSsTKw8nfq=o^||H)3Y^O3wmaqbO@9n|*-#Kt*i zdHYvc%AttBL;2_0vuJ!nJ5&Ngi{aM;1{FwO4{<|mBsa|}hRUD_> za*#17(dho5bwL!;GXeVq%gOX-Mq(P=lqm)Wo&GSSlW7*1XB$N`8 zxui+8g|ww28dOLs4QNuTb3ZHlJ@0$2bG_Gho$q|#IqSOi`?^+Z{nvl^4bOAm_j5m- z)RmX`AWkhR2ZWuK697WY><4*oi5d*&Dzce;chIJ(IXU@i*9?H7 zygXX(J=NKcHSBEw=!g*KVZmV??5t?ORx3H)$3wx-WMV*RRG0y|585N5U^2#MiHldL zOAEQGpJng5hO3~3r|$Kr_d0g;=nI%UV!1)yKq?((%4=XbOsocszBo8cQ=uu-6$=cO zChmiwiYr&9lO^%Q_!x4!-z)87Y(&r%dTMKnEgsMd#N3m2U~c;HM6MypwdchFOcT+C zLVV!XC|%W~bP(NS<^}Er*bGc@a;Sv8bfS`1-VzKjrcwuhWFMa#>b<@UrsxO)q5c9& zAu}&fD*ZU&lEDB?QUSf<NMSx~$!HPd~W}Vt88H~A^6ic)iH-=Qr!;rUDLap)N zVfV9V`FU@b1M+j#t9|_V2m;K>izXElcIa8*ybyyw{0x$WI!+V$08Ru;6q;gzKTCAg zdknDT9|M1`K2N0$%#g4XFJf|QB9O+sBEMdgu22O&UunxLHR<9GPpJ0sRN$XbfF>#z z9%DVgc7jF>M__a?xj8Eb3_6$a>S0-7+y2nHV@2CPRMvvB#h#|&>VW0Z+T9U$HPp+S z9k7^f+&Hb3n*%Enu8*B%wHTApJz`s39Ko!ktE&bYDz?A^=>mdng;y#t6%u4rJSyY^Llzw+gWmO}57Z=oe`j_+=eC7)sZJAAyy>;h}-B zP!{b*KtypXz>}O|&oix^u-_QKBcy{g0VlYz%58?VqqVx-=9dfQczd zSPQ73j%}-kQ4~K7;0X$NIdtQTu>w*!#Tm~D5Dqh`nwAqv&@fql?!?K))(#FEipIKG zKhpq6IFCg|$ufnY>|H*9R0N#vOC-rZk$J3&+S)0ZLv^Us?JSxYEkXg0p$PkoZSpSr zVR|rs#kvOK%@i>>wkCig&``-FM_U8@`cX9nJD;J7i>eJjl+a+6WSI~<^YeEi(5^-u z#3hufgAAhl5Ls6EHwk{Uq({~C$;k{1{-YOw#vEFH5Yrs!(IJN6d6+g)zZgRA4jtme zm)R={Aq)k#k3K^&Hao&D-fHVvr4heCKCW*;8utLpH*T~qFP-&aQFu72!4X0sOvuUq=o8pvL{9q08+?L=4F4D zl{sKSaocbbFHF2MCvz4O#20wHgj@ihG>fnSxVsoownOxH1YIN0d0t0mBv0+6qy&-9 zqq_5ilwoMcMV&r%YOn%92URBn`vby)ecaKciJ#DnqVJU~5mDL!IeD=IhS3*bn?n>^#jVKxsgvGZzvS%zj6xEYZL@HDe!{8d(c7eDAcRuoRAObiK$7rH4yrxm3 zp^I`{s=o#81cWPIkfs7-ybia9wsR6k0r0^BWP(`)4vy>Hz{%+7{V0JT_RnlBi2hKW zMGGTk3UR?3%V05@#Fe!|dZ1*WWX(_joI2y#p%=Q})LdbgzE4Df_px578Zr&4=^>r z!wZJZ9LnHmoBY?LzNV}HE{8wxji z;*+}MpWd30leBy;k~TJ6e0VuGgd*F$(IWBZug4*mMtXi|Ij=qs`!mI9Hl9`H*p%2u zlna*zb$+>^;2&R@3sMg$hfuhIr?3z6=xLaHY3=CTc1t zufGIpH|lI)Sc2sOvl?0-I&H1{;Bw@or4LFOUIZ2c)6>6?S>AK;BdSjRzTc);Y9^1g z01^_IM&f?sX@ZCQW%8!a0A~0%b$0* z_=B~NsmCg`K>`iS%gO#=pgXN=0Oc@7Yu0fv`U+eZfQ}%uF+eFn(0ox-Q!HmtYoXI4 zgE4IRQ+y=21mm7;@-gF<;%brJ%fvF!!*&2H%ad+zv{Ype7IQ>_2*l92F9z_`YiHSF z^1r}lvT*X2w5-NtM}d4O2$D1CJB8g|kC%a-H?U|H$F;WD0?}uXKO~XN1VE9g65zLR z#ltiTLPMaCWAx&Nl4CF;S~6n6^SbfnnJ}zUswxzU0DNsimuB4I;v)Dd12fxZW|j)+ z17YWLjvu!Ek%l23$v=O=&!Ovu^@5lVKpsm0_&}o&{*H%eDufz8Z=9hfRt)q;&P0|E zq6P9Eu?xdhFcYyum!ipg%N;d79!yq(uvS0;)^@748a^M$YRvr|)Irg1VtIm*r}GFmvX?}OHU1;&@OPT=^bwe16{YKG^?xBM*tgyX22N8O?k9`0$G zlcGxcBF!T7Ny3d z^oPls@T^(y%?pi+$FiGRXOen8bwu5+a^)N6$WhKU!n`X23v~%x5q- zr5P=w$WqdAXoSD$zpzAEx%TQH+9Mhwgw43ffs5i>!o`qi0SJVxy&Ag{VWGIA*}UNl zhIL;bco2VqAkE$5aa|+k2Z>yUeTLNKuegBQ2D7+_^R#&QN2 zk)@Dvf`tmZw+sN3WXO-3(63y^ibi+pU^SRjJQ0dgz)?c)!&Nu~8j>npxB+r19B9t*Kii5PV11zo z5jUL9Tf`X>F97Z}&`Ltzc>(E5+({|~zlz4(JK@45tT8#79>BZ+kq@~LsRRzY{`u&U z`j{$)DEWX*6Q8`k`NT;P_!KgpuYXeP64tehEI7sO#`qV;*mgOji__O878o%e>6xg! z1gUI-$Xdz*&rNVxe%UDHirvJ;736>SM1HjC@@H&Hxs@@H_$39FB+>|J01^pQIMT zcyKNerurO=bei35Z78cU0cT>mYgfG$cPSpXnF)iDD^0UE8C{gf!ie&gA7f*%Q?k3c zQ^tUF2#CGqWF`kE>lJKnfbn(^ZiJ8%lsipZ5Ug9E$&0BR5HY+DKa*1Cb z>lvboWvy*`dU_*cIr^^@40LsMw+gnr{{(^^uYYsdmfN_9?;+%W2t1-j5PE7uGORDdhPwycmq9qRe26VQV>KoCa*yVN* zaBl2Epy#(EpoM4zR7LmQftkX>X~-Os1_1F&AOADxT!W{V*VuV^>}cp(S#V1pz968z zT+Yo!DDUC};PJTl#OIEVFZKJkdV2O(dMpHQ3cD7VU3eTnaHpXgc(94BZ7Ti1q{0D< zWrh81KZ~>6Q>Tu%v;uQWD*z>K24$Rn z^Q#b+4c0wdmw7R0w21S^E5t3Ur@Q;oI~}PqsqMZxp|YD3(}=)MTDcjUk;`ngkyJDr z#DYiJInY6DZyNWskk*rNG(JdS6c$j4yJNT+h|4L7#>en!2o~FKo@_LTk)?jUkW)zb zxj;8c)I35ZGAPGQE06fXD`-VyD$`*GB$K@>!s+3Ms z5p8|D+?@kegp(6ROc*Kzo?X9woues&&OBM|MQa(&Z3* z9gyH3pdtmF9~CbkfP_Y3%S|c4lDl}u#MDq4fRl9@_@newrS;R;#fge`$EXMt88!tM z&;$-1afP6U%mqlRpr!RTwF}82Kt3Zly+l*d9w{ZEaRU&6A95efiNrRFsQ(p-nK9%_ zCF>p>mtGS==1^3fKzJ9nEz*Mmmx3n14MmnvHA8d@4s5oBM9-JHxAb{LB((QolV!d7 z6AO7$a6@TH2_c*~6NhKLXU)(0!oX9fuan{vd)gAI z;@e5t*!)!`eG%0WSb+_db{9N>%dUdVR&!KvlLr9;5Fd<^N<(3U&O*PrJFcyd-tq>IQ*-hmTrjxh>zdQ2o zxI#Zj!@l#J+kg>)ElJ+8sfC4Flqg9s1FwjyY z5F^jDA`c(#c*rAJTQKzYDk52;>@+SHhxQq7*f6~Q*u#L~@88LGmI|h@47SJE35tkZ z#_%VF4vr^TTlgLF8xm(Gkab7K?RRt}0sZJe4$3GL?;HTb0+*Vj4YliZbV7gj zrKhR8D7u`c0NlA~MgnYb%-dHUzrvR4YogywK+%SHuIjR+j^XN7J6#7fc?N^`t=?rv zl*mfwco+^f^VP3&eOGoAv}()_pE|F!F98!{LtP2`&WXkz^gyyiqJvL`qdo8Sq!&v| z>!K@db(%rU)V86y@ISYLWftP8zVCU=Y1697tQ&<}y7yh8MONsc!}!E`++x=~=GrT* zz!ap+SP-@hb@>W~!xvGbBtLCUv!+@A$baNxi}`YeS#|@l(xr zcK+($_mGDSI8p+a4x7mu#-BG$)$c&A$2HhpRhwxxKpjEA2c&bl+_%TNvL4H;k$7gD zYPhxnE*IyzK){qWbJnbjsOjo}+CL&-7IHN0fRJ>ih809QfUV1f(i-}{eXGHICf7H2 zonRJ?wc*ytCMQdI9}>1>>zMJ_M;b{OR*xiQr&_sb<10B1z>Esih{&mC>Yzhv0K5yA zEn;;AHsn;&PkwJt8G0jsQF{^gKbYpu68Mehajx5Y`pBrW&v=SQD$i@!2g>mYGQY$f z3JV)(^mzUyJVz47U7x;`a6C%)Q>kcIsjh*i{U)j&i!_$RxZ4cPPQy+vRD!0xk zF8pEX{D)yMa7$dYZmN8`vDWuA=n>DVU!ezbE_lRI>^J^IHMfhjL!m46qy>3qLM`4}d(UIiGQbvBJ35P9q z&+Ck6t*2wd1`5bcp(ka@Gk#5()D&F{Of8y)KP zd7`y_#}2a>+<&{FkD^} z4lPI3m{GLmVEo&_ZRX+ zNr;qjZGU5~8+qywdEd_qq0-2feRu*pw#c z{e{RAY|ItliwGMb_7&|P>;Lx6%)#L@i9q+1F=-phlsubp=~4$+W8h25`BA4%36`!2 zYBmC!1u4!YsQ50!uN&GyBfs76Puw7Z8f0{vtutWHlQn>ZMM-5HfmvP%_vvk?@CkXXG@WU(W1ooulkxZYk>j`3DBz+x$dUJw6C2i)@z%wo8Z{&9IVvQ;reZyN;Fs0Y z)g|6PhE)yL2|I8A{iu1F2o=@tmY0!>CWds5!@^LVBODY80L7?Y+(oP?Y6pn!&Infe z@Kk&Z%Qs2qOngM*m3Kf=+>o6mh{6>@i)+L5?{`4#GE1*Kuiwx zwnv2!oT3Wkwd+D{4UI-eI%b3zO>0)bCcp*$6VP<d`#j%hYo1BEih ztiz-{tLUEvtp>%Lh@<&`jV~$dm%xUlV$`v~6%ZKtjw4ieOUn4HT@F|Qt3BxY?U*#O z#^;>XkDS1U4$1hyi4;HfPWVyo|0I5) zw+n?(uyDNyt0)ujBVXemZX=;1D)VsoC(X@P*i)6f%tyX|UyL0Fk9yHmH#{JYM5fS~D*SF-LGrpQ#cm;t{;x0sMM_L!1 z!G5GXHWmK(me~b^iNGo~?#Uz1>&MJpymV=WXFQO36=hYl?KuV2m33#%=*UQaYougn zbjXj?^@pQ(iyPoN$nmn{;07!rUTCHxw#yqbsr2?-Jf#}?c>>lX0$h}pl|K7rnF!&hT9} z@&b{WkW8q?Yt>Fj?h3zu6d&vHDN<^hZa3W5iiq%C3+KVA9frulYE?b4@`MbRN>aG( zyUq_MK*c6lP10FCT=yG?!fN5Ha~&~az`7vZ@AZ;_eFrnW!Ve!7^{;?TXYZ2ahHh^n zlqu;tmY3_^cFZh&yXZ9!vS1#`2^m#|%Gf{90?--7{&3h;2^v%VD%|XBK`{48)wfls zSc9Jaygl@n6wOi(3@9IS zae8nYiG`I_?=~+tbeyj#7x7>S7`c9L2@~)f|KXRtBnEspdHttPeJCw>Nayik*ioiv zQ@|jMRkZqVR81{wvflY7M5z)uI|VdvwZvF7UCqN=kcx0kS~y6 zGyj%6!ha{H9EXbbrqr4b+=2!a)@k&zTHfeY z`?z$Ll`6ceOPl8m_4oUBujv*?0=m@9V!hucJo9L7y;Q{CKodT`Y_o+lSmn;Vpj-AI z4H~f~eYz=GGPDCE1a6y>)PRlsUpc53sQLE5ujIbX$0xTJwsp0)@AJL$TT-RH(`wB> zu~hLHe-i>hQ^i^`P%H#h(M(&C0oQ{BPbo1z80 z_0B6(R;kj;x@(t{!<)XozTij=rS^!N8J+L11bKb%RrPNM%JVgkBikhd1utKwXA!P)evfcDet+Q>h;j;=|K6p1jWI1`W45$PuSXh-p?V%t(UUL^ZeAL%8zDk zd+kF;8(x+;SZw&3>7roYS^B%;%3YFfZf<#)r1x{xzBDecv3LTfVEybVTyAII6-vj& zt*DzBwSLEEg>o4_$<+Y(@%m3f_AU+|VR@*#`cY)V3jOH!Hl-16U-}ks2p`<%;OMyGjyaNL_Onyj^(eOh;qICW>>{iB zb3o&H4y$6%q6!aFgE8m?Hc1!n7o9=&yDoJ`M~)nE^}RnlJj~Icwa_Ng+i(JV#hPxB z)N(hZ8`v=Y-r}|T3?pi zA}R-!hiW&L`c=!G{BK5PL;ips&jT(^6r1wx_w^EAI)BeYNUH)Qp|oP|?AdOoR=q$9 zz^C2j?BwKr*~ZMm;y@>FJNZf@jaV|HZv}EBWsQremG(6d8aFwG5Lo0Zb`EPOp<421 z^PU*`A;;^4$8KL|<|PTg4>Q+#z)2atpnDZai3D5Sg`w;mt&ZPgUqaOzah z_w<(NYVT`E9&DWEbL+L=hrgsU?I;wksMQA5p*v+-T3KK33`s3>0nL8F**wFipf_$p zab-lDHZrh=&D+Qw2X=d<6}z*x6L&1%P>6adGu8?;J=%WVyyHyyd&uKA2bENz*d3*} zYbpi@1`?dCfXiCu4{`}u zv2=$@w%b2H2}J3OCYmeY$xxSr>e}#j`|MTM_YAh$qa zX>2Lu!HPWV*7yw8_y9!B&GD;D_&V1ul?n&eaay7p%$PuA>T*-lRMw;-nAmh34~IKZWMaI2L=F5PYLP(GvdGX#GXNZQ>c;a|LD3I~=03xcyX!T%9RI;XoK78Nao&mhd0rQ<&>?N=CtxXy4UzGE<7dl?jQ>RN-p-Yev>5Hk>2x(BFqTTHtn}ig!D%8~T;aA^I(R&@Bp0@&vOSu6F!+nl`=YXb-xKsjd6H9>txq!0umnN}5bFJC4E z$MA7psB3^QpO6oP=owi`($WvxJOuBPpEcj7-c<{)`KDq&34(Gsz3w)$7Wm7(c5IJG zNlC#KXGSv4Ng=HxRj^J!LrB)p_50o`S{xEtm1i?yR|FK~+mQoJH*F*B|4Qzt?IVH| zEErVlO+SF!AEO$m)%n+{l?YKeHTRywPz1S_n09c!@%$Jl>e8pi+V|N^j+w|%zl-B;IRthp#gldg`22|^H>`-Vqp5QA= zBl-t|fqyG2Gt~Zs&g(7&(>cSkl`|2!`XhC39L!3`uC=;1|NXs%_wueHM5N}UPA)Fq zZ&-m?vv8R78@%Ct+z90)3? zqbQi9dbukF1x?FxvY}Lj3!ZG)t^xS0)xj|~8w6zBxDkfPJ?A$iat+*izQ@Gpn(fe9 z%xUh{m^Z@Pelp@z#>x*2zUyz_T7rBEkkHOu2aFIOe;1p{Yu<`1l6?((JUx7Jpp4IW zHutq8@C$0AVpiD8b5M}Wb43uUzUE1ch>Bc$^kjc_!N;$QlB<2zxU*2z2Ez?ujnLrz zsCGvypVenI{Hm7@W#Bv1yN-b4qqZTfUs+d3^ z<+cr?XpQaS9x|@M(>m1XtF~e%R{>mY96?|O#u-b6XM6(C2q>{1rY)u-uB%B58ZzD< zawRp@wm9Sg-F4jBh2J=b4Tz2$O9xH5xoBdnx5-=PV|u!50lX!#RdMsAHnz8}1xz|V z);wW>MjA8Dyt@=1|F!}#DtX`_V8)Kqci&)FYcQx(EVwG4RF$F4GS(j3iiFujUq6CE ztv1G~{-)ihuuMZn<~vr11T6^cA4z1%Z6oKwoWcJ7PY5-(0nDMM9a!dv8^646Y`g|- zKnEyiqqDwmKf8THnJcN#Ks?rfcgZCRxQAc@sK+db0R+|<^!3oOhXjaWbGmQAMNYtk zT#<<(x!=FOVY78kODghIs*M0r`q(9B)O@uxZaWsh7l|tSNlBGcUx>m?oGew6vTcJF zE-WZCBIpVDDvDU2AK-ZdE0C>ts#r2I!L&F5T{7Rm40rXxT_Kq#jN>n%Q>P;+I>hK{ z)-AJ0tpy(;sLCPCYs@={f~suP#^K=`laVti8$ucKM?-UNPbwrKN#mE)`g}T*rEwT@ z0LE<8$`PzSm2?2qMm4;P*$%|@ggd&pG(%9;WIvj`jR%_oH2<|AEj8_@ML~^^o#{oP zj9^KOOE7>Sa4M$2>wXFkfW1HiaE$ZNViXHe|3?xmSX%a&ocyu zY;{y_Sqh~e2^w&NFaz983hli2p<0%_JW242pp>*3u(Bc^1UnT^&?vUU0r-Y@0ZiKt zWQJ;5AcV+yqqT6<3`O-g5{Te{&w(L#6bd4nfeUmChY4uU1Tc@Z3YBL#{Y#LxOyS`% zTdr;M`SnfG0$;EbK)DVabNxOS`gnOE0wE6~tVAT+04Q2;>l`HhtaEc!$2+pxAHja; zY_-%)xGmze@Lk+kvlugUXKB2|S_R&c{1(J_4MGblp;>KfZ2Y{ktLEecpZCxML`q9! zWgoS+ft>LC@c4J#roon$mZa`5@wyW6g2kxR#$#E2xnZubaR1zfb|cmmxSIsKYOGXM z9WCSHRqC!lj0`gAMT?9eXU~3=AX4$w1v@maDR7bVVD#(*Q8QA>3bu84gEb?hDk7JM z!Kaaamh$0$CsF!0>ZSjVKZPnxKhI>8-??{>h`NYBx;r~BGB|RnR<*TjYe2y2DR3?* zVM0P-wK78yX8XSOTYfhh3WPc)i--B};MbpEvY&UOw zdI9=le5k9<{CTKqv*5<+l~38Sw*0r1pNGbD9{aFWj4flg#uo^F{P^+QAD%~UO&-SU zlmFnTjZ}Wm?58|*jQm#uip>I?=os#DFD)w;E=>%E@7b(6rRHd!lCI#TnQ^x`>Amb1 z0h(PMi@4~6328%e3iM{5Sg*x%f9?6q?9ufG-LWXL!I$#~yF`u0rqP*towm$qq&JJ- z7X)j*A5ajq95O!5Z{khwwcO-4f9|dQ^tlT~2w;@>VmuA2cRppGg2u+XX%FCIpwQeS z5ZpQA!gYn*?OVj{cKM!i!-w$OBNVJZ@gue&OYMc=hG4e=i2rz5wsLI zyxS|u)REq1xU@-T@5@cGbF;oQA=44`bPm1Q_-b_IsP0}qo)Y*OKS(S8WlZ};5DISa zm!o6;+XH_1dw0d9%(LtFMxqnrrs)@9+CzU`e!0HCNi}Tue2Xe@w-VFLWDW?KZK1yu zTW7xVNj*A8^tac0`gdecv{>x<>Q8?V;p6FV(g<6pzr%XPx30SOJ3FuUYVC5)fTkVa zYOBxQccV>P^?A$l6^(ZN+p!xRt@AN6bB-0(nNJTb)NEj*zj5>CrKasCW~(m~3|0^^ z`n`X`;OY57_5l{(+cZ_;cnEKFPtshGpWTPF5{ewMi^3%hc zr$@xdWX0UsULBb5!-ajT^W!&fi7HHbA-z;pb?DC0kY{ZN`~GlM)2r_6;&4ky6YPW# znh_e^6?~! z8y81=I}gu)J^=kHUCW1W;WcGgL+C$v!2Nu&uLXz1sj$4{XP9!NX|51Gu*U_m1&D0Of)GjQ{`u literal 0 HcmV?d00001 diff --git a/androidgcs/default.properties b/androidgcs/default.properties new file mode 100644 index 000000000..e2e8061f2 --- /dev/null +++ b/androidgcs/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-8 diff --git a/androidgcs/gen/org/openpilot/androidgcs/R.java b/androidgcs/gen/org/openpilot/androidgcs/R.java new file mode 100644 index 000000000..31e90ffd1 --- /dev/null +++ b/androidgcs/gen/org/openpilot/androidgcs/R.java @@ -0,0 +1,31 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package org.openpilot.androidgcs; + +public final class R { + public static final class attr { + } + public static final class color { + public static final int all_black=0x7f050001; + public static final int all_white=0x7f050000; + } + public static final class drawable { + public static final int icon=0x7f020000; + } + public static final class id { + public static final int objects=0x7f060000; + } + public static final class layout { + public static final int main=0x7f030000; + public static final int objectbrowser=0x7f030001; + } + public static final class string { + public static final int app_name=0x7f040001; + public static final int hello=0x7f040000; + } +} diff --git a/androidgcs/proguard.cfg b/androidgcs/proguard.cfg new file mode 100644 index 000000000..12dd0392c --- /dev/null +++ b/androidgcs/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/androidgcs/res/drawable-hdpi/icon.png b/androidgcs/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..eab1fc68fd7ad531ac025a53956f78de8d4e5180 GIT binary patch literal 48558 zcmeFZhd-A8`#-FdnGq@^BP&}Wxy(c%6pCym+50Mcg^-cGN7-B1dke`XvNu;UvbXy< zy?@{P_q*@=U$}dG-jDbDbDh_9p0D$G9piaCkLN4Dr;3k=2&f6Lu&{_^Wu%m`u&}+5 zfADbNlYPZgVffbtTS?hxc<{#=@3k-de|#$$bz3YfiYDZrb62bsB;i9UwDb$Kisc)$ z-Afw-EIT_pZet5mTm6?-2Hci5hHvMn~f> zkcCRha+`kU+<0%c&aJ6q&{105R%npN7rTG_G8E^PemgCOk8g5umPRo$HpcKH7e+Lx zdw26&a&M-*k%@_1!~kcOjPi7=+ZC5Ty8Qvo=in72{%$=+v0#=mPPWTVPds;acFvK% z{Pm33OF=$ewwBEa-W?0e_eoReMEF)g=t*8pO^sppgnb`wV|seJhBhVE zT4?dpP<`b|Qsj$dYEpfUvOIDJLvTaUu>Ch-cS-LG2ylgNMTO=kgbO0yai7~wOwAaD zKPY0h;4mf1pCMG6mD`T%!W+UG* zj!jK^tl=nd`Rp$EPLKMsVVz-W2j|s9&ek#L9cIa%ztxFY2up4Lb86Md=xCWv`=qn9 zngqXqz&KZy!X;1SqMovMYUwA#V*I!sf|n{PVQGZjgs!@wZ<#IekjuUmncP2(k*ABT zGFXmbPq#KriOU`|Mhu+Ynq~YnWUI&Cr_s-h>NuYg2lUhf2Dn zqf%!dPe?P5k4{XSbaWgyb`X2fC9#aKunF8XM;_xYdzaq0cV3b1_@~GEtP_sl$Nv9* z)JqdSu%W(7p|e2+8^uz_t%cIPyvd3Drv7zK@Yd!h!z%xS+y@4=9LC1E{>bN8DsQsH zW`kq=EvU>*OxVMV)s%nCy**oQdj03rSg@3S(uug1iTC>9E6NM-1NYa#$%K3pbbFpx z5O1IgEtR!VaJ-7#OOM@)xzpIva&7PUbmJ9=mm9-}`^e`qEZo}B+hWt?9EhX&Gu4QD zDPWQvNg<5X^_vxlz%$nWVcS}Ow#oaoOd@3J)s4QoL*mT*dM3vfJ4N9Cv9Ylm%r^$p)|in6V=?*orY6ISBu)~$+xfmc z^Vz@kUkLf8);>ri(w%+h@CBQ!s=mH{cB)FK^BX7RXILt)Unu84P%ip!r|K1*Lt}4* zew2?oyO^#O@<90u21zSe_2C?^>CbNC#QwVD%oB&nH6J2YtWSTzaCRl`mG{|$&9ZwK z*gDY{k>Bb4NE4F3hWr=SPrd(c5clf;|2JZf|BoGPVu<16Ym2*w&tJUAY;2UAUtH{1 z+wGYB*9QMv-u|(?Ef;!lc*wIq_l%THG4)XJBwJO}{nB*vyO*rv=Mh%243$-G>T~V2{)s92{cB z-D(%QlM4F!`q&)0pWaGcUA4Gz&q`vn%yMX=#z|fJ!hZ{{cP}iwGw!gM5G!Pxj-enT zAu(O-N*F0Mk9+rb_=|_fxqewJceX}w*LsQ{-Q7bs?8d$v95|{+8lVG?N+r!w|X9I z>^rBcyn1tba_o3|ygN8C(Ur}B#dHrb8;gg5dgbxX=-UpivgY}s_uqPkhB5>v>>sSv zoz^~l^a#0IJ{C3u7FO6)qSI>c#(al@p}gP8iRfTH3z7h{c45Jn)s#>R83W54GCR;!&wq{nxLhENl1E zb=;2MmWG~}h_}6Z<%-KB8p5glb8fD@?%~MLoK1y%2Iag>1;r(tx19n*Mpjl&$H&Lh z!?3WT>cMalm-dcbMfc~z$G%L`ThGha`Eoj#q-|Y-r3pNcM?L-?Ck8wGL5?8h0;~9>aYHH zJ(pM!DlCQQMjN9U!$o&C#IE%hDzvyuii@MWWE?x9c!tQIhRrKfm z%|#9YfkE^Ku4k&Me_{+1d$%zC3K>`u%4dH19&)ri>#!WWc*-ZS>^RHX-)I6XrWt&I&w+TUEf&2ovQfO}N=iy>s>aj#%uFY$9UKoZ8ITf;P#3X6 z&m$HguYZfTFh4(UyfRW^VrIsla2^Z)6XNsunK?Op30ShUpC0KR^hFh$46+N+9Nojl zQu|o&84D{wMM){7u&7AEaB5e}?ReYq=wE9@NXSdLG1-}^XPe*k?mg4i&inOCb#P!H zTJfB_R}*54d!31*qv-S845FgipG0?}^XpC=5mP)xOhM^0F!1cTs%mUky`j}T8jTW@ zh}x|*p7z;)(OqzZGi%<1^wVC**-u63^Zon7Jnbsg{r!E|0{Ye4$O{vjT~pwMZPKWE zm-lCR8L^_4K19^i9U5YvH=VHtC~We%&Hb(QCK6Nd7A=Ky;QeZlytq>;D>Yo}Ceb+g zJqm*3sp7}|;?L;sg6Bda^gG zQHjpNP+<99N3J-37#q`4%#pvz9rbv3+%AdMafzW~+yY`;j|Q=QlE+GNdsbSS^b^tT za2s1&SgO0y*$;6_{aFfTW?q$)mfqRI{wjcMGtUR7qz&v+q~yu3V! zSUz|=l@G`T|F4{n-@bhdzioki-9}vB|0>rV$kYLo;x~LVlGimy{p=u@+A4w zfJ^tfgV#N^71>wmui6ywgTAmQVp)Ixn!%Rx8lS}kUj9vYrih4$tdf%Fe1=_!i-n!t z@kx7I+f!rXEX<{5KiGDc<7M3;uClSlK?^^t2G zh6c-*3VB~K@0H~8a3R};Ot^JROAF!zEXXtWM8V{IZ+`M7c-)JOi_5WeS=KZ$Hogsy zRtrR4W|I68&iuBcf+2mEg9t5>+BF~r#VcmOy~|%AdvHWs>i_B{l7v|k?ImMkV&LXe zACZt+ccR3*tpqP*Vs8GNmlAm&^6!WRS_udU!sFshQP}ukD}~9u?}F&rK*3mWef*b* z2kPe%&zRh!As%7Hyvz3mp=U3Vgs z7@NrB_GievGcPHLBFLft8BLaeZ}#cE#i@--y9#yx;Ib$mPx+%l9B`AMXloLqQJ zj4=v(Pd+Uz4eQD9?Z1EVorKHHQF=g$T0Jd(`L$x$&i&5?Wj7?Oev+1Z9<<>cru-yl;}R18XV z-jL|F3|}kyJTDt0R&Wh&(WCXI-1pd&g2+Ylx%qiE9v-+WZ`ML*Tt-Hc ztA@0+G#H%;>+CwDi+3SWQ5hMDj*y@f;6gK!#N5r13p4-hw_12yl@QOGN235d`Kp{P z2B2MbR@Uu=bMh6-`BjRa#81la+_?i@>HFa9dh~65oE)aFdEm;BJU71Jxr?6}=whjV z<7!`jKN1GU`y2Df;}DBW^c8XXV;f*;m&eW^uq>+X$iSgS2V83g0c-S_h^QzIBy4a< z1pyRq4X8X}6BnO^C~86yjjZL)-{0xv?&T_gvysrOt(|~to@dvfj+Wm8lmY$t*QeZ1C81UI@B8)bKuc%Oyg_#&WJ5x!b3E(!E_mLDH^@d% z5P>@z0&HbWE_v1O8N7M($B#9!r_i7SUOW0GytaGl{JSav{qL9Hc9O8$NG?N)4Wu@B z5f&=sMT{?c-go_cG5_h~$Nsh3d6sN~ft5SEL&>Y7azKSVE*2Iq6#*e(L|B+U3OlN|zdt1;85y2S()IQf|!ViGytJoFTP3u-ni|gEibRB z83#TiH1nyWZ3D>Rcp05u!-REn@)NJ;5`C@ zf*fRiMw7KJkfG$y0wU{~nwlx5FAV_Yitfq0Zn1tVG2`0tsK;E*?nGGAG*Zx^j)q*V z`o{Sf60e%NdJOb)4YuAA?~%raDI)E0luc#k{erra$_eL9g?=hn%%7#Do`db>h|thv zfIW)L2{)mUG%+%IYG{}NeJaF%`6VP;mDK?eLSrd!INZ0hGP*rWcRGyz&Uy)Y$K_vn z2Y~4!Vq&t8@+n&y3^(&8yp~;7riOGmwph+MX93^V-rk#FH(`uwiaa)bk<^A)f_ARv}# z#jkneRd#WTlx0@;a&?dYs2z0F9d)pY;tzHKEE|LpHZr0CZYAb@1$l39-^$aIL-l{R z>8S(%WQZSUNqz~&gyUn@*3`fazkmM@Si5sAL3Ux=aj>s18E$%fxQjgVcJ0PFtk6bS z2vQWlZXt}1&Vq3EBQ()98$UP@kAJ&9b-!OowtLzNX`%i%I3b1Z%bm#@U`%##@c=X^ zF6#}ruv@$d*3Y|=#0$2UhfJaM6c7*?)4taZ0O*;nZh@%N&JvgtOs=U9L{9KJXU7aL zl_!}C&OpU&4ET`T2R^nkWdbbCPMzuse*8hMcy+w$O5j5U)^nvz1d!{dtt&HyaEWPp zmXsQyiD`%C-=PR|SW{#HZRd5eY7RYo%2|04+uRJA`*)s*d1LW9Q@RhsWk= zmMJ>zt_mdFHin0lyllcr5Vlin&Spg{vP+Pl8an^AjS1;Hr6J@AGC zmJ=fVRHgioA(D>&8kRb&ni?6&To<$en6>ZYU-TTJ$}<)oL49)j9P*<|y+eN!?W%6|@>FNT6X z>zgFF@(VDc>95@B3hoCJF1y;J7R%RZX;qz^suUAYX?nc3KDFwj*w_H#7*98P|G{9C zo;>-4p`m9(>J*u(xq04I9vw4OQ>p7ef8F5|<$u8Sm=Axw-=D6aa{s;uSQ?yepr?nv zY&5T{OL5dp2`8NZA^Y(CSCSXv!KUyIdKR#6V+TBl2Rm9wY5 z-o3K25}tR~1_uXU<<`oC$d2v$nzxwbrqk5a1UFCxEBq?ZEdXGA<=VBlE?E?0S4htY zHhZ@+V$jiV;ql@nkel=j-?Rtf$ypVb04u={C*bxcn4}X~x5F~GoZ4D3h&jZv2fxZ{ z)1X`IXOn0|xX)lK=yO)9*2Iu{+Y))#a^mL=XL75VW_-jmJtQPxN78LW6~TS4a=!SS z^5_#n(WKk{*JI1vvt8_ZuCJehxispyQZj@-+OzJb!e^!-HU+{AWi{n)Vq!A4d#J$5 zd<8ZJ*l+d7G~iNVyUvjjU^D2k5@$3YE6AJ|97l%%(1oO-%uhWCL`lZeTVQF11k_tO zNVh6-avuRmzL*bU=qLnE2^=dQ!eqmVf|3seu8{Vd9wjAoa?4%F-=6 z1BTo1FkD)D3EEGs=#N}C#GGGP)@(;&0=%vg`;>sEzJ2!&`rL;IEDj5m180Q-UTn9f z1Gnx%6O-;z;(5F_5SruBP5xg~IC(_zKgDJc&iIi9uP;rvh-5k?K%<}Dg+C2-LSS}loCtHlcuy?f6M zxEvnVhF-L>KOc4M#F_DEBAF#^U@W^$rcTmu=kW~HgXXg5IjU@;qT~NNFCOWM;zJ*n z0+9|JlPaNpE^vKCZ#w((wX68~`Cp@OeTCr>=Zk2#_c`*_e$AA~S=zr?jsMK)W7}9T zyPo<(w^r(8BaM1lJlo1`mucX<8V?_z3Wr)gf5J;m$biqGxL^WOA)yTP_I}Z>dY6@* zEe9nLw&vlRH|ZK08tA#U%c|ubPh?{~dSD|w)N|(L+m&ALSC=e5e2K<@9F-!DV`h@Ln8u&?uGy!e%*JTfS?3*9U(6`W|wk^0}bkiMhFX zA?IT#rMXwX`?k(10d9pVSL}A`+AkzACKKynWwstJnX!B8X_pe$GzwR(WO^m{)TekoDH?9c$m`;oj!)O^xUrQ91=TTbXXAQmSI_7$~@}tAQ z6PG@^{Qu6_X3(D*btj6B)VfqbE&k1NgE7*;_+Sge&c@aYiRucm50skk%$*XqWP86| zCc5FQIbEc^p{B!Q+2EY^Y&^4Ah@?%;CQ!>ml8w6N>z~W>`?yRv9T-))Z2|-B(d=Re zlJTpc#@Ey5iM+Ia(1b{*6Bx6rZVvM(b?SAHS=8(Ps>lRtl=rzhC;WHX85hjzNk zpRo#Cpr(O31%MGj6O^@gkaPshwSe1+^UCj{N5{v9dS@m;|%ELLX%qT|YN3eA14_(oUI4ACW0#A%>>7MQMovN`73bx0D znx;0{+?#KY%NxMh$$q?rb|hg9ZS++ydSeVkFTy1bQOkT6pDHV4pp zI6?ukv8AS`n;`XKWo5881);vbGtDE$S`Yp}T%Gl8vvr=!EO`Ft6JY?C&*S{9SNk7h zBT&cO7vGFCK3TmaRBik*2t4Blt2A$`Ca*3P*C%$<-ZEs_^BXaWq3CHTWnHBrWfKd; z%_LoLoBdLwen5_VU-LR60Cn zHfrjDsoEh5sy`8BdbOMxhkR}|O>rzw6!VU*46&JaQSWy|{fN-H*6Xb%uI+5|G&Y*Vn&7g|IKZi&I!wH~?_+fe&$3S=5^GR}!E^>aL(_G(B-Af`x@| zseRUqcZ*`q5Z6qs{w%)a$rsEj-FOX0s`Q$kB~9K|{fy*e=KMriaizY6@;qqui$VIekne-Rca4 z<_Rd;G>1PAjC8Z*t!{42bw>6_Wyu&l4S5+f`@Kbd_1VQYV`;f*Zt3;8-5n81)McZR ztX-kPRSRGK8SP+y{le~Yxb%zNx= zH*c)c$&(5R2{{5VS6BKJGTZuT*+=~7i=(3>@B?Ar-*I@=@!YXd^h~IW{QhvBEt<8X z^5Dq;%_>DjQO-P6(fYrK;mRdis{uCc)2gqR_{C{Pz2}1q%)Z?z*iXL`OBcavw_uQ@ zt-uo5&!KDWubi!R>yC};7e0Uw3?73+LjYqY&>zf^c63lpS0KT|8VYvb2cqlf)iEJp z9V)cQNAbO%5L`H~@m0@5F;OH7mI$2*i+3JwBVjW2%J1yye7pIWyP93$@zJ%FO;K#! z#W8YO8u|Z|M~$UJlRsWc2u%)&uBH2FW8WWvTGlb(InIZAf3%lW;-Y;o1pV8aT=uX^ z;8(Zklj!m*9IBa_Z4+*h@*~v_MbLk~1lAuJTf#U>;^M`Nv3Jd5G4Wmt|AEtjp&V#g zpdJJ5Jl%S;$&i0|pF>v3VRJ$57t`2^zPe4iVwj*?B4nKBdOOD(3*BLi%xY)(v)k8c zoGeUOI5XgbPejSw=tcx*coR8q0)<*Un~+>qg*1c(!S3qe-Y&|@;s0*I4|Bh^#;NJL zM6B50o7mgGpmSdLaCCBlV%w3FlJo5ObAaBNH-z6Ap~DyFLPX4tFHNVF+nRvibVI6% z@7oOwh#zeG)=4eoI8D{eyIa*F=%aG7VLG6A) z%?Yy`PF=0tB~gn>ZGNS0V~EQWFY{+XO4+&8pd%7c#1HTppgS-tWs|^dQ&Lh<^`&4OV!0Uo0yQ?rVBYp7b6YU_vON51`z!be-2)|?6DlCb?X#djDdmpE*`0SA$XUDYWVLMu12b8{o@SgFN$_EX=m zxsYf|yjDh3ddMmfwdhGmwfE-iOg(9bP1}`Q!DV0XXO$$WXpEb{`Z_Qj&wwjy28k5t+f*lBq(243oDKg!i~~2?lp80UlQ8zjx6MNi25Q*z?V`2Nn?O za%E`d2i)10yUPA{VO%c3HEK-gzK}@P$AI|f{LLO%v(sGB837BABHngF<&Wp-nCDA) zP1vNpX0+EM3|nJ}u#xi%3rJ%It&7QcB{I5d2UbMvV2SaDkc||WMvQK9H(v^-7)ZZ9 zRex@KX9s#57B3I07X*o_(N zUr}T#zo-@26vY5Za6^q-4S^RN>P%`HUs5w68qFM{eK_)Dj5kkSsCU$IxXlyU926
r;9m-R5IG*#GkMUl(F+3 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 H&ZK_;Db+pY literal 0 HcmV?d00001 diff --git a/androidgcs/res/drawable-ldpi/icon.png b/androidgcs/res/drawable-ldpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..eab1fc68fd7ad531ac025a53956f78de8d4e5180 GIT binary patch literal 48558 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 H&ZK_;Db+pY literal 0 HcmV?d00001 diff --git a/androidgcs/res/drawable-mdpi/icon.png b/androidgcs/res/drawable-mdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..eab1fc68fd7ad531ac025a53956f78de8d4e5180 GIT binary patch literal 48558 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 H&ZK_;Db+pY literal 0 HcmV?d00001 diff --git a/androidgcs/res/layout/main.xml b/androidgcs/res/layout/main.xml new file mode 100644 index 000000000..3a5f117d3 --- /dev/null +++ b/androidgcs/res/layout/main.xml @@ -0,0 +1,12 @@ + + + + diff --git a/androidgcs/res/layout/objectbrowser.xml b/androidgcs/res/layout/objectbrowser.xml new file mode 100644 index 000000000..02a3f5dd6 --- /dev/null +++ b/androidgcs/res/layout/objectbrowser.xml @@ -0,0 +1,8 @@ + + + + diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml new file mode 100644 index 000000000..eba6becf8 --- /dev/null +++ b/androidgcs/res/values/strings.xml @@ -0,0 +1,7 @@ + + + OpenPilot Android GCS + OpieMobi + #FFFFFF + #000000 + diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.java b/androidgcs/src/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.java new file mode 100644 index 000000000..190668d80 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.java @@ -0,0 +1,99 @@ +/** + * + */ +package org.openpilot.androidgcs; + +import android.widget.AbsListView; +import android.widget.TextView; +import android.content.Context; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseExpandableListAdapter; + +/** + * @author jcotton81 + * + */ +public class ObjBrowserExpandableListAdapter extends BaseExpandableListAdapter { + + // Sample data set. children[i] contains the children (String[]) for + // groups[i]. + private String[] groups = { "Parent1", "Parent2", "Parent3" }; + private String[][] children = { { "Child1" },{ "Child2" }, { "Child3" },{ "Child4" }, { "Child5" } }; + + private Context context; + + public ObjBrowserExpandableListAdapter(Context context) { + this.context = context; + } + + public Object getChild(int groupPosition, int childPosition) { + return children[groupPosition][childPosition]; + } + + public long getChildId(int groupPosition, int childPosition) { + return childPosition; + } + + public int getChildrenCount(int groupPosition) { + int i = 0; + try { + i = children[groupPosition].length; + + } catch (Exception e) { + } + + return i; + } + + public TextView getGenericView() { + // Layout parameters for the ExpandableListView + AbsListView.LayoutParams lp = new AbsListView.LayoutParams( + ViewGroup.LayoutParams.FILL_PARENT, 64); + + TextView textView = new TextView(context); + textView.setLayoutParams(lp); + // Center the text vertically + textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); + // Set the text starting position + textView.setPadding(36, 0, 0, 0); + return textView; + } + + public View getChildView(int groupPosition, int childPosition, + boolean isLastChild, View convertView, ViewGroup parent) { + TextView textView = getGenericView(); + textView.setText(getChild(groupPosition, childPosition).toString()); + return textView; + } + + public Object getGroup(int groupPosition) { + return groups[groupPosition]; + } + + public int getGroupCount() { + return groups.length; + } + + public long getGroupId(int groupPosition) { + return groupPosition; + } + + public View getGroupView(int groupPosition, boolean isExpanded, + View convertView, ViewGroup parent) { + TextView textView = getGenericView(); + textView.setText(getGroup(groupPosition).toString()); + return textView; + } + + public boolean isChildSelectable(int groupPosition, int childPosition) { + return true; + } + + public boolean hasStableIds() { + return true; + } + + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java new file mode 100644 index 000000000..19e9b2812 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -0,0 +1,21 @@ +package org.openpilot.androidgcs; + +import android.app.Activity; +import android.os.Bundle; + +import android.widget.*; + +public class ObjectBrowser extends Activity { + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.objectbrowser); + ExpandableListAdapter mAdapter; + ExpandableListView epView = (ExpandableListView) findViewById(R.id.objects); + mAdapter = new ObjBrowserExpandableListAdapter(this); + epView.setAdapter(mAdapter); + + } +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java new file mode 100644 index 000000000..12a4263c0 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java @@ -0,0 +1,27 @@ +package org.openpilot.uavtalk; + +public abstract class UAVDataObject extends UAVObject { + + public UAVDataObject(int objID, Boolean isSingleInst, Boolean isSet, String name) { + super(objID, isSingleInst, name); + } + + public void initialize(int instID, UAVMetaObject mobj) { + + } + + public void initialize(UAVMetaObject mobj) { + + } + + Boolean isSettings() { + return null; + } + + UAVMetaObject getMetaObject() { + return null; + } + + public abstract UAVDataObject clone(int instID); + +} diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java new file mode 100644 index 000000000..a1e5773b9 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java @@ -0,0 +1,50 @@ +package org.openpilot.uavtalk; + +public class UAVMetaObject extends UAVObject { + + public UAVMetaObject(int objID, Boolean isSingleInst, String name) { + super(objID, isSingleInst, name); + // TODO Auto-generated constructor stub + } + + public UAVMetaObject(int objID, String mname, UAVDataObject obj) { + // TODO Auto-generated constructor stub + } + + @Override + public void deserialize(byte[] arr, int offset) { + // TODO Auto-generated method stub + + } + + @Override + public UAVMetaObject getDefaultMetadata() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getObjID() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getObjName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public byte[] serialize() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java new file mode 100644 index 000000000..c5ffc9d21 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -0,0 +1,117 @@ +package org.openpilot.uavtalk; + +public abstract class UAVObject { + + + /** + * Object update mode + */ + public enum UpdateMode { + UPDATEMODE_PERIODIC, /** Automatically update object at periodic intervals */ + UPDATEMODE_ONCHANGE, /** Only update object when its data changes */ + UPDATEMODE_MANUAL, /** Manually update object, by calling the updated() function */ + UPDATEMODE_NEVER /** Object is never updated */ + } ; + + /** + * Access mode + */ + public enum AccessMode{ + ACCESS_READWRITE, + ACCESS_READONLY + } ; + + + private Boolean isSingleInst; + private int instID; + private UAVMetaObject meta; + + public UAVObject(int objID, Boolean isSingleInst, String name) { + assert(objID == getObjID()); // ID is in implementation code, make sure it matches object + assert(name.equals(getName())); + this.isSingleInst = isSingleInst; + meta = getDefaultMetadata(); + }; + + public void initialize(int instID) { + this.instID = instID; + } + + public int getInstID() { return instID; } + public Boolean isSingleInstance() { return isSingleInst; } + public String getName() { return getObjName(); } // matching QT API to the current autogen code + + public abstract int getObjID(); + public abstract String getDescription(); + public abstract String getObjName(); + + int getNumBytes() { + return serialize().length; + } + + // The name of the serializer and deserialize from the autogenerated code + public abstract byte[] serialize(); + public abstract void deserialize(byte[] arr,int offset); + + byte [] pack() { + return serialize(); + } + + Boolean unpack(byte [] data) { + deserialize(data, 0); + return true; + } + + public void setMetadata(UAVMetaObject obj) { meta = obj; } + public UAVMetaObject getMetadata() { return meta; } + public abstract UAVMetaObject getDefaultMetadata(); + + /* + // Unported code from QT + bool save(); + bool save(QFile& file); + bool load(); + bool load(QFile& file); + virtual void setMetadata(const Metadata& mdata) = 0; + virtual Metadata getMetadata() = 0; + virtual Metadata getDefaultMetadata() = 0; + void requestUpdate(); + void updated(); + void lock(); + void lock(int timeoutMs); + void unlock(); + QMutex* getMutex(); + qint32 getNumFields(); + QList getFields(); + UAVObjectField* getField(const QString& name); + QString toString(); + QString toStringBrief(); + QString toStringData(); + void emitTransactionCompleted(bool success); + + signals: + void objectUpdated(UAVObject* obj); + void objectUpdatedAuto(UAVObject* obj); + void objectUpdatedManual(UAVObject* obj); + void objectUnpacked(UAVObject* obj); + void updateRequested(UAVObject* obj); + void transactionCompleted(UAVObject* obj, bool success); + + private slots: + void fieldUpdated(UAVObjectField* field); + + protected: + quint32 objID; + quint32 instID; + bool isSingleInst; + QString name; + QString description; + quint32 numBytes; + QMutex* mutex; + quint8* data; + QList fields; + + void initializeFields(QList& fields, quint8* data, quint32 numBytes); + void setDescription(const QString& description); + */ +} diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java new file mode 100644 index 000000000..3091595f0 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java @@ -0,0 +1,332 @@ +package org.openpilot.uavtalk; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +public class UAVObjectManager { + + private final int MAX_INSTANCES = 10; + + // Use array list to store objects since rarely added or deleted + private List> objects = new ArrayList>(); + + public UAVObjectManager() + { + //mutex = new QMutex(QMutex::Recursive); + } + + /** + * Register an object with the manager. This function must be called for all newly created instances. + * A new instance can be created directly by instantiating a new object or by calling clone() of + * an existing object. The object will be registered and will be properly initialized so that it can accept + * updates. + */ + Boolean registerObject(UAVDataObject obj) + { + // QMutexLocker locker(mutex); + + ListIterator> objIt = objects.listIterator(0); + + // Check if this object type is already in the list + while(objIt.hasNext()) { + List instList = objIt.next(); + + // Check if the object ID is in the list + if( (instList.size() > 0) && (instList.get(0).getObjID() == obj.getObjID() )) { + // Check if this is a single instance object, if yes we can not add a new instance + if(obj.isSingleInstance()) { + return false; + } + // The object type has alredy been added, so now we need to initialize the new instance with the appropriate id + // There is a single metaobject for all object instances of this type, so no need to create a new one + // Get object type metaobject from existing instance + UAVDataObject refObj = (UAVDataObject) instList.get(0); + if (refObj == null) + { + return false; + } + UAVMetaObject mobj = refObj.getMetaObject(); + + // Make sure we aren't requesting to create too many instances + if(obj.getInstID() >= MAX_INSTANCES || instList.size() >= MAX_INSTANCES || obj.getInstID() < 0) { + return false; + } + + // If InstID is zero then we find the next open instId and create it + if (obj.getInstID() == 0) + { + // Assign the next available ID and initialize the object instance the nadd + obj.initialize(instList.size(), mobj); + instList.add(obj); + return true; + } + + // Check if that inst ID already exists + ListIterator instIter = instList.listIterator(); + while(instIter.hasNext()) { + UAVObject testObj = instIter.next(); + if(testObj.getInstID() == obj.getInstID()) { + return false; + } + } + + // If the instance ID is specified and not at the default value (0) then we need to make sure + // that there are no gaps in the instance list. If gaps are found then then additional instances + // will be created. + for(int instID = instList.size(); instID < obj.getInstID(); instID++) { + UAVDataObject newObj = obj.clone(instID); + newObj.initialize(mobj); + instList.add(newObj); + // emit new instance signal + } + obj.initialize(mobj); + //emit new instance signal + instList.add(obj); + + instIter = instList.listIterator(); + while(instIter.hasNext()) { + UAVObject testObj = instIter.next(); + if(testObj.getInstID() == obj.getInstID()) { + return false; + } + } + + + // Check if there are any gaps between the requested instance ID and the ones in the list, + // if any then create the missing instances. + for (int instId = instList.size(); instId < obj.getInstID(); ++instId) + { + UAVDataObject cobj = obj.clone(instId); + cobj.initialize(mobj); + instList.add(cobj); + // emit newInstance(cobj); + } + // Finally, initialize the actual object instance + obj.initialize(mobj); + // Add the actual object instance in the list + instList.add(obj); + //emit newInstance(obj); + return true; + } + + } + + // If this point is reached then this is the first time this object type (ID) is added in the list + // create a new list of the instances, add in the object collection and create the object's metaobject + // Create metaobject + String mname = obj.getName(); + mname += "Meta"; + UAVMetaObject mobj = new UAVMetaObject(obj.getObjID()+1, mname, obj); + // Initialize object + obj.initialize(0, mobj); + // Add to list + addObject(obj); + addObject(mobj); + return true; + } + + void addObject(UAVObject obj) + { + // Add to list + List ls = new ArrayList(); + ls.add(obj); + objects.add(ls); + //emit newObject(obj); + } + + /** + * Get all objects. A two dimentional QList is returned. Objects are grouped by + * instances of the same object type. + */ + List> getObjects() + { + //QMutexLocker locker(mutex); + return objects; + } + + /** + * Same as getObjects() but will only return DataObjects. + */ + List< List > getDataObjects() + { + return new ArrayList>(); + + /* QMutexLocker locker(mutex); + QList< QList > dObjects; + + // Go through objects and copy to new list when types match + for (int objidx = 0; objidx < objects.length(); ++objidx) + { + if (objects[objidx].length() > 0) + { + // Check type + UAVDataObject* obj = dynamic_cast(objects[objidx][0]); + if (obj != NULL) + { + // Create instance list + QList list; + // Go through instances and cast them to UAVDataObject, then add to list + for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) + { + obj = dynamic_cast(objects[objidx][instidx]); + if (obj != NULL) + { + list.append(obj); + } + } + // Append to object list + dObjects.append(list); + } + } + }*/ + // Done + } + + /** + * Same as getObjects() but will only return MetaObjects. + */ + List > getMetaObjects() + { + return new ArrayList< List >(); + /* + QMutexLocker locker(mutex); + QList< QList > mObjects; + + // Go through objects and copy to new list when types match + for (int objidx = 0; objidx < objects.length(); ++objidx) + { + if (objects[objidx].length() > 0) + { + // Check type + UAVMetaObject* obj = dynamic_cast(objects[objidx][0]); + if (obj != NULL) + { + // Create instance list + QList list; + // Go through instances and cast them to UAVMetaObject, then add to list + for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) + { + obj = dynamic_cast(objects[objidx][instidx]); + if (obj != NULL) + { + list.append(obj); + } + } + // Append to object list + mObjects.append(list); + } + } + } + // Done + return mObjects; + */ + } + + /** + * Get a specific object given its name and instance ID + * @returns The object is found or NULL if not + */ + UAVObject getObject(String name, int instId) + { + return getObject(name, 0, instId); + } + + /** + * Get a specific object given its object and instance ID + * @returns The object is found or NULL if not + */ + UAVObject getObject(int objId, int instId) + { + return getObject(null, objId, instId); + } + + /** + * Helper function for the public getObject() functions. + */ + UAVObject getObject(String name, int objId, int instId) + { + //QMutexLocker locker(mutex); + // Check if this object type is already in the list + ListIterator> objIter = objects.listIterator(); + while(objIter.hasNext()) { + List instList = objIter.next(); + if (instList.size() > 0) { + if ( (name != null && instList.get(0).getName().compareTo(name) == 0) || (name == null && instList.get(0).getObjID() == objId) ) { + // Look for the requested instance ID + ListIterator iter = instList.listIterator(); + while(iter.hasNext()) { + UAVObject obj = iter.next(); + if(obj.getInstID() == instId) { + return obj; + } + } + } + } + } + + return null; + } + + /** + * Get all the instances of the object specified by name + */ + List getObjectInstances(String name) + { + return getObjectInstances(name, 0); + } + + /** + * Get all the instances of the object specified by its ID + */ + List getObjectInstances(int objId) + { + return getObjectInstances(null, objId); + } + + /** + * Helper function for the public getObjectInstances() + */ + List getObjectInstances(String name, int objId) + { + //QMutexLocker locker(mutex); + // Check if this object type is already in the list + ListIterator> objIter = objects.listIterator(); + while(objIter.hasNext()) { + List instList = objIter.next(); + if (instList.size() > 0) { + if ( (name != null && instList.get(0).getName().compareTo(name) == 0) || (name == null && instList.get(0).getObjID() == objId) ) { + return instList; + } + } + } + + return null; + } + + /** + * Get the number of instances for an object given its name + */ + int getNumInstances(String name) + { + return getNumInstances(name, 0); + } + + /** + * Get the number of instances for an object given its ID + */ + int getNumInstances(int objId) + { + return getNumInstances(null, objId); + } + + /** + * Helper function for public getNumInstances + */ + int getNumInstances(String name, int objId) + { + return getObjectInstances(name,objId).size(); + } + + +} From 8d7dc0eab7f5f648396d4481320ff8a813629c42 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 1 Mar 2011 01:23:10 -0600 Subject: [PATCH 002/284] Trying to get eclipse project right --- .gitignore | 9 +- androidgcs/.classpath | 7 ++ androidgcs/.project | 33 ++++++ .../.settings/org.eclipse.jdt.core.prefs | 5 + androidgcs/AndroidManifest.xml | 10 +- androidgcs/bin/OpieMobi.apk | Bin 148198 -> 0 bytes androidgcs/bin/classes.dex | Bin 12640 -> 0 bytes .../ObjBrowserExpandableListAdapter.class | Bin 3092 -> 0 bytes .../openpilot/androidgcs/ObjectBrowser.class | Bin 951 -> 0 bytes .../bin/org/openpilot/androidgcs/R$attr.class | Bin 358 -> 0 bytes .../org/openpilot/androidgcs/R$color.class | Bin 447 -> 0 bytes .../org/openpilot/androidgcs/R$drawable.class | Bin 418 -> 0 bytes .../bin/org/openpilot/androidgcs/R$id.class | Bin 403 -> 0 bytes .../org/openpilot/androidgcs/R$layout.class | Bin 449 -> 0 bytes .../org/openpilot/androidgcs/R$string.class | Bin 445 -> 0 bytes .../bin/org/openpilot/androidgcs/R.class | Bin 627 -> 0 bytes .../org/openpilot/uavtalk/UAVDataObject.class | Bin 1127 -> 0 bytes .../org/openpilot/uavtalk/UAVMetaObject.class | Bin 1440 -> 0 bytes .../uavtalk/UAVObject$AccessMode.class | Bin 1199 -> 0 bytes .../uavtalk/UAVObject$UpdateMode.class | Bin 1333 -> 0 bytes .../bin/org/openpilot/uavtalk/UAVObject.class | Bin 2255 -> 0 bytes .../openpilot/uavtalk/UAVObjectManager.class | Bin 5422 -> 0 bytes androidgcs/bin/resources.ap_ | Bin 140460 -> 0 bytes androidgcs/default.properties | 2 +- .../gen/org/openpilot/androidgcs/R.java | 31 ------ androidgcs/res/drawable-hdpi/icon.png | Bin 48558 -> 4147 bytes androidgcs/res/drawable-ldpi/icon.png | Bin 48558 -> 1723 bytes androidgcs/res/drawable-mdpi/icon.png | Bin 48558 -> 2574 bytes androidgcs/res/layout/objectbrowser.xml | 8 -- androidgcs/res/values/strings.xml | 6 +- .../ObjBrowserExpandableListAdapter.java | 99 ------------------ .../openpilot/androidgcs/ObjectBrowser.java | 21 ---- .../org/openpilot/uavtalk/UAVMetaObject.java | 12 +-- 33 files changed, 61 insertions(+), 182 deletions(-) create mode 100644 androidgcs/.classpath create mode 100644 androidgcs/.project create mode 100644 androidgcs/.settings/org.eclipse.jdt.core.prefs delete mode 100644 androidgcs/bin/OpieMobi.apk delete mode 100644 androidgcs/bin/classes.dex delete mode 100644 androidgcs/bin/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.class delete mode 100644 androidgcs/bin/org/openpilot/androidgcs/ObjectBrowser.class delete mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$attr.class delete mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$color.class delete mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$drawable.class delete mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$id.class delete mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$layout.class delete mode 100644 androidgcs/bin/org/openpilot/androidgcs/R$string.class delete mode 100644 androidgcs/bin/org/openpilot/androidgcs/R.class delete mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVDataObject.class delete mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVMetaObject.class delete mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVObject$AccessMode.class delete mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVObject$UpdateMode.class delete mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVObject.class delete mode 100644 androidgcs/bin/org/openpilot/uavtalk/UAVObjectManager.class delete mode 100644 androidgcs/bin/resources.ap_ delete mode 100644 androidgcs/gen/org/openpilot/androidgcs/R.java delete mode 100644 androidgcs/res/layout/objectbrowser.xml delete mode 100644 androidgcs/src/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.java delete mode 100644 androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java diff --git a/.gitignore b/.gitignore index dc058313d..c9478a9c1 100644 --- a/.gitignore +++ b/.gitignore @@ -64,13 +64,16 @@ ground/uavobjgenerator/uavobjgenerator.pro.user ground/uavobjects/uavobjects.pro.user ground/ground.pro.user -# Ignore GNU global tags files GPATH GRTAGS GSYMS GTAGS -/.cproject -/.project plane quad + +# Ignore auto generated java files +androidgcs/bin/ +androidgcs/gen/ +/.cproject +/.project diff --git a/androidgcs/.classpath b/androidgcs/.classpath new file mode 100644 index 000000000..609aa00eb --- /dev/null +++ b/androidgcs/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/androidgcs/.project b/androidgcs/.project new file mode 100644 index 000000000..c607dd2bd --- /dev/null +++ b/androidgcs/.project @@ -0,0 +1,33 @@ + + + androidgcs + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/androidgcs/.settings/org.eclipse.jdt.core.prefs b/androidgcs/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..f3fe4d6d6 --- /dev/null +++ b/androidgcs/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Tue Mar 01 01:16:25 CST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index 83d19e96c..7a96a6600 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -3,16 +3,10 @@ package="org.openpilot.androidgcs" android:versionCode="1" android:versionName="1.0"> - + - - - - - - + \ No newline at end of file diff --git a/androidgcs/bin/OpieMobi.apk b/androidgcs/bin/OpieMobi.apk deleted file mode 100644 index 87a15c5e83805a3bb48265a78f9bd9154813cd35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148198 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⋘Lj~+icr=hU5&=G=F4lyq? zc_{@|$El5D@*PFUS(puB3X_##=T28MB%!3$)3f}r>5y-~73=|o*`$>tS$!$#0Mw=$ z-p6?ye!bw1K0etHs>Q)Tp#bOqF-gn*(`&DTjnB#SAk|POJ=!M(Ac&lb6L{S( z;sMwT9Dr5o%Q{jlB>f+Su;AwQ$!RSG)Ry2souQzSGq$oY56+$0Bd0S=KOr(Xn6|Z7pGLX8Aw@49)y!hYe@yiVF|k71%PQ|L1v_;1tP?`XO`_MoGGg3 zN+g08e+Uje(={bB8(iRHJQbSA2+0@G8!_$+(1>QHUKIJ+n z<}Un@x*#wR4@5MGutY-J02EC*wHu1R@9t*iRryEX{)zn1u7~<3QCsA;_$~wM9PLbZ zmdpdby~$gO-a@O1-{6Ak_J8Q<=y>mL!K1Z5wda>!z*FjEWb|il9?6M-*EcrWWPQuY z$=UI7d8>@{Rw*5+)Mi>t558#DxN&i_7jH-S9!A|H#IIj3bMuO;8nw(m-o{5Jne-sX zP)GgKEJ_fi_-fxYn%AWG7|&CDnn9wb{H||^r`I!VM(F*BBrSz@zl2>95C3-*rT>P# z^#8?MVO{I&RVuEZ`Qr~s)J1Il`2PKVg<6u-s^%7qUc9((4U`M6`r<0hU!{uegX=>% z<&pmX#i#q9Xnp@P{VlbTa*{EX0TA1JcWG)LxLHH~y=-Tn)$tQ=RX@^*F1{*8SDN`} z*uuPm$(_qvX@mc6Q2j5F8V1$RomTpIqG6kDkL@SO2gB~Y+Z>R&X~&KiMl-wSsjg<} z>FeX;vm>wk=Z*bvQ@O~DsrC=oS|<(Iw6?qI6US#<*sXS{PB>;ed+4ow@Q?XWL7vOK zF!OAkp$~iAQqkHjzP$UPw9@*<0u_rfr}9))Tb(y=-t68Q5Ou2hGJ)?FeXH=$zxb)i zEiJjm#V7T3zsB-$6q@ z7#m+|+*STq)Uwd^-Xg0u%HtJ-?LTg&$c8Up{8rGyv9h+@Y2YTe#7y~P+N+e1{;x{9 z>bR9UZmKtOzWgocWIdOA^Q~^(^AQh$jFNVAfWyP_w^X;#Z|K?h3+Nbh&HhwB_Wopjvlub33L z!)d1cS>cnXcYH?Do@xG*5BxODUvjId{4w)MMfpmbsoGlU=ow##zuvym>cJ8UZg^*9 z<)X2Re=M3`ux(H4X~pvibfW$HFN|>dB=4FYd|sSozI;*}*Zbsdb!$5t&S~U4O5RDE zeCWx7xRp&?On5q_c---yIj&Q_ERr{xYiku}^;Jv07Tq2>fq>&GgY-;MXK;E5v!@&MH?NFv)n388w zCp^1OM6}`2=rdy<2FL#JQ4RIQnBk+=rS5oO(AnI)^i1c_J9$fsw)$DvK73!G<{ulc z^By9!B5ZxZ<}>3)ZH;du3$Whf`t`l^FSc(TVZXg|N1IVUN`4w>6e#HVhpYtwE+tD#f8N_=x!q~o-xqpx+B)^Nx6h55 z+P&I`sa>D^^tX;y4J|x0G)>z+d%bPvY=h9LrO)2>t9a4>=GGad_9N7n8lKn?*-}~a z{LNmUPUUr)@W-^mJ z$liPF=FT18{Pz8D*+*gTdbQ0DkAJ22y|naa;ayUcak&G|@2s`le$!JLUJ%+Ao~+@D)Gv(aA}<15F;o%C+&6daIU(Y5S1Q z`F(kBSAz-i-dw{<>xbjoPq1*8E1Mqpv8ihK!}?rzgq@vS_tenx-SLAB+xxAP_a{$W zYhS)HUJpd7EPbqef4cpmK@S`LrP`x+4xTeS3Om%I|Em=z4jr1g?&XW`2{B*giwX~a zyN6x)*}f)up~3d+!x*XLF{AoUQ(4jU!{bL)d|x;Jfr)oGU%YvLaY2nx{hRuW<(pB; zeP8>39L#r{xqLB6(%Id0`A>uVVN+Ghu0j6KA<1uThvi;#Xi=$KeYLjFxBa!?T%EZ# z?ZV%_jkD~Wpqd2h_&WBCQchX_mm> zDKE9M3LWd@c6qHb_1y}Wf0{u9WSq%q_I-{yhME|texR3T`@H$kfK%KRzWcT1qt-5_ zy9&efHe1uML;mx}_>T62-~$gEb;(dGR=#BIQZ)3Isl9i?uh07r@$O}Rt9>1LFRJf( zBm3U3`@lYenh##ZybKSv_U&Pyi|`D*?dW^qlax{<4gT1Us*&6W4UlA^uZ zs-85;k&;hd)QHPJj8zAq=(zBb3Ts~fyWbkA@(QHdP+k;l@)9`$UjO&r3SYf~2a9q* z?(Ua!kBAiIj@5!Qq(1nc;Y>OzI{y@fHrkg{KO#RBH5IW9Z!a%tj|V*h7IN@2t4D>U zqUZqtBpp3O<`^`}SVyU2p|ECBJ)Uo9~kV}gZm`Q{=h8>!ymPgK4VHyf+m!_HZG+~wt0~-=M-KejW zi%^KVLZ>eQs{}~bOOh|w*~qAZwvj29>7m2?NQM3#2Rrd$Ccx5iFtQxg_1&LWraq(q zu=r{t$AgrTS@RLuzd7BJ%68*oAgaY z4+vex)UUe=1;w&fZDH$TQq&{o&h2jFlE5f%u6QK*OCONrJx~jHVv2o>t%lXm*7-Gr#j`6Cg*Z+cQ z0U|0oS9`#)h}EUZsMIOftlmD_EdS`+d2ORwj6~6}!|otk7F@WRYE09QqYJ1reZz~7 zPc-WH+lv+yCC0MplzK=0zU4K>!e_jLQ5Fj7(pABPwj%nfADsLKi01~?vUV|&*AR{+ zJ5yObop*lIjnoMNY$9!P6a=HzuRreu8M8(GYsYZm082CFSclBNRJJ8-=2nsi$c8P8 z(jVsV3wwK1e<$CGB&D(e^ecOji$0e8zSFNUa=wl7 z7t^WVmi`n|B^6Tq_wkT1sK-{%P1<9mfSEPT1~mj>0i)*P4XPhJDVQHK!9vO16Ey$2 zdzU{W58RBWRG^XFW`B#;k}Wq#5O8Pkq&5_45y^nml`mz5N5}!i`wYujwia#@c-t+hPFKEmBn~dfXIr zYO06X4#D~c_eog&X9Aiz(iTNDQnXd`SacJKu?sAJ=>d|jr83ldGtRw0IctPYw>v0O z!N-2oEVZaciwNdW4xF6+1pA^J+~5^b$kH!Oy2*+}5kG~c=7PSU+!RqKfc~UcFSOkV z`!J2mqRfE8%fFqwbd-!3BPU1K=fivVTC*`V8$<$UOEV9Vb#!P^Q|?Azm;S?a^Lhw1 zcs~>U@AZm|)rU|xxlhm{3imcvNZEQ&_Y(@)1*SHE4uq1m--<3alWv$5oP8{1ypA%!nz&!UXN?8)CA zbOME90yUSe-Wn5g(056}q~tf-XR$LlLBqVRzSB1;NVqlip;$5!OXKQAF0cNPy*h1Q zQt2c8A4RLIdRF%@MT8OAL7T}#r%szTllM3Vf6aK?EC8r!-9Mj2$h5; zTR$8qGgR6l3}RqClQ>XqsZj5m|qUplJAYO>|U$LX^|?GCVQ zSSpA1?hUJc{-nn{yc1p;OeCdQKz9BCl=ffCWc9TGC%e8RYrE3bTclZ0EUaGKeg=1@ zpQhEzaGj`H<6Qh#s1{^G!ms(;lZZqRD@tF-jFFLzOM1L|;&V}GH8|UL=;-T7R zMV1Mx+qz9fp_5j|M1zg0|E$k0|9lN1Y-jiHt5VCZb-gvaS0knTl70v$D6Hm2n*aQ@ zWt`g~Y3oipvwERKIbw^}Y|{5(F#__h?K)7k^FGVOEx@FxDl%q2>t6jZSLot(kJ*(wNxXilZ8RVb5W`%DW{*FK>p+j4Hnz&xI0K+ zwR+#-7A5VgVd8|O`mahIoocIDZtB`NsUOr-Ir`Xu9;!8E9BzHlzt67nKh0D3NweDs z4;)|5-|TR&2Xb;zHq{|YnL(oibYN?!FRfqIr1lD=Opn5#P+z4J;qi{Hu^`$TRrwN# z>f!3D(Q$F`U+u8e+8SZ3=Oh_L*Bn6Iv2q5!Bd1q91WzDtp4E=g*12*Jj=3}gcy=!& zfdren+LSO6J!xB0Vg37eIT|4LEsN4Y`Dzh1RoEH`j0`Jpfde4PW!yK?46&)r2Zda6 zr(5V|s_}je*8~Jbb_aj4k9GKM%X&?2N7d_{CPEI+?m3`<%rHsW6NwtzdeM-;q}1X| zMP;~}UB`JoKA-AGsVQ`Zadt~#)-t8prR?KULv@LM(OnmgE_#G|i@1cLh?$CdJj8A^ zo^AJdAbcTxexSZ5{%Eb5I6r&QMgekLri??Jv6B2!3iMCQkC%>+kCprm`tLZQ^aZj| zGZPX&#WNYCIp~|!RTHBm1KSUnq3)Uun-dQwC=H^k+e&o^8`m`8m@w}tv0|;F?8}lKm5_o_J&eYdxdSME?x2_Y%$x*hR1wJ zymry8>rzF7h)c^9VKMX|8m#m<<(r*)u=iM&0BLV0tE$iIX9RS395fbB82^A(ty5FS zLtOr=a=MT(j&88WRJp>Ij-ny$_uOkX=6ZkRoLFNu)YWjC{XaUGLDRthB0fdeA<8;T zdD-0(^n)V_6?%gxQwwBDkdcl1@^m>ZU62|R&Oc0jWrummzWs(9iBbgKtAp&R25PKN2`SnBk%&lx;OxDNjOYYQmwA0b2QN5Cr@}?&(cD$)I!yooM zwSL3E)PRJXCkN>ySb=bC&`L&HNaQQP*dcnT zG?GCS^&SMB3{!dNzf$>`2m}b^=y$XI11S6<@&eQ4G!P`TXC;x8gB}px*ngtY@SjiG zJ2()S4i+C4tmj<6d09;!u~|C(?S%$J8=+*2yxN4JzQ|hQ6sA8&yBYxLKW=w<3oU$b z7atmFSs)szP$O_-ORu~|DU6bQCarL0D-yBm*Dcrq7_cMx8jeUN3--mwWBgB+VQFd@ zm3}N+)G>7&ihO7~K7?Eml1x+}E3Mc!gFp*GDg-D4b8~K=#ic%f43cf@#mqEmmLsvP zvx0xPx3nNO0Vre#YZ@W}c`s@iz8rUts|G`-qmH$R^?0Q)g~twhz8*vv2OSVv>GU?w znfioZWCe5-@aSxSL^2Gq3HJ~;p*o4eI1|+h)%serrXVtvEx_|&{C}hB zhog_kB}HaB3J*KEErL3L?T_yiC%$=+O*dDsI0xi@0M(j(8@SEj>ODk4PhFCu3d2Fl zy^#98&p^QPE-n|4g(`PWiDoKg0RH2ceGCDfLE;?-%91cTB6{noItl+?t1AW>de|no z)~y-&_ke<0Te=S$ zbs<+naqtm)%LQx)dODILv`EEvZL>RES$t+|?sRPCi9;3Q$4+Q%zm;b9KyzaA^vt9P zYZT8`RY(x5HNDt#f?^7yM7ku zuG%{lJ@d^AH!NRO#DBl zwM*4PsuVvR%n96&@CE3d0M-W{G5FiswEE3#OfW1lz!ws6ai|WiIKjAZo^+0|O@hxZ zd2UQSz40)f(e`sHdA=={{vOBUOiTZ8G)4B!~WJu>A3m2sH~vAVBRCI)gx zR&CNhJIiFre@{|IW>jfL-0sX7+k*=m#i7TGGYG{u$P8*LQ-7J&*%;t#r1$X#Qcaad zDScgW(a}N=+leaEEaOLpFGP}DqSGtg*kPE%#W00OY9 zQ?Mx^f*k1jC27(@QS;x72xJi(aPDBs5y2R> zB4ys-eFg9+RUFGq7ZJ$Z+>EOs+2pKPJU(e|80%<-}_?@U+`4_M5isBLZmWbS))y}lz=uXih>XxzVe?xAA}+j2SFsjHb?wg5IeyhVLaK)U`tHB<3x)yJA0(S3>~HD5GWnAy zmDwv@HSi(QcYczQuYToOJ*HhF#*up#lpkz!(|uK)w?^w!$b0?%$9YD#@9!Z|w~M12 zNB4H)7yFS?BI<%yMP$QQ@X?dW1X{QtMih{KaF+xGMQ|;Um(@qoB}f*L-pP@;_p9^o zhYdDg>d(@=ef{+am}>J<_k(Srr^7E zr9se6m z;OcK)J$JPZUIC`@ifjVlEV!bnzw@5LJ|c|?Fm)=HFh5gidJYHg>_@HsQllHLb7qX1 zmAB;$1DvK?A4aFIAh84?{K9Xp1Hz_)_RitfnOkH%17bVfETg)FP0}O%TaP%8F2Qc| z`t$8el>4;JYtDUsgGoGwmP|XEBD!KOR}Maz`wt87`qOO>ou`j)_13y__FA5+GI}xghD$@; zeH~l-E}a~=tw++~Wg&{=2tY&v688<10C0~mSRs){Jl*JXnf}ceLH{fCQVdPO#yYa} z%@y{3cRl_66VCJF$qc1ol9_<1p4Ja6{Rg21p ztcm8G>-w-Ah?P0hP*miNe8-L3GzI6^#XXydYkWjRdW8BwV84`Kg8R7yv!u@gULy7f zDynaP3bNFS`}#PjbMT4s*r-P~wa`Ecw}0r*ukRq^0v{=B3^RzT}jXF?Qc{*bZotKG+XV% zJrbC!#G}`-_22RJ{7}!7SrhZ*e#+lS_jjGnUD6fST0D_eef~J9j9f|XwRCReZc}ZH zu}Af0IZZ&{-7l}T9dRrpdLXS$(CO6@bpn( z%c4(Cm3+0ZbYlYp*6l&Y##g=nSIm2DU3>a=(_N9JbBw_W;YYjnj6aGchx*gVclNgq zEvz%DuS~I)F`m_UzaATFRLZk!P5SoIt56L2xzc=!UfHkix>&(OAp2>m!O?MXpRtOG zhXd9IBA!aFDq3EUzWxYzx~|dZ5qq$wwz7Uy9aPhb_b{A@yU6_9GSD*0+R3&mzMjYM z-G<1cS;nubjib3l7^mN_8ym@gSmk~^$42D&9~|d%1#2sBSH%^rK3y*&u8^3;wV+Cy z3PTM~8sVx@QyvQPb7S?v9;MH)e@SlviKL#H*(M(oGO2)Gtvz@u>|9&|B>c{#j5llC zIRAzxLf+_AaJhS1n&qp?n-b*pm6o;fXrKSmyS+_2%TyV+=lPa{E$Zp-H4nvvh`G3up@QJRONsg&6J;xl=4` z&eaN&qW)Fg`rs{)LIim^SuiPh$rCTCF1Tk8>{=yZWXgOoO3>an{nQEP^{*;T&s|-6 zAR}BVcYi=r3KBr+;i-Cw(@y1wJ>TdbD@-oUQ;d*$;O4$*x37+?V`D}a$DaMPDQ{qR zN#zs~G-;IsiU0mK<(50cq+UY`4MIBF;tD<{^yrcRpM_rB!|XeEJCHwIoDVm<;rd26 z%l>xyscvSkd_nb0hpfll+l*35^ImtAn{Pg76>>k!w{y-ZH~Ol;4#S{x3nq^a77E!` ze395)pYyE5+HFpUbtII9K>@TwVyuR48)?`<<(Yw5XHwd;khGgXQG_aWd7sPL%6Bbi zux2wd?pU&+66PbX#Z*{aWUwx~i{s}_{#4}vsRQ$8*#oMd8fDtn99EegcW!K%Zqa_c zqK|Q@VC|U!<}{AaY?-|;g-^_9M`pJ1Hf8>@jxy5Z)-HIvS1!B%4tX)C<^Y&Q;VYq_ z@D$QDM|h>TUO$M6@d)PkXi%c^@B28fLeDi@^ zph+-IJ3P!wrBl5n%qwU2FB$$F+s+#qT{nuy027kB;^co?{)d&oRuzw=$eT~*rl53k8Sd85tXj&yv{ff=q z_5TiGUFG(-n{NFZ!irz?lv*E*Oq)5603VO{QF${;DCmp?f0K3V`5V8ze0YXbOC?!cm2eqnZ$!6%e>k)v(Mk8uskBej)cDzJ0LzQuJ27AA-(V~243lVM*=fApZY zN@HLLQ$+P22ju@gw~_DMwqF?C&0T|2wS zICNh?gyI0Nu;1|JE_hbFy|Zp?b!EJ~SWl`byG`1*ilwBiPMbNB`}jy@Oiy@4kN(+? zbd>^;7+-6NDkGN%`s)=QccuKbK9~_^X%%|^tBUaChTs8(p2khcQ)m5TxF z3YfQqp^1M&I(Fms{Br%HMn)C;$uE~Twmupz$*77s!h3!9Zb!51ieHgZPc%OiAIY`< zqpQ;NGBbr0or!gvipjcd9p`^Y?9%UkYV>5WvCy&7>DGz#74BE1^837)85FueNHIJw zJ=lMiC^AXy*r80Dnl0?a?f?Fs3aAb-?F|a5{+LTc!H$uO)qNUkan5YXu3h(@FIh0; zZQa$B)!*r?T4k+sdwa6+hnpuz4HM$KFLQIxent`57BPQ?i?Qd9slB`z^T*&9|m_2WfVRJ^}mu(u;r&bkd?7dLBC-; zDWE)%+AbF%>`7LY>8h?6ct&ScyExbdo(3II*E-ow=P_gZx z)zg7oEo2VqrMtWYZHI3So5mdfIux+5!`1!(GYbJ$fcU_o%0|TMNa{^B$qWx?CKWi1 z3T|p}U2!cWIFrCdBb`xknsolb5)szV|&JU#pr=RAOgh+3=BOTWsAx<*d7u~*)c$BjwmFADk+qp9Ijklg^=)C_hUxZ_xZ!A zW>W#Pd)287J8CZFU!e{02CohP&F?Sle?Nt~$sx|P z3hPg#3<9|E6na_E?&)CAUIMffIBy2|CFQ-NeUDP(^~K9Kgh!bXKXI_Bh@d;p2l{F1 z)siHTut~eyhf)=Yj>sjSIs=mZ2h<3BPq))(-o`tFOeV1+Vo>efb7)o&6DiPO4dUNSo{x*Z_C1tsz$uTJ&E=tl`uh5p(9cFLN(xSlA3FWC zeb#L~0r%Lj?N=Cr1ll)v~bt>>oe1*JhCw z;e5y31$=n6EEQ6h${*(5ysvDDTgK}@ayXRR zb4YqljXxCG0`uUqRBg=WG)X@QKZ&`0-s{&!gH9`OWD~V>RzT?ML;V>bj)g;|O^s-95MnlK!();&Cn?|FuWv1SH|Fgxmt3Nd4E)$e_ zT@Zjg|0vo%KT6C$iRz)1l?r-Momc+yZG%$Qi4(J2D@k;;$Ckp+!3u|H;d*%$V)C+c z`B;m4F$OspbBH398n#R-x}UG!dh<-1H)rlDiEY{{%B37FQ;O^2f{K)K;EPwWO#ZqS5*>Vo#((3P?vj-%B0^OM@Ewdl=a$ z$?oBt5aZH&ox@C+T7b|!5jnR9{afe)qb-kFGmI{j zkpKP-lr<9oFANrzH#!^v)CjY!ZJ5Hw$H(XV2*-$`2^FxynGo?yIL0@=RCD>!I^{uB zim+%fRDxez$FK3%KOE8gUHqk$EF(AU2HLhVx-V}zcI;#(jj`BjplIPsY0wirr*wno zo`4RQ`F(5kEGTb9Bh@>rwssB3G(ng7B zF#DihtqlC@N>~A!u$gl+GMflSXaEBN z0CEQ(BFP3(w7{M(5fhQTs68=oQ9?8Q``c>j^n0oNcCYh#WyWZ{MOq$$vtkc=-TvZIj^ma4H0WY zW{m?jq^VB{06zT_Cj{`?7?)ikBl2~Vu^hbT8R+S7@E-(F0~xp>q|r4C%_1r`3N%wSnd}k3MA{;@UkYKmQm3MsQ1_wrEJ1V%ke8H=odnHGG}#Z^+u2XDDSL0r zpX?J=>ETV$+MA=+m&7jI@oo9(W}^>x0UVF(H+sd@*r4xv3Jgcw1wwC7(CPO-9J3*j zux^7v9$ym?rS)3y^i|SiM4bUx0YNIj{VV%BS476>oSsU&03#!>=)sS>r&>-XZN6l4 z*E)*2)L=4c&v|3p>{&^>kZk0}IJ22uHSwaMJ3zWU1QReH?SvDRs9lnk4^@s1I~M-Z zR7^O@tj$3hq9>aL3j>L%2y!;`hh*DvR}y}{F|xT@EN?i_r{j;{_tz8`$X9QQhy6^ z;_~tP$7@4yxN+bIKWemP3xNI(sVKCiMK_ixPYuTU&1>IvpHGv^9=)TN#lM*^pSG!$ z^)UBi0;=?igLf*Cw;0<1tgGJS!1k=BJ)OIAIy#}}S8gK_xSM1n5jqMRBi<3pDG+4@Z-|IP)4x7AYoi0yTnICa? zcS)xc6%*@iy26~8l@&pw-I?_)obNWD--n1E`Xu&ZgoaG>*(E}3tSXvMDhy!lo||#f zWiace3WM+U9uC>W#0$cB8`$5!B&3=4;_RBi3^Ie59f{uAdM{MwQ-kgMG}0KO?>HjP z_8EpU=Lna5$9Ntxkz3Kx6)WBgSgzt#=*&nlC#QQ;wkg@8P0iN6E2TZ#x*xLh<^#KN z@BHc53TxtD`8214QA7X2g$t@r*BpD}?pk`M;iwE8(#Qma!6&D&sYwJJ1QaGwZt?&* zIyh)z*Tk8a%wC42>!>FBo&~KxlI!NgXv;*SCZ~EH%9(|hv5ZIWzN@_m!+yKQGZ8Ko zYM(>gG4b`d#6?GnVBJ6?ZtuRo&sjZ-x0;vE!)A>zuafdrTOVz*!;ea za@(F|Q=<>ZMxk|h)MA6rSILckS8PP+r!Gmb%RKX1#is(t^-(si+08(p5qKoQj}j<> z3Ke{tgtiTZQ~oGXIao6M^;EDD_i()fv`;$v1;U%6q5WzE{Ak0oW^}7PUi;>hZp}q111F+I{k-?`o!Z#MTh~ zB~Qpl{0iW3gd2M7L~DhM9wRSp6~QeKT&v!KT$D6|MX}ZFM|-*P*NS(tZRIUXb0<@- ztJR7I3`@vO=|S9)%w5U%kZ3DdKX#cjAJPU6Hf!l*mlyTgpE=Wr>Na^s3IO3MtLJAW zoZh;v=1tKomw7t8H)D&q`+<Zp?nVHt&C&soga>d&}G1S zhMWo1;0i<*xX1yCe3LlGU^l<}66kPW7JXr}OTVRjDWXcih8Y_h;|#txG6gXu01r~S z2X_hk6)hcJ<#KAEEiE(UHrgWxd7NzAN?I|_x*pSMipBof^QX?gxf+?YLyUu+Gj3*8 z^331A6R65O+%pdd5m9mlhA>VOZ{G|9u^Zg; zSI8Vq$eOl4m;)Cf=q|IbW*Bajh6u6krI&rN5MX++MM~;01}`zNMf;S%&9uxFLW)FH zQX;knKJ`%zuEE3GP*kE!>v&Jg*-zwGajD6p%UT^8kfQ*ASQUf{hWYGHiCugPZOXY@ z9QlITWHRRzyA(O(Yn}42sWH4Q3;N3nbRXz65XyvUH4fzX5&ibj=@*zm6EAC|-6)OP zHyRrZK#0OP+mTC|vf&iqcmTZ+Vo_x$Hy76zT>h?bV9g~M-fLGGby|vh|e5irLobPpgM)6<^y_e+Y;j7c`B| zeG>Jpu`z%tDza;08IAtC_VggzrcDhvgGq^o)hV)LM|hi9Jxogz(fh{odF-*-Qww*5y>{i_J;gCS&ld#iAUIH4iRdxqwcv;2F z+khw*kjx%It+WIOsu(>J>DVksg=t|058CxdhRea-{lH!BQ@H#Bva+ z8zFij;s`Obs;CC)D%q$%#xk*HUXIbHvtbKg*3Nwqsgqk+qXHjx5-c1LLA617Ohmcq znFaA~B9K#bORx)3p%GUIv;`hviEeu35l)&|fPAfGIJ=SPg`kq#*S*02DL*VOg%^J@ zq^R5}*S1wONQ=M2*Yf7+1_$5D0l;(*uHV>ANr3gJtu z-B-J2*%djrp+wT5duiMhKE?-xnl_m#Q`;nfUw|DL`s=Dco`=FQ6PFgJik+|vQ5w^x z?FZNL?{xaIvgXxf!-m^t$wem!Q08}xVDv*X&HE6JG=WE z$+-ITcWHtpK+b`}jDJdpFzV(2NEV=4Fb0Q)LTg3h*L+KU;d4zMTHE46ZRg%4YKVz+ zQ78IVj}kMoVz8{YPqyR>d3wD#v<;jhPOM-^pj2#h-|O$z8Sz$Jfye`qkj8(6d# zP?*AFe#YM?^cA=)z|IcPidZ!uos@Sf8K*oXrw1gNusXH&OC0MeKP`C8&4w*A#jyPF z#p|2*BG`yX?rgPqisBj6g19Ri+g#)@c+S8&e~gd`k97PDIZ;3+JcjBQrLC3vr%?#B zYc2W|iu-pHJfYr&W|VBU+jrmz?wN1jlxv%D(^7&(E#Ips<_RDQTaq07={uK<$h2r7%#q5M5W0#O33sMCIl6W7r?FHMYjW;QRB=sjtKAWjC^N9A~Sn zY@O_cq|0kGVkJ+1t5-O!?TqGBERio>f1F8r*>h@X%2Jv!v&u>;O~vZPhnZQ+JLc=p ze2uAVj-Kr2PKYR~ZmxY(U2R)X#TDD!R}3s5>LVCrD(xTK?+!mP;*M={wrDc}=55<1 z`9rQ426>oL$Fc-YF058#h}yzmld+b5em0eUmni3C-%iLdlOyKP<&}4*j zjpL_;636WR$-;#<CXSW zrFJS&C!r*GGMw=U42wu}d5eboZJGbD09&`ZR&CD~=Hs*al+cOOgUIzQ;visOd8pj_ zdvkO3(q&WL8yh=-+r^e}8bLB-VHHX9a>$~bEdPQo2M^@xrAw!ZfB*mrx6dqF zET!j)3RROa+f{L5bs3i||Ex2IdaI4_vnzJ4gD?b)iUk5rltV zOlu29Zeq5t3QgfJ zAVWrE-xi02P_7g|tN^cDk2Bb{DpW>Z@#%c_Q!PqNyp@f~S6GYN2z`|BfS@**etVly zM?~+#jEu(Cg}GK@UVrn4qs%^0e13N5hQFzrGB1P2@fW{WT{P`vVD|O6yzur^eToP_ z|CPimAF+1EL8be(yLCDQ=sTId&_NJnuo`2^MsXnJrseIftgR-9<21KxI5oGJkL2Z+;(bMW0k4+HT}r; zW3M#Hj=^|52?_@qULogtKlBkQhUY|9!qRFross+O=}sir)h(w1tZ z`>j*&WyZYbYZvs69BJq>Z^UZ@8i~9%h^J4T=n7eNf^zN4)fFpOc6RxwP)E;(ntXJ- zAf?QZ8`M&waCvrW$_@frmhKZjw>tjzrLlWD3H)MWwL<;xXnVk=eTpFfY48&+ zj>pKpL1Z9{tfIN^g>$h$QsYOWMH#2=7^zc5$Xj#~{IKbk{ln`#zT>kJrmS?EVM7EJ zufq@_0ClWCLW>_g+wq8mS=GY%@eCnX)zH3s-d;|Mil9;z4m+bO&+AX~T)1}um?$DQ zOGx>Gm;IXh$A5v~;Euw29GMTS$-7t-&EVN5w0a1x#Mo@JCtu9{v)LRDxBmX9YJR0w z@fm8J6&&0LF<~K;KLS@l5)d<1b|KeHCBAYJKT&CJ{cQV~xN4d3*I>4b$k#n}=?@T>dy z7qB$w=htoAcM9fd#tB1nWTiUCX#GoP^H`8Fae>rgL#myvE$fc~p8BW0Knc zBewU9khvOJLEQbznL*6)6LFIlz46LHFwjDH^3C!&eJY)o2DmJ}3X{7oFZ^wVH&?}d z#e%BtPv}NHaqVv);9)=+Zi3ku#TZQUMMO&qzg=^)OpDgzI1wXzp|n>gA|XMiVdynf zrhkIgQ=eThz8wMc!Y6Jo7nehXR)N(?INME48b7@go(Eu`S}^9Si`k{yb1O$hb?T?> z>D-IQ1=|mJm|TCh;{?G>4|??OCPKcq!ozp;g({-Wvcb&FQa?47K9O8TRPp}NG(QWg z`LCufE%_JIxmA^pW?Bb%4qf5?>9c&(#}}vS0sEl0iI-qR_~i8OFnMBf&Re5a{Qfjv5eW%>g0cXf zgwSh+w`~j7rLb5TY+U^7Zv|Rry~4^-)up+{7v)706x3Z@UI6a6f`e`=^lt$YO^Cld zVMG|sR11m4XUI^@5p(WPa_TDd7(}1>+`Tex@0G4u0Tg z88CWc@K#mJL0*QIGR%#L#s#4mlF58q8`x}gfl_`{wP0HD3pF+Y$yHv>j(l)(1Bz78 zA!>3-lie4>zaQ^!?EkQP5UxN>_{8QtdrYu?S;>P^+R^aR@K2qmuQ(m~C>Yh_SE!88 zUtUx!!D5G?r(S!zW)B^`Pju>a1bPOc&}01DW6R&(VGdpM>%fl;$@4R(cP;ZM}98^q<6ay1wU}2~62~nOX z?k;MNqHH!Fp(x@e$h%!7b2^bW^MqEQSX&y#xgn&=sXeFF+!liY2q4Q^Qa7SiJ%cp( zAtBXr$T%K4cyMJBMd3ZW3d7b0TJabnS66(Rl)F$ zGe7Ok|HeQbhRTpgD-a{WTvfMoJ!{0EvD)%fc8*G(&%~LsFEydTd|})iKAiqa6mE-3 zVNi7_9P%$s&3dWIeippJfq@otJUkT;EP!Y$A(=v>^Tdo;hEk&CKYu)$_g?DL#4=?~ z6Oy@&l& zlj`aO@8k?+v+R0Fa|b$;-PhmUL*}!1qT}pX$IY!HT(q3Ja;1Tbi=;o^b`g`Bu~|f8 z=jOoBQ*q;0l=fe)K#TGv2`v3jvSA>9Q`dWv#+2=pgcuhX*1oYY{rLw-%S2UYdW!Ga zgO3z#4hjirAUPj4rv3Ctcc$^QJB8sGF9Y&&5eLyxr>e0qB#TA01L)* zYcFdnPQ6`oNMB!tr|7k><=%~pOJTp0i7aog5{I%$@&(85mLY4Ha5@%505?N8>aFt= z*&s6>$;Q0h~@vW*do%$I6O z)5z~y6ayi|>V%okse}x~;h3Wg2UI`b#4>gSEV>A1)4n>lK}%nJGRhjf?>y)!6E8u) z(;}5Y# z?FznAln*}A7XN)duvskrLQ++K9nw_i zsl-p!E_##*YXGJQ5@&3>*2|2r#e5Ts{<&U`Q{VYAzH871uZ&-z2u8fKs{4N87s));h2M6il)vTB(G-O19`Se}E$b3-Bu3PwDa;%k9ITDo z$ZFR05RH!<)nBPRyD{ZD{SaIdSTDD)H2>H-_oEe7=V3|~jBh1OBgt0eITdwGH!6?T z)7|Y|a_CWvy&1f$6S`+45JL1T80dl)4{e?f*WHreCgha!?K>Qvbd5)KytJ{k zUHN%h^eXv2S$IdKq457-tl~CDF!iifWUPOH)Pr`=cb9h)ZHmp;^?jlPK za@t2!RT+|ac*Mya(5y`+ve*aZ_tUKQZlw62^j0GxJ zcLjrI33;hXVeF?bnVLk$a1>czxhTLG1RAC{ z&EorkAt5$h8*zMoz2W*N($+)RI;7DlNzbe?N5m`*`y~J3XwH5*lL#Uaf+zU-c&K~| zI_ency|OS;6ka?YhUU+NIi{)^o3D)Sl&W{BtFEq2oDpBvW{whlaX(^KNc#LrXKQ>< zUBv_qv!>;2r8Q?cyx%#9ZAFdK80jSI}@gZk(aMn%DqwX08&&xDl&ut zAy1)Z z*C$Bi-Ov{F^DQh|TtUKj_J$tpe6w7t<&v)4kiov1qmQHFzFdpWI?(Xb+F%n4LUWrA znW&Kx8xyPhfZ#oZewyytb&8s}{Wh*m*(g`*N}KrE_Y8?$t2{dUr@Va?<8>{mcf2|3 zqLorE0U*;4CSiO8PWH$4lB?t2>@zSO^449v0!m9i*O%m=0y(X*FB;1iw8HB*yxHxX zV{GZvNB1{V=mXb|!_`o~o40v>)S4{-U3Fmh9zb852;*6(ur02g|Ht< zb?H3Xjy>Vrz|o!a^5qcFO0iEr&+9W+u&b+!kQ=6_Yr+AOsFjR^6@C)DYztrNBo9KZw^vpBtxZj#b4MnQ7al%3 z%Y>D!r}@EdU&@99nH~dWu44(2ji=&I*N={l=CVv6=wJSKT;Ac!#JI;6mu1g@xY@kr;|I3$PG(udr z32hhv!?#gKpWUG8lWs({@oII^lR3ka?2fZF%kV zAC7J@T5xWE-MDLu`hrG1Ckk;o2K3&T2%Z3V$B*!{feMYXuwcpRWISl<$@t+aWR~~C zZ);_$32bryPru{%6{qJ&w@%(F}+D%VqeI9Rb>l^hcoZ!g5Vx@t~rN zMwSHe-gxC$cd~!I5kCv7{3U-Y=Ogy{z21*P(30di3WtxQ=#7&n0qGT2IPCfB(sM4Z zHgVfsE?=d-%?GG`Zx#R2udSnFsIR|Ph^F)r0uRQ|t^5HzCanS7_er3(Ea(r3lczZB zGpMCX;h~AkQF#ujs;T`lNSKNIw_IlUQd4_n#p1W)F;P4O6%@?=kD?f-GwlEcFEq&) zdj*eD-2cB^%l1QD9eF%Zj}xZj`Rb^-CZAi4N~f8Nx{V0&F?feb!(d&0xRiw~e;{Kt zcnna)`!O#56$XDQ6z>bD2u{I?fUwCBsR5MSFKhsT6YT0D9n!d@qs#~Xn^}RjK_FuU zCW?_A^}P;^ZCO#!N|tpFyU9KxuLo=v`l7!ZB4W=J7!jKz3`Ysk5o{0N;T?_#LUoJT zRVW5qAVEWg`9Fi0 z@$TnQ*w#iK)T}oSinG6o`9cPAC8BlsbYQ@NKHB=Nv`YD6g2<4L_YO4#$bfn{)90q}hQitQG> z7d-Ls`o7IkI*BmbdYIBB$GIBbn^#y?LJp#+Yup{Qv(%ESYx-fC0_cVT=5?6eP?u8_ z_)wnXthIwa8p<_v#H}8;mBD&G9TROb4Pl^oad2}RLLLn$Bci&5NftE5s_ae#?1t<+ zo-uFsbGd4z|BBIa7mW!1fznaYu?jilamDBi{T5LO$^a_M0;+< zGKzvPdIPs$Innp&0h(za0Y;*B^ONo-{4RqNxAW!^ zxSWSDNA5xuc?rb!;M59G3jx5XOw*9aFg@0Ce_vKcIbb_O&xAh7uM@+$nEsJBNRw*-SPC z&Rr-)5hrDI!HVfne{S0J6nlrv7g$(W07YCe&7}d_+jyUjm)ygUQ-FsNn5ge^T**&1 zE-s>cMT8h2w}l&lsqu~PhLoa9f!D5mLf46ifq^YZ2u@`R`laZSRoY~oLPt+iWU05}PCOjq>PAe639f%)Vj`>xUf>}s>3IDiQp8&V zd?C0cfHmS)!ZEABvxX>$k}PFN9p|YldZYFj_QTig3szh?=OrjIph@lfi>M(XUwG%g z3gL7%gRD9^*8@Z~0})kFP%sj}XRIkaj|(TPt%>d*;a|d@0so)xd=$ovq@6}`LJDmQ zM1p}8fsu(QK^k-plV@=3D8;*_DO?iLi^!n$k?-NX@ZYIg_oD1Iv~N)KAfW^O*M9QP z50h%FtfH%gwFRRRVy;4VDcX!RCn-w$I0zA^h+qz|!2~$bIn40GsRire01AW0$JsY- zB<%t!rLnkk7&9{+$mM(k5lz%A{~>y+f6h>Ox?qlFhad=r7y!GV)3h??IL5>?1Gb83 zLql!fE`%=z#5R_*Se>x10{8_8J~4<&VO#`+?v1k)zjWeoZJKuoCr6&!@I5k`oH)00b@o&H_U9Rzbl4e8qj7o=~?EmXR?8d<2U)MSeY~ zn?RH-{jm%G2w3Zy4O__>(8T==xhP_VJ{DKAqfBfag=&PDMUEgG4@6oSudJS{gqUDM z+$3?g3|8o3u2yshU>O(Cc1b7)2nt)AK;e%bWoxHUH)5s+2nMmGft8wTPxVG{1`YBj za&lyeLZWi6cC%wPapN{g#4GX60QL8-qSyQ{8%Yc>NkW98vnhC)Qu#CECzUldUtkai zVEE@BKe&c=-@Fa{F32j%7ZnzBrXp7IG(n;ORfPCdV;4v#)6w*Cs1T?-STMkAJkHLR zu`utqRT$lZPZl}=9RRHXSRIyRPEQ#jFepss*7`TEv02=6 zJf*Unt3fV%3?wVTSVO%8f>t<~)MY7}K!=`03|_Q?;^QM{(w(aDBrh>!AtVoUES#GN zi<5T(-~}VTvvlom7EFn#-SM>)K)rVD!U9DmX`rG)kI~Fa2p$smEF=JzYL6X8*8u5V z-~8V}Lok@idmw@Il&oJ9&}!%@EtW5h4<9`$j1U7=>nsBiia|dHw8#PhL>JSzh6y-1 zpp1t&o0XYZ3)X882TPmBRC47nlIhL;+0g z2r>o$8KH#*MEhP@3XK7^1uxozl&Q0bv{)4+hGD9Mv;zNv1-Q2CKU(!k9Weg+mgkxV zVAf+;x1dG!2$VG}z#{8>vm=3IaZNE0z#YM(!Hn!MEUl1z<5RfhegAz+5kfxJ9e6aj zokLDe&+#V!;~+*+=vn_sx&`l+w0}f@fGl&&=m{AW@Gm%s`Yi$Jg4}JA6D* zkI>FxUQLvdDM}B2_Vwuj0Y|hZU^kr>TUT0Iiqy;GpD8ybYT}?K4jkZ&VF)UA3XNH^ z`nGJ*ca!C|{O7&#zD3G`6coxz2*q#mHrAlmgn&p<@CF;4fn4d^;~0Drd=TiH$RnIx zcg8?$9nX@i3+g&JYyGEPkA-~@cM1hQy!STK#c2eEwieT70?5R{D*|&#yey=(h$&$Vxc2*hXqZKLCmL>K`Yqu(xj3AqQ0A)^$%?&I*5Cy{S1)n zzt5BBMAB!JVTfaR*OE||1>TOHUi`tok0%Q0)#da;8R91#BXtlY(5omK4k0&#em~Ml znw>WrYB>}nxC-$7_z*6Un;`4O#$e>7Uu{pNvtVq71oO4f&;`{{W}Hs&(Io1b2t-Ih z8*oSx?L%4b%639xLt#X61;}&)-bXsdoD|P`P;`kBB&Jjp8kH3IC??$XxpzuSAHhB+ zP6ecmiozcG7!IJ3s~kEU0;3_}~stT>4t ze!9G~$4P-w;E@YCuBXT^vHUf$nLwwzS>M-Xt@#`)fw1{fQq=HkgjNQ9Od?IU96J;7 zg(?kGap2TrZ}x@+1?l1cMC_0R&a06Is@LHjdn7Aiq_Y9f6j{v;ZM z>GIw40ThK0;!*(>00y7Qd2J;aLnvbR&`rjW+!HFZ;PIlCK(Rt18OUEC828-Q;sq@M z6lfxM`fh{yXPh)A*aC=82sF%<7L6XF{NGst=%=St_#WXK3Cd$MZ`bS@@&*vt^(7}% zaGlqthT*tDQRxaE2il7;pD@9eMFQZrq-_cEX_cbCUK2Y{uu^9Eq1FZU^BsqMaC{wx z^fLkf5~F0G-cTHWLbWR7a;?e|%nvM0az5bsKe&Hic(Iz8^~XJ?!6||Vxt#Z-7nl%2 z?6Wm8;|Ep>Cc;D}1ejIi1*}-HSQ06>w4dWY5UL=HdjKl~xLT46W60A^3ENBrQFC*n z|M@mz*s;7OBpjtZX-q(DG?APn&`3pS2mP;IRVNAWfXHk%F3wZ^z`*_lAgwL zsxrWMz(Dh2(nx3V7%_Z#*Xrbm?f<_GV~S+*y2Z6%7?>cy!Z)=6ywWb`+(;agi$%SP zD%jqDhOGbygA%ocfLXwHQ27;wphgmA(qu)W;}8-R)IV^T-3GMnz8y=ktqI{C4$}s3 z;KpeT6>r1EN=kVEZjY$*c&Pb8j=Sk73hSAfiGi=5%Q6%dq)a0s)pd1xI&+t2tDdyoRhieOs9x+1vFwxS+Al28+5RT>8MubET)nO7@ z$k#bIbRDc>WkXL1wJJ7fWMt%KphR%kp$jOhM4Q_U7B@wF-}>#ws?U}^<>7zTqR07V_%9tNckU$-}gBVItm?&DZ=4{DO z=!g&N`V?eEq->G-;Szz__d47)a_Oq}v$U`TP(QJE>``6=0v)+o1oE-%?X$O;qH2%` zph{Dsk(#m)tp8uPk2&%N+CzT(7WyvOjX&TSfrUmYOg!_c2bUO0rzk@UQ4_~J^GKeenKuoEmp_jO=@?X4=8@)l~T&#cXJ}E ziDbDqZvwL7eG&X<*Y3)7zKe}Y5mXBcQ=tpOh!bp{gxG-diAZNdP@F+xo%xn+>ybV{ zmIv*F$d_44lp*&w?j1p7g;JMbK@I`mlLD(9Kb{mNfKI=Jmmt8G_jf0MXeIH=#AF-v zg3)ckj%H>QCySDx|8ZDuz|mBs4i1DXPV^VRmOL?ieFR(t3^`zkEOOPe}J9x|u|2fY^lf=cGMV;>d=q9@`D@(Fbw?=|_L za>0F_MY-+r4g^1sM6eKP^vytv3STiu2UHp|5=67*(4j+{al0q$`24Sqjx$76Ps)+B z(ewSx+oHziW=$$xF??jOG7z?rfD(~crV^;`J%t|w9f;zH7Dao|r69GqFZC>$=+V5< z>>^zR499d(p5m|}GG=64ynKr7>!D@j9qdfGzDxn?pa!Yh%&Ok6UHWc9EGPvjzX+oA zKM5ete<98`e!RVZex?;}EK`X5?`D)E`d}f2rAIUxiSI8?SEOU`G3ViIyZr13JNbny zgd#-f1Ri?M`h7Lfo%@Lp0;^;{q**T^K7l8UMV!?_o7#zmaXGF6X(|5x5{6{_M! zZf>H{?E<7D8cODG3fr+LS1b=h??sDB_LU-}nTJruLu&^3*lHBJ#1Z=!{J{@F%i!Po zODk4Q7Jp1GM;>4uFr4s=Q2OC0U|{Yt_kI2PH5u!m{D+AK+2;Ve`CSQv>@<0 zLd`>?3;DYyU^OBc44=_^?86BDE->qS5F&u=JvlC^b}0XV>}DWx_fsoz!#?9zk}AML z0_k23y$hgn;DdwBD2c?ZSXtL950ES5j?G@;LwL2YRuARLSxwy2`+-n|1$NJunv*E1 zsmuQJjtwhdMWRufjC z-xY7=mIUGqNd4nQ51mj1aOnnGI1%8KeB{u@a?Vj*i zJ|#yYAZR5Kryw=y%1ihlYE@DW2sWh}!4W02_sknHK1 zOM0(wgDEbRoWx=bv?>Usv95?;FG^QP1wK=G$5#cR z(mpq+_VHBUpHPG*DtA6$KfrN^z zW)!LjSRSq2&%myR^zvQ~Sd91WTiHoVg&hg^x142l7!ad-#I_pv1mnJefd*)(mIW3d zSIG8{8MBU!ZI^caWm@pfn3@ac9z7}0=Xe3GLE$4$GJOc;}K+kWg&CL_xh>!F#}-eup|@& zA+Je|9IPvzkO=Yk@rRg9WsDSv&aZ;TB#|==Z>H*zd?K3*rii`)obC?xuV}P#3--D@ zc-MbU+I23QQ4II!)vKHTu5SO{y|u`-7?!89E;$%sxzmSi8;i|o`OK|FtV9;uht=p8 zY3lb^YdILo(1ag>nU8MpL`aYmIgNmbVkp3q+*n>`#2SoOfJ`aG{d>sBl^#Tio+$1A zSlOippjOiVC#;R!8VVA?#FQoM2Gr2BY^#P@6u%PS2?}_rG~!FK1CnrxI-VLJ99B|2 z*-l7;hQ<1ylQ`MH+}3t)$-)IQewt z9OW%opo9jiB+3A>GYd;U0_}R#LEJ;BI>;cBA0o>N9ph&~OL|mIU-_4T!GH7)(3oJ! z^H}CUkAf+>w_(~u`o$3RE;yJPZ(iO}2*ObG{Ng7RV=qV8r3WqDYL(*;uZWLs8aM>o zFzo86_jmvdm~36xOF#(;CFr2mKLFxP^htAuIFkVYq2ED>06$e@QKDL1(Qo=G>cTx~N|pj;u?a&%j&mZ80^oxU z$PlXt930Khi7V03_9%fM?4R*&5dA^w?`Ji}%nQVWrs^RTh>Bt%9)DN{2Y{#mP-5p- zl`{+E;pQHnYhN-Y&Re|8_ehAwEn6-N>Jm^K4Z8#>h1;=k0UZJj5=Y_;V;O8l|8Qm1 zz#%9ZNV2B88k{=iQ*fQem;#JM!Spjym+p~B8V6vad4X`saJZP z7=;}Z$R310ZM~tq_tQJMeZ`@EXte~@>>eA53Im~DgR!D za~se0?!9|jaHtYoZVg;2#sQ=SZ9;=3jc`i@agS$T#UT-k+@2xE9J1MEea{*4pav*72hKs`_X(1Fj?12`E z|M~Vf6c$qnr`7%dlHAz@+XRi3V}MmUsUuz-oOD;4=D#*sE(V5haL1x z|Mf|^XuwCZ%}^bj(#yz~ZXz76G$q%drt;tYmqG1DIvePgVY|SphSrB%wrW1O9C0C` z^Mbl}fyKb|^uIo{V(9K~RGs|ScpG7>`S(d1AR&QiB*q(06Fl6;e}gjeQA*KPg1}Th zMgRG5@z6WrSWIN!Fh8(+_ikHEFItNY|NAGYshJ^R!6(H@n4o@B4c|t<{PknO`EhYXJI82294M~R*7CQ>$gFuknK;J2x z_L__o^t^#ZGY{^y!xD%-h4@1fl9>Qd#8e6JTc~sxnFT?CP{>h+F`&dT7!fToV!`uz z`u7t%tWs*LwwD0-+K(>H7~#?q_$dQ3J7jE}2I&LA&evZKGoMe#l#gKH+wh;M>yG_` zFdcwAwgB*fMj`YkJ)x-(YW!#5bXBlppf~aZWceUkAn)P6GhGWa5i4{l`Zu<;QHzTK z#7Yp>3MjxjOscJ>Z~Hm5l>eEMpUyasEIGYm9pC?7T7cot zA&)k*%`XMIJio3Y62$0ytZcm?)v?oz7pPA$Jlkz!`=a8?xh(F?vx9FQF7_xLl9_n4 zHm#xI`F&d@xwNdbD7~ZUMzq&9((cvVp{co+fp#qu>$Bnfsi_F{P1_QEKNo#8Y0G{n z@wz$LwZ{9_bLCXmTVu*sNCb^zP|j!E7VFkXe1TN%09RW{O$nlUds~{)L5*`CwDwmp zzC`N;j(=sh4Nz5MJVz$UHUJ2hQ8$meMSVQn>mpaUWV9C-7ui3Zt?WlhDiRs_Fe(b= zJS(M;nD_wCCAcX-@GHDKVL~3j{%PuDp_dWnY8nPl5Fh7Bx@sd-#hZg%|*ex*#pZ&C`?c2Dm?C@Q0+=Z+3eRuDTZ$y$4m7 zuR2HsIUgY=aU+0)2+w$A$Ohn#>cY4&Fwo6>6biKvrDG0RN(Md};V=3xY?hU6d^Cyn zh`I=2Gw)L2rkFOg6cV0;EHDdanBjSh;0C%I zRFv)KkeUMOw_BW_A%qh^q!u6Fs;a67pjdG|6q}spK{6kSXbZ3w1UddI85z&L9xU{m zc?MqNz9fZ0$7P~TRk{jD_5&14Kr&(E?EF+ant$*xO$}T;V7V812~$^{f#Q4vx;mWu zh{eqyGUt{$6?(#<3Av{m1QVMvc`?+b04slBE@y%f*#a3SSg4R!+WXNNRDDdREv!={OJ4QTzV z&gG!F4rZWPL{I?(X>=Og3po`&X#M4P-6gNFzmNzK15U1+(*Y7M0PYRYNbuaRE(w)H)iSuAU|&#_Tj`t zZc+qGY`|o!BdMt)RrVvcZ$xGPX7I&t{;dM9OE4Hkej$#p5E2sNma~g3r>TK7Vl!}} zGMwAE!I9k%mmw%59-gvpy@ppfrS7&@@hdp1W5Tm<_;+(+_MoEy&SHiW77DkTYGRGu z6D;+;k>!1YQm6sI8Ni}Do+p5su<-E3-gadFL~6l~2j>`Wq)kQ1AgjB(8)a37;7p8; zAOB%STaL$VY)GNx36a&Cj4n#V!ieN8^9u{GQ?klADxyPl2#CGKMgC1rr?0TN0mj=$ za3h4Apxnu_1;Kg%N{&3P65xn3LhO`ME0PKX(XwIw8#iiiZ=ye_EDTudQt;P z_fnSa&|N7P=>*z3N=8}Hf*{!LmIlGXn{dK#J zhK9yL){d@T5bXH*Z*JQ(l*~^GMS!^1hDAgu6%tZ|L>nuwEc)fhr)BL97NN1E5J-Y!Uq$QB2F13FtQ^?m42?D*UtI5$oq(DR28&_XlKa$6Fi-S7Gp`uxo+Yh3npILFM`sI~Z0ZP;ZWt@>S%7$&j>6N7;ZwwkO;`;Fu zcrI&baPZzwb-}lShrQH;MD-HW34xuoLl1|M<2r@eG&CE;hDWkUjekkCjR z$Pr{Mdx>XEm>QA>;9?yoZkG2}n^(qeN|d&`M2bL>VUyqjn!w2m&JffPa{;1NP*rV9 z8$hxMkWU{@FVUoEk0>RfaRU&6FLIg7jleOAsQ)VwGh@n?3pBmHEVL_}m_w231cGxDwk> z@lyOv9mNy;(Cqs^mp~3hpirW8#mQQj^_PODPTo!wpE%Pt3zj}l%EsX@FW`l!j(`<7 zP|4|nCve}Hm7((_D!7RU76kVlFXt3oe(fc}FsX`JT$r2ajxz(wRK1NS0`O1)>{OH& zttX8w7T%XfplZb)ryHUJ*Q&F6P!J)wR8fsxIw<_j?j@AFq>SXpYfoT({g0>uW$N1_ zM4%I?!{Mf)=rtc(TWd%N1%ht_SV8OSCkS}+&C&z~)yW8h3zj|ofpyqnnwHkKzwtq$ zqWi<4lBEEGh+)W0n-^LevMpgO5J$8^P{?PuRzR3e#2xtF*`JrUkApNExlK*08E=Db zkE9d!E#>c?EWd*&+h8CL?uxwVMc`6E?sUdxd@HGu#jE-hYzc$~zBM&)F&|)T z>s=#76gZI@Po$3%2?ZCfT=~LgpnQi&dl5xIfs{$rDN5!r&{8B2v!7HW!ovFA&UBL;i-PVc$&#&>#VhS<)Mf+=i+Juz0SoSgSD{fR;cpC`~*JOlX+ z5owY}<HcJQ0 zdlA46%A3(VC%F`NWklx3u|B>+M||+e5qaC@wcOkfiNOx$%G8hCU^Ox9nLq#=z>T6+ zS^v0(Es=j9>yC)CKXZl%=;tPKQAQ#C;w%^zxYS&1Zq!m&5Bg7Eda`uIqASP}fIAmi zkpLUc6xdY6OIecon&|IKP_!YQtGzFvuB+5(rD2OE&tUMzemEY9;@sg755u8$rXO0) zKi^&itr~O0v&lXEukX^r)IfsGEw0$}u1J=M=%BZFZm3IBXp@kT2D;MLr|ZPfbx(1? z|J)3gS%{}bW(pWquB<0!-6-7B$ajq9l+r|p@uk}sV&_vQ)pnSHDM)4B5V8$*`P+-9 z@1jOYV&$%O6$M|A|H#KSG3Bv4F%<2F62#Q2bA@AnE&~Gtp&}X)IwLHmnrkJ!6mb3g z@^-!IvZ}@h4uJVkG9I*c7kE4oIS>#|o~!LIj&AiCc|%VOI8yz# zOdE^p#@{wd)9ypAM>9EC+xWnEf^-A{ACN)qm~V}JWe>JjeVzw#@}X+mal5$I4Xcfu z)~sE77d2gdQ2U4bu0@Wf<{Oy7plk+_4q)rIZ0XG-V`B|i&&2i3MLocY%(dyxh*mpO z2~Q$y$I-$3!BYrH7xNH$tclF-fYVwsc zJ*iXQCGM(;;rxSX?%LJI=s)D0>mo0ibMRbDbxouH2Kzv9CRT>Oals)W6D_Vae?xNx zVBFO^DiMNB=Lk5Zumu^ASH$(9z|HPFrc5tBH*?^K+Ey%WBzkUrPLPa>!w02okqc6$ zSy*wMh%45BW~)&+TDk1Rj{w=SRG<=W>OHilrKcajwf6X)qW|HKBr2~-KQ8o5Ip3QQ7`P>h zY0*h!7^u#qLywrE_>er1TLH6YxR0?UDxAAZPAGJx{_tR+`ojnEv^SaWaipW7S{`k5 zcLzYOaJC2+0cMJ3#h=@V;0Rs}^WJlIU30KbaP3R-c9KPYrUHkp<(}7>(W;dT(>nZi zO5!3SyWupMyu+!jWq4;CX6ZO)VW8UVFvz@h+}!;m9w+l%wC1LUJwK`*K61pkj#hJg z4~qB5uDr7B?Yr^R#lF;JX|IrXr_Om#?QwdA6ASDuq1*J2wWCLe7mpRF%+OmH_9C=E z(@&TKoDiF9B&s|=Qcft727Xf&{8P4=nXG=|SOCnzkW=3UOBgP%3Bi)68q<$fnT&7q z8>-Y@PBoB-)2K|~RPHvagb zXl_hB-;%#({rbreS78N(Z)XO~fOF_4D_Gc(Uh1S5LgtVs>Q1nOx=-{U!n*-&mT!CV z5uqLket1Pi;!H}O4I(;BOsb5`>T{F3-hw@VY4iYyXQaQ7b0(c|%Vc6;F!b`uL%=JG zV-n%w`!i!oDBvP>kh5I^OM7>{Wo(K^HEL#74JstSreZ&P?VU9=Fu*gufL#sN2}ke& z+EKg@5GpFXtawXYG%=-fZH0r>FHn(C04PTNrUAl=qIQ7L-I)P0zbbhauzeFO5MJ^L zre^pMB0;WETWT3m1a{o{BD!Tt1d~+67 zQ&w&{W00(b0$aFD0)taH%P)N-mB%7I zSqOYuizP@A2&u1w;t1*exqV$utp)DH*^PO-8luk3lQQ>)5$8dN34FuxZ^u)$rZ7S@ zY};17si_|v2B}#C6SS6jZ3qEKuwU-9GC{QkG2%m}Ft?!6Y7P|22&)c@GDX@a3t9~l zZz7In*&1K=cAOsvmYjay24_HE#CIH_`njacKWY_#6|mcbu0M=LBWiHVLGeN)4s=i! zAay;wz9WKCnfVoyvFD?My?p~&`C#GpAIUbIh!^vR=!6t+5+0F{@9b=II*|}9CD?XqeNE6wi8kkFPNhW#DZwv)laCX9v(!Q7H&hP*VprOzbb0@GkT@U(ew7KhCQ zR%}0FQU1Tqn%5CU6Jc@){c2*9A0w(K-5SmbxCk95Z1V=6;vn0V*1H3{t9$JhCW&I9 zaX~67Dn#ybtcJV_5N{Po2tzGC8yMgmac7YE5_@>!K zlZn78m0w99&l|_e-Lz#(m0LWJc{y2mwC%YH)s=aF?%eF`cxQw_e{|q{+MclJ6FfS& z58`;)cYZH65qC7x;XdvGnN&tk9-dMI`FaAZ@%uW;%F6Z0i@UjyGe%A z5KVr|R7fM7b)Fzb^wsjmc<&ML8#({LJv1zg%clx5ozt6>n+H7zp-hslO9go@-It6r z4s$(rB^J!Hxq)-?P#OF9nE*N?u|FJk<@^`qN7>sQObE<THS2{xTgcEux#?@% zUV*1CrI?{%U6qBp4$@KSA$Y%R@o3>BmI7Stn$f2CM)zx zDlHwio;43lPzkPvyib%9F}7#C&C227Y4o=cYvFsZrC=@C{u; zMLkn_NfV+`Se(^Z7Sp>l!cy(=qa)eerfqf45GNr$kMC@Ue1Qly3!h0K{I|0kGPd!{ z9I)5iwM!29L3x$HPM5cxPVy>RD5!y?`K;FrWGBEsS)^GRidr!xAx^UNnt=|+d*bO^ zG5uu8iN@Nx@S6z~=%Jko=Hiu5`asryXLkfMPX=0KS(b7aeV(4IYvn1n*52(VdppVd zs0-{c0ZPBKAGn*F+thgfJ%UbGTgpnA&O+c8WI|z|MlUPL7Wc*vxAP*AIEygB$y!YdoN7HJiA^rxM@cT=*C8WV}FL?c*S^w5)!JgEcBTzPV1SAB8 zO-69S!uoSA>IE9cUVE42Tm1g`T)2Cnr^m+Y#j&JnYda;Cci5_!493_%(9}|-te+U8 zuy*`H--S;o3y_>>m2^5y_k=GdC1r43JNr^B2msPit7{FdW{W8b$vdt5tpXC!XREw@ zt@iHSqd0HOgmGnL?KDLGX2!qT>4J{~nYOdnoCrQ#zl!`6>t z%bDF=5JQ(UZ-Y=fpr*mW{e%#LX`^d;h zK!mbPPk1hKf7e5Q_g`M}KJ7qxMhmF29Wz0GK>kP*U?$2sX@(kwrm0_fpe5dneCSiY zO*wycRo_|EWqA4LrVhV$?hLM~`u0hy=}+OsTi6rZMy7VstYLr-MA@TQLpXAWG%%Xk z))6^ZN6rMdR^x>4O^f`)z%j!!H%YtlO~?Yz3Lglen=Xw#f-ls$Dn&Hasg zJyzb%ptCLiGxtew4r=3L6pVxhP=sirkidyf3sULnFHpag&)KmQjY zd?r~nHMMrd+uL~Si#_HsPgZi52AO5T9^u4bMBU)usi{o9u8o77!WBWe{PLJo_n__C zRRz#^?%+=Fw#;5!yQ>PP$j8sto?IEQot2d209e!;iu(mrJ@T++KC zP-c;Ps*;c(mNMkwI^_nMZ6y;E?^Si%-8in{*g-bn&8tR?kOhLx8oT7HjY$PzCzHu4 zkjf9SF~>QjUh^HlutpdpUyp~0TWc0y!`H7FXn;ed5{2!6Sd&PImr>^JBN68wpAzdXh(BU+TPf`^r`02e9r9a*;0`PqoEc`b}Pfq)F4&~zmhsGx55`@^VI#bsp= z66CC@MIK-+({^9vka_cGqZ3AnbX_}=v-3-ZC8Bard8l@CQha1OR5+$@JmmxE@iySn zMD7)1*Y@!L?Y~xlkX8;zLU|R(x^?HS?yN%!z@*mgU}xuY-@@3$6Fja%&k30UOCeG7XiLA4}O3O?$3BggB9$L>h~gM0kmzt-#up>8!i zdD6i)A3zdzr1&30Kp`c>X*HQ>pUbCWz)7cqk;-RWN*<4qJXqNA(Q5YO!(URCoG2t* zQE2pULU+pa^tU6!%mS(>SF4P(uA`s63cYbFiYvq8)R2KS>m4HQII!C*uR4)+m~h7u z&BdsfGIo+e)1$*rPWIiX=z=_6&%dk|#qKD*-BmR?F_BOp6RtKK80KYRxE=-0zK9>SAZz}RY7wFJQ>pEpuRD* z$2xoGlT(wO)+h{o9L9&%UN^V^OR?Dm*^j6`f>v8kMJT3;WdBjjYvbw&h#i zxinHZphazpYA^!=B9ksR4XtlmI$5vM;2=l z;24t6kmJM9w8+X@y_+I7NTemj8Lxs(tPFJqIA%z#N#Er@SW1n55RT?t^eE#K0W*b= zAS2@LtM3jF4JpvaF@jJa#?upss1jF(T#rpkdW6h1B5nYBc76S*zVO<1G~%_zSaVCC zW>~k%>l(5HQbPd%%TPTie^We^fsf!g^mW_R81lbx{)eqU^!Ebv#XzJZ%gc0ZM+nHY zI>2QY_KjPCi{7w8@^zR-3ul7qllv}bt81_Q@xxBh*3-jdGd9)n08$$O%u!lSOqPzG zt-&{*NQA+RWNZ({10Y5Dq}evqchSAlT)=7p;S-B%l$E+wDn`Rz2lWmtTWP?}yhJS( znQ|*xSauW@N!;rQxVi06OW`l(fo39Su29xboKOP0N)8{1jnKVZM_AwkHEfS<)eZ!e$Rb#(m)=w3r8zgNAU=+_R$c0 zYe0@-K-Fo`24|j(CrA&B-AL0US)&C@)CIfG0c350QQPNf&PcQL(Fp!w779o32p-!1h;81AQ`iOnS0<1&ib4{ z2uom8g39BR0dDfC+O?d=$pLa0{<`=wPp5)e*J^Hn%AM_;*bOT9dqAvk?{rB=r5TZU z#6}!yKY~_KP{HN7bHO>0NOtfk=k_TH{Zo(;3m$~UNWil2(8x+bkhEb z7P3~-4^J<93-$&OG=Or9p=*Nrj*vnSh&(W>YWngeAs~i{`c6|bg!u&dK!~21B_kyC zrrVV@pZHlb^$zb8e(aTo^TZ#@;f$u|$Xehp_w7ticxq}Y?)X6j<(44QI-&|zAE&U1 z>N?Myt|gm8qEmIs1K1S-1sS_=wl&8x!uoS^U*iZNNWp?Zwca`p-2M`&fl?}bLRyIs zDyQL94Gcw)YjLXu6dLfwKv9=L7nA>m!_1Eqpb{>?TSHi|v~vJ05tgZ1Ck7Qm6rwbH z9;4ztTL`Hq&^wqwfS?gKr07qP?DLZt9T7Kzw`%p6gZAn%@y;z^SD)T-fzW_*KCpgovd1sGXyu$9E?`>{Z(}kB=Se@LQZnPjG*_8Z?rRkpU5BMQ9vVT;@Cdw8x`Z?Vfyo|G;UJ< zsQTjNpXK6w{QjeTcG2%qvE+KsT`o?jYJ=ehyK+!~J*wT&%10?h*}HzrWF`dtaK9|@ znRwXj*bc*a3%h
`VAMe+?=o4>X_3#$X3Y;Z)<+=$SD5gaw?+N0$Ec2j8r!AzmG zUu`SjgA8^vCMpiGgOs3Dcf@i<07^~e*P#|Ji&QazK+5Z$MA6!^i+kXrGJWS%iTH!J3X&pjG zE@Xfv)hk(A7;g0t`JIs=S_E%N996XRX)QgSy8)9fF0?P1ppgdiji2}86X9WT3Q}M8_);JSwF?A?a#R}l(`ZW8i>aR z@Gg0T0v;kT0n}qAgaHKB=sy~K=?wwIa5&|g&=4nJf?N?3L*jn_?Wx7V^&M%*Q%P+E zkkSv1xpOC#gfQ&b0P7Ov?1_>p_eU`bGjXw`l62WNNLaY2Sf4;oz*kYkT632EJFGws z;;CZGcmSrw4(QU!y$qqwo){G(^MrByJ#^|k1BwnYdb)YXTB6p1j}TPl5azWMoJT=b zHfrPW@C}HOGf_4KQ6w$~^#@MMVORq&W+SZ}!RnKe4uIOIhIceR zg1DaGj*gD)5LC5V&m|wC$Dshte;^d#X_Y2BM~f^nhqIVK>@WY@SiP^pn)@1Q;_%TJR{q&1xi06Xutqr1-KX% zTY1=^T9$Zu62UKmQlia(l@;MZa8l9x&*3A_Afe;TO>_kMi0Z_E)*)2%?oo;c+FZN~iyodczO1)qX+!k?JcrOOlIK~*= zSz7Kn?F4U0{1$kQPeKdIuTpPmU{F&%&~Rmm$z$p@BBjluqVGGqK~A{+`fyF7b+V(Q zBWW;%r>TsmXcH>6@mM79H*>JFk8?El=sP`xyGekv@(y|VxwkZoGJ{o!kwGTab%?N1 z580yxkrZFuu|o5jB1dso%8(6+n%Qcn0888N*fRoa!}I7VOv)K4Bp?3oBuf8{dg=d- zKLu@Hb(?`w@#57hLez!d9PIDEOQFgmwW^&12Yr2&R=~O7trJ2ek4wwBz29m`PH{{B z|I*X_FS5S>RsL4Y#&AL$l>rd8@7%Ut$32#Y{ChfC@pAg{%73?{zs+e`(N!w{7iwYr z_<=hoe=6PcWzD~TM9>KRyYJGe#^WM(=l19f#-hjuZ!Vl1;4)ZPNv_oWx@l$$`DJNWQGiO<#CBHGDTC`Q zh92a19XTu~Ydq8{YaB_007i)^#!a{WXyx)HDDQij{u(|8+uMg$2lO-Fd9pq4@Btnx zM)F4fG`;#CsVhU&co?!H$~Ndk?|WvPvHXdXf3EWv-ReHQnbmZ4*a`O}qch~!6vu9X zY@57Pt8?b}mPGpeE7y}>wtStNy{K`TiM|Ye#;?;WHZG{u`J>a?IY$=V*^b+FOEJLRz2>J2~9iR)%_#e=4rQ@d`(A< zREyR4VVp)6n>>w;9b(zl`N%^HGM?DyW6-X*#i%E8o#HmufbE?6*T$E0DsLArf54_! z`)1FQ$0Bp2e_VaK$UM)m{?YaIMxNxa<{yM~ve6F3`t_-9iB+NPtHNVMvSMBwuJ=or zcU&Io!g##{QN>AhLR;kJr(SFc{M3DZeaS_g&TRpbrQF1(l{_bu_V$mTEh^TYO1Tx@lY+3jbL;Sis4`RpPXj zSIP-SuM=Nxs7@7$eZR?m>?T|GxvfqYIlk*B)9!Vk&lb`DCE_J~kt^6?)2p?|)?QBz zs~4rR{?HT_ex0$le#f@j^Fp=t8L_X}>jT)2n;*ZOuxVGqomEzxKLYOY{phq$uwHzv z-1q%hZ{+o*Tdp-bA?2EyyLHddtHg4q@=K#<^Fw=6Gw<>rk3#?kYYu`S| zR~=aFvBD_$!en&T==E7%6a8`f>!V+SY6R`*{pnw@kLU2-73sZm@~)p@^r}~KyPdWR zO0O@cJIXX2q@D=q9NJs25rC)+w;~(Rs0YaZXE*h>tLL=yWKR zHk7)St`3R|5}?VZa-ujhi=TYU+d#zDebui6|rc{BI){#neMawE>TIH3>RE4yKRP$?&8eU$c z{}D7%`lYlc=&s^4O@9#G?G;CvAFn9DFGbC_JZ0uYqZG|j*%6HnkrB2I&r&mr|E6m^ z;w$XVukToUn=g-=fua<|aFzNAJquMXWzTs7nkkAIbum4@fO?+Si)Wg~dA+m5EZ@v3n)?bm@HEmrrakIR%~u+pAS!d=r;H4^5Nq>QPuJzG<)jWjzs8*X0%eo=_NURqW~Ede zKG)Amt6gSyzhU`lT?wmS&QFfGDwQjnlBC}?1y{V%*s;;MzIUEM+k1SvFOU5e z?KhsMW3XRW@=|$AJ6*B%JI}09<5Ta`y-c0Le%jyAd+<)JC-X*)^cM+7V~fAWcjl+r zYtBAoFFE>sd(OA*Mw6GnC_8UTqT63|r83%}Iy!8#e#xch`~J2BzWmA7?egh(Y-;PJ zp2aEgTX9!5FVc;idnZ68U_39iDv)|U@~6Sgsl*H-z(*qN4lKf_?gQGfsoc`u$E_R(#$zq+=`n7&^!?;`2(Oq9I z`Shv1{gEH5Dr9@-=@w%Ts}Z-OhG&jMO}2@A4c}^Z-bJ3F|Bhww&3aGTZN}_2SB~y^ z)OR`fcf;7J`O|Zo>w-%-8nr7{RNqmewQ|e6?d_I(n}1gJW6^J!VD9l_8m@hzw;%QG z4>r|oXB{~3zDHQ8RpS01CxO|qLqF{g^gmjcW%S~3ouXFU<^tV1pS>d6GKK97rju`9 z?i<4mt8OeYtEHQLc>C-n#a>1&gUkM>6GoaS7t*GEZHX6JtSmz{cMX8s#_nvuSs1(`Z^*WY)K^nWf}mdv^cSquGUrDJKK6 zueWFZGBX?x*chl@%Ux$$VwWlKck%h%Y=$4&*^C82ZR`WPCY@xyw$iUK+3mT>C;E2e zqK2WKkxAXY**zNmmkw__zI*k`vJP@ z@Y3S3zDIAlKixVMSl+|RlB)c&?@;QVl9jWXy=rwErXJ1As`fs*z2tVerQ-L%p4(30 zi?`P2XID2x+%}_GpxNeTY0&8>XvW)7e1hY#YGUCI4cf9&+n zb}?QlJYoMd!2WRQz7y&p+%kFhKE19klo*?_ZWA5jmvNf%XnLV>m!tOf6Rr>jTi%Mf z>40#Vx2)UV@$vrsJE8dV4IjVBiry7J`NbzPxviG?hDOaJUajiO6%5(=PI>&Lw6tPRch$5-6n#g;akrkyWQBpYnyvBJ{lhFI$Qr?VyZ7qu#no{Qp(ZC49y z6CbuWP2+a=2{gO!X>=-ITeT=L-}dwcqcWTFOIK!G4DT9lp|#mlZ20Kjx4jaFCe}%s zWQ}|BbfgiZYvvq^# zz0uBzUpBJ^UpH9(6!?80CQ|54isebKvn?4}I&J=4s@g>_49lGbB4=(|rXEZG{^n(n zt3{LR0l7!J0}pndyfDM`w&U}3+tt4&f__P(Z&rPXkPs~CryhN@U2wIjdhq~nKJSu> zo^r+ThJf*5YG;;YACK_{$Cgtq@$wVH-y3^H5`Xc<%$etXTvt|q*Dc9k$Hdzh6Gl(O`q6&< zo%}N~ddJ6^^Ffm^yNO~?DM z6%QS;dVlQN$h#)$n!uckZ~3?ua{Opt`l>YjJ#zByiz^PN9Ez=@jG839eV#3hn79s= z9X>KP^IddjfaCsFwM5|vnSjy3)Ai4G&;k=FcS|{>q_LcO9bURL8^RFH->5rT1KIK*P zIWBtg_0f&?>C~cw@5TzuuG~|lN&S-V)I z@4mOmQjNNNV^uq2U+$fqeqO)#(8Z4UA2fNxn@UdR9%~Mcbo{NX=vs6yHYz)pL8|&Z zgI+8B@7{+O1{_2TvXbV%%1PchMl;Xb=|7s|@coH+&W^bF%mbbkye3~<@?SAaWvlh% zKC$4c*mYCk=Y=|}I)C@5Czn3?c)c!hKd;)EYBT@))}alP8;gH<(Js->Y>tndr!{!= zBt1L$mhchB`tsBT-p_KM4}GgvtR0p(@$z}(lkzBg;kYfGCum?78&{G5iAku3R^? zS8P<-KkeP|$4&Lz*8$zx%Dz~ILkmB5zj^GsdFjcG8Wp!4zx&Wa_IK#^h%sp~M=|{d z*M(?l{?W~2{b%&rcn6K843w-3s`$qquUo@W!24o$r-3M4Ld{0wcGaf2q71()4N04X zPgM2{4BXuDwLNisYk1qevEnaU2{){{tY?o+?B($3ak+GDYoKF-{`1J2o5s4YxK^GX zaJYT#d7+KF%g)Vwg-cJ$l7BDc9-e5IudzPSpq^r5SuB^=osSNJn>x4aZI^l9U*dL7 zE&9`61R>ysFdgJiBk^}CVzF{f9 z_J=v?sc1-Vw0W5P-9y_Y(59a+SMSTQQ)l8PW{i!c)_$z7BEDmDP zTFzf;OZTenED#ebf6!>I%r5FX>?Xo}{EltX-7V`(?)BQaOgi!NJ?0x=iJV-`#v{o5 z#+D|TZm$3X6KnI{AMdH^dDkn)!wGCZra$`5z8?e#Jn z;JohfQ0YjXDp#srBV924&*yzvZ%#Xle$n5^A!(l(9%*eRBD+pM*TW#4`r5(7q))E( z3hgh%;#W=$8>m-C#KiTptYGVNewK3cb8b9>ed-4UH zWsaBPhs-1PfezB#23n_#i;O3@%nFkEj$ia=q!!1T7Sz98;Ex4s5%@oF;M1brnmG{epc4jXYQil*Xp3KgYn3U z!&f4=w{Pf=uKs-0=9anRrbELU9@#FPR(NA+Czh>MXm!fdOIqc~j%5A2Jzl9baTA|T z<&Q`uSq2E+V5vE6m!!AnZdU8Z(<2mtBHdoiPaCa!xiplrlEwNM-o_Yb{oSo_^TO_~ zzOUaq+T0`yGTmSJ>b`p|(GZxRNfWR8M%HPvV}&f=Qna0+(cFsGg>^Ge`;T2nV6J!k1p?~ zsyDx*(rm&$zDQvD{88wTgMPHN)%T$oX;0Ck31+ftUYjI1TYogE)T`y)%MR=@pZZ-l zMDgBww|c>HVb?+1YYyLAUf=N@n_b*lmbI{p=EN+WPoMSfbxt zaF)M&6MkBKgi87c4Ig(V#B3|Kp-+5k{$9rsg>5Sdd zy5C>(i=5~E+!aI0y4KZo9K1AcF237)@9A?->v}(5v~_lgK0T$kr{1FSUAL{xR)r8> zo;>HRp)MaqwoY3}a~bdoh74Q%O1x^*dsI@9Cu2p-JWKAnOqF4$%5}$d&7O6xWL*^_ z#g+Q)3RC+}ahn5e*&i6Kx3ioH2ot2a!gyVV{e9vE+O%r}DU5UH{cOrZx(C$a2FJ9lc0 z^ajo|^&2>87A5b5H}PNFc0+b|e(3?E()KsvR$*-D7t74&BwAGS+I*9{&C}{ zs~rEpyU9>1TaoF47h-R@)F)4SaZC;Chi9_dDx8TrviU;RX9s38KF-g7X3v#oey5h7 zHl6Vkw&rfiGN79gX6+8iRXuf8#wy`ti_4Z*%;UV>K|OH+(g#k_cCS0{BH21Ea;N2m z&jvwZ6+VsC8C@>hH_SQc%6@!x#DQ~Xu)}vPk2mS}ll^169U4_@18%-#-w|Wr8{b;y z(sIyVT4l#)zsvrS3!LBe6pP-hPrmCjDd}=U(LXH5zS4GG_d(fglgtL=txhGM&Fgm- zhwNYwUdehr>$-p(zjbuY*vpuKit1Sx@6Yc{soL}B)~BexIjQ6}DeLNSJ?7E+k@O(3 zRo(|a#kky3@VYyeuDK+nRDCNXBI>z=MSyE)U=7u_P90%`!z1ZY{>q=4SK)?aE^L6%#lgY93QD?S4tx%W}4bgSpBbQ>oB2e>2q4AAEHRI78o%x!L zK1J8&HasfSoa0DrOK&c&sXS`2c*K3~`D3Ztx;GBf-(LE%9R4E}=_IId_)or*b;+$M zX?xr6Dz>@L@6Pw$THveG3tx0UoUi(ki7({Msg#r?g>04gNAEs2=4rOE+_CMhQozT= zVI^DFZ{I~#dc42Zo=f;`m)pJjPt+WX#zTt@{+#vubxxEn#@yK2P`gXJ@A>2D-%L}T zOrEmkDV5IcpPfr;M>|jD6s12*FG$Zwf0h2^^aJ)Y8?S8Cdq%A$pS^7`xM=^F^F1TK zV>ww~_Z8$HCA_i=zq96;?>YHryu$Ci55yWjHaVF$;a9fhx#r=PV-EL!KIA@;qk2Rz zYrS=-koKz(Av`t$8TZ(Lc?ptP5_MIZNGIUm;t zpW9Acs;}Z~ea&QIJ$!yL$Eq-c zpJA41C4;eCdXLJ*MfIt@?eiu(#y$>nq&ku8>#sQ9Uti+!Tc{&>>Sv_~Gk*T=e-Y8ZuthmWrJi3}4-mXmFMdhp&x$*q$0W~J&a(DtDC0Xtt({Ujl?m6Lcdv`M`+)gVScR_r@jlvjOi!;gKl)Bl z;%M1v>ow#qeAAyY@9jzJsLn7PtzLEJvx7*oUc@%`}I0}VTsq%fbcS_az3!KU`n%}xHLLCpI&y|v z91nlPRs1L0sbO3+E2lLj`JHQ9VMV4$gw@8U+^2*#)!6JS$@ElmJ#TT*@=LMb)>yT} z{Hyf4N?M~zUd{Fguid);OW01mwul55kuz%)_vB=m9jRh|7}#P9d$M@^`w3l`?XDH67-&ozNOwFS@|^a-HI>bKfSX*d|bzI_v80kR-w~z*BK@2 zXd_kroRq!1^ft#VPv(BZ)j5x~gWhNR?;TE#O5VmYwYu6f>Ik*P_YlpyTQ*1@>G?E} zT}2V$dX!6F{6fBj2ep-9rKjNgL3fS)*O|IY?>u2yJJ7d6SGd&kegB*0_5jZ4 zTT+{a-|$>~cjf&9Rmt!%Ej`h`&ka9S{l=vVYf{}T77iNC?$`2sCn>${{T6Zk=&q;h zhIXjf?ci1z4e_NR57I0~J>fDQWWj&?APE!pzdpzV#u_rVr>rfy8tukx=RQ|``26Db z#lA-xYz=!vwYC4ZIp;C^nT6%rrKxF#u`%bhC>>+vY?R&9zRbTDWcg;Dw zX!rHHDEYhTJ0HHiw(aQlGBX=be*a$|9Ug6AkWaoj|K+9_|Fqa!88$!t&E~fp-WjWJ zZK?kEW_?;<&7WD1ui4&zv~TAcL+;Y&T|JeXo=xOFyzH{inI4{=4962ZCD(J#RbI_| z{?4W79+&@)^o&&Pdj)TwllxhnsRofpL)UH zsI7;^Kbxw|Z@Xq2RT}E_GHuBpsqmN5?DM{tSD3qfmoT$4%&6h;;b;4n!fs7myaUCV9elXA84$+k!95y7Az5`Tx1T z{+G9}GmR3JEXXwcZUS*FK3=<-q4?)UufoyjD$ z#l7k8p7THF{LlaV-~W5>G?6@1y=2)6S^wVUm%p&=y8n6S&G%k@&d&YEl0RQ_@cpY6 z{rQS>M8-tq(5~fCh`nxIBJyiEm9GFXzeo@C73eJJ0~I1U=+R1%T4*GUZJWr;(?tBU zu>rF|49o=`U?ErmR)b!!5nKwc1P8#|!QX*fz-{28;9hV)_&oR$_$qi9d=oqho&etk z&ww9*=fR8Mm*BVH58zMWFJR^zk#oR>UcR8EgZ?U>v*)+zF0@?}49#KY>t8WDeL4(%@_0Rj|B87Sf3Os61aAR91vBU356lIf zU@=$$&IfD2Mz9%d1DAp!a0N(!{orljKJX*(JMb6an;@^2 z2iJh3;3jY@_z1WQd=`8gJOh3Reg<9!e*h;zXg+0tg`fv)1$#gi90oUoW8mZ9)8Iky zB=|S*Gw@p=9U|3WCTIaGKrh$^E(LLr1qZ-ka0J`{-UB`WJ_bGoz5pHt&w%H_i{SS_ zI_XQ$1Uf($SOU%mYrutI0PFylfjHO)(jX760oQ?B!3V)VfP2B`z*oRGz|-It;AQX{ z2rm$61fAequoi3v7lX^dFi3+OxE9<9-U*I@dO~glbfeJ3;x&<0Lr}{?&;=HO#h@Fo zJP6B%ECtKJa-i$Px!_G;B{(1Gnz0J31{Z)ggEe3+SPwRWi$EXP1U7?yFaWlItza9t z7;FbSz#!NOQXmfwfP>%=I1H`d3-xO%Z3Cz zIZJ@$yO1-zEx!t$f5P%-FXfAiXw2g;LddkU@@?=%`K9noQ_=XYfajm>2Z$|K`$Xem zX|i&SM{P7#y<$N5{RoxUxV2ttqj~hw_?1^bF^^Z97LV7utG(7uFSS=*?UmQzti0Oj zc+e{bbX=$(<#l{0ujS}C(Kyw=^6H=E%kpFJ+Gje3^tuu#ul}#{c+H#k_-o;_9)B}@ z#^aBb@pr z)iLx1pkwSAp!4`qk3J36IepZlpMx&ouiB#_OPAWQxsZ}|>@MVQ*rOvJO?Wg3?ec1; z{re@Gj>^N9cFJQ=T_<)~I>*N25OD=*2fxokD~VLoRh~RVjvtW@6PL=v)ac(W?UMhn zbgulw(#7&qXq}fY%8K*1q@(2cC3HIJ_dsW`GO3>#Qe)*aX=zP2difg3@t>q;u~NOy z(t2yxah={n?1p50m0_Xg6lz5H{?cP;5T5|Lw;&XR9h+T>C88q#MI&u1*Hl_#Oi zUj3S>!Qb0-KyI_NLOx)rk=re;k~=Jo$VV*YEM%!)K4xj9+-d0w`K+bq%2%N=FTR)r z<^4A8ws(y7{4wbkPv7d%HjlP@bgoC|d33%{qQME&yycQ7Z6v_ zQn#NM&=cDK3)ppj1zqUr7kcAhAw8k`h3rVG@AC9rUL0M_GcCW19@g@^C{N4R@vZe# z`Q4se>#6cjcvRz4dyTJ)cGh}#F}qG!dY=4?M>Xy)cFX52ohC0q7kTZwh>{9gq4v+ARNM)Uz{YkIC0qsrr^A^2U(o^-z(buDYA3k)wnyO!qz6Je9(Ca!j zRX>P+5&FB(&pm}cfqo_WPobZ83Vi|nM)b$g&p(C!M)W(;>!tl`{1f%Ng7h);dpv!I zr&l|@E_aC>_w=2lwf&0vJ)Zs`D@Df8_W1x%J|#M_>aSD8TWbgVW^Mv z`vC20WAo@DkFNFTB_2(C^li{8qSQQh&@dN4qvuBFM(d;gv51fLp^eAWCbL@xjQE?( zkWychd5hA((3m69ZEeiowsWv@rpbU~{A%f@Yl>-~o31UU18zD}Ob4UAZANRlCF2!B{NtlE$i!y z&z8-zDZbR_V8pTY)4I7m!?PDUri9hC@Wk)Ni;Tf)>%1gF+XO5hLN=++vH7fgudj2_ zceCdsN==Jx-Cic6#{4nvk!cKL>YRSj(zNWQ$Qk~UjTu=d(;WuLkxXm}>&y%%2)7t6 z%&HfXR?|#-w6HH^Vt!(*v7XiUMJ3-_>k0Y5Y2@2aBfsP{^0%Bu9zTtI@9X4l|6hf? zh6rb~x@02L;Hug6f)b5f$umz4R zwAI+m_w-Tpm!W5*#_I8--Y44))z83Yr?nZ1%*11{AFro8oeA3`)9pK;vh1Kbpb9WEoeSmevt*zve#heXy+w8OWM ztM@3jKI@Hj6Peao%P7|4`;%m<<()@aUO(Q||MSR7 z5ytfVQkj1|h5wUf{)_GAXQL{{Ta;CmWZLd-Y&9iWT}f77Ces+T{~M9DLRrI|R!(J2 zCd8VwSt3q~_H!lGuEdvORz_oOtPjJiSFGI5FxI-pr(_zfrR}FaoAGJeU`Y*r+_u)3 z=ONeiayI2$9jm4OVbg3DNF5=oy^gOgY;0fphVj{A+M-M4>Wdp?$6Au}cjbb|4n=6g8cw>-ndtYj3Hp3(M-da8g}2mesY!)^%B_uG){Fx(m?F9k?8w`p-7`0r#i~Cjdx+M<95O#7t?2@!Inl*PWQ;7?|s;6n@-reV@1my zJ%z3~-}0VL=UYmQQ%!_L-CHN=T8Ounesy=P8_-S6fqkVpp!(6b@63U-oXH94w7&xJx}Y|T3P(l4T+%#sV_pp#5giBF%* zM0zzkWFdT2ht3OeItdj$cYMF(p{lv6LsnKz(ms-j^f0T#!A#_Q8*zQOT2?#}DaGKX zE2)vI@0slV?xK8UC|b(n)>Oyq3uSfexFr{vO})ZCZCf9at_&?J=HZm)`d|LJHMGu~ zc?0FgH^6RxJ=}KJy z%C6~C(y=M&t|{sBrli+QNnbQ2ed(067Oith*A~6>*=IjCN$4TyUg%NiDD+ln26{6z z3%wmW1|5T{551J?TBmcoNMY@Mp|l%L&-(6a;HET>efG0@*N2|3)W>wZs9xjJ`K&(m za`Tt-QO*Uktc{)!)K2X+hx%4u`o=?jsa&c0P^xuTs(YEzdZ7E8mRWojRC)RHr~1)Ye`d@@%^Wi$EpseF7molJ=75Qh&GzK%W$IF7xPe zkFJo=hAle>+IRK#@7%CMOrJOeZ; zDTZDW^vJR)Cae0hxqaQ)v1Dc}mChEr$KwYI@$^;QJ9~F|@v;Heh^Ltt9cRo-w|Uunq~-LM z+uP%X0*%soCX`Gjlz)PwXr`^2XLX#}e^EQum?PchKv6_sG=Vex1oc zJQLrilW*EU@1=YCw(J<}-NI%leyxPGzrk=?taDkSZcV&_w5<`3~XJ$Vb4JCmYu!*5-AgH*|2NF zcBwCuY~8Z%qTVeVH%t<4+pxWF>-xTRa=qD^$tCmI^nqj|Hj*7>(XhKfY%G^$z>c0D ztFG!B9ZRQ1QiWK4d@Py6D#H*PA7Ql( z!k)7Z6(j_6fU~F`A;ix_jY}wzWGzm`)2VBcGLu9qmrRtl@*SKk#`98HTm~hW9J85& z?A!5lUcwBTgi6*P?jv%}QBujxoHMnIFle?4EA(Y)o>VNsU;qTCzO^%CsWqI@ds~!VARmHcJ(nK4wMVdYflr zYFp2!a5;NUsY~T;=j}+Qi9kK$BJb|iJh+5X`Tls`>)${szk?1(4=HeZ zVm!dZ5D!I3q&%ffB0+Z}lyI6uQSnS6PI?T`UZdVQTKuE&REE1Q@_|u1J^Z6thP2g+;rebr9L-V|Ng@M6fIcDy6c|= z$1}D{fdh8IsIX+~UI|(zFK3x|nTk!$TYFBL#r2CM=G<>?G8Hw_US!q=RPuH6Zu0}= zn|<=4nRZ+{%>AUAeewlkE^p%dU&Wk7=U?EHM@-crpTT7H&~CZN8u4>7{B3jjo&NjH zgHwF%QT&}!aep_-<*I=xNTTZ7)t(p$CO_+VKh zb9~=3C(ILgSas4&uU(YV-#OIqlQ(Ys!lg!kmQW*e&6lxQ#M3&7m3r$n-$f#;%`K44 z67;K^hg?Uz;zt#7zHA;>n_8DdRTwN4w_2*!EFUdG;ONv+DJ+itt<$1?>!j=5aI8T`eRQHlWX1QA(pK2|Cr+%tN}SM{9fTzus~ zFlc7hrms4*D!tk7`-*Aam@|GKonbPoS8rC{dBB*l)vKLd2LmSHq3k zjS}~Brxq8pgN-eXt&MGs?TvFA=eZ)MaY5rkw}37+Z=bb>62eYI?fnhsH3S;AH&jk& z_LpmRps|L*hF%O6gAG-#sG`9+vvAv~EH9oAnugU4e$S^@OrXIxSy0iSR?|zu1Rp() zBzS#wgfA-M*n9AZ1MfS6&Iilq5w-9i5g%WK9K&DBbw~Yo&S^C#&Nk*J;1zIpvoX(t zJ7dN?2%ZHmf!kY*xvzy6Wo8k%PPBBJ=QJhfkh-H)KUer>nORFo9dFgoB7s@U;GeX7 zaMp787pzqURx3!oW>Zz9&LwrMO?|xy?!GqTb872vkMZ4^zwI|4^*_>PP`unWcwMEK zBFsN^I@j>)=?VF_=TaGDuevgGY##b~xDT9%m#5~f#DgO*&GVVp=8=28k-PZ; zixXUn_JR3Y(o^%-o0sPsb7Ke92KRvz;MorS1`_({ z;1zJ|Vrl_SfFFZb!Le>+{KiGUbLge-D)mzOYoPCF^?l_E5c9k5KYQTy{~YkozAM%L zccAY)bKoc+e)OHFe#_F2v%ZMyTi<1ynEU(UJ9+0Dgb#`P8znxt+20C;&!Q~kTCVN8EAASbB{)Q$1ujT3QmIPkQvcHqUkH)S4PvZXoyTg=@ diff --git a/androidgcs/bin/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.class b/androidgcs/bin/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.class deleted file mode 100644 index 306bc08c9eca5d510d01792bc7011e1ef8b75cc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3092 zcmb_e`*Raj6#i~rn}%%(EhN+wXrJyJ1yVD^C9E%I!J3anCXB^P5es8!I)lWI66^)o8k=tsx?i_5Jhr zc*b<|bB1HS)LS67YB$!Kj=;cj>9(<9aMxz3JjLoVbxOI%@@2a;>4z{y5*h`7|OoVYh+O%QfO4o1j5*Ch0D)`*TCBm{Prth#w+{mzPMUz4Q}=r1)YMs3lsE&1**M%*=vBu|$9 zYh7h6SW1<;Kq^}-j&#+FqA)8ieR@?n7aES`S`8LW6uG8q*jY=oaf(%es6@I%dfSVn zv(Q+tv!0P`aipl>G_}#;{`_XeZ2H)iKp&6In|0H+DvOqRPau;W2@341?;6!1H>Whr zkixb|{N33VN6J?^43~`ijdhnLHSRbGOygZCg0p^-l);=pddu-PcmlIHC*5^vUC=R) zi>!`gy4|2`jgI~{7&0&8&dU~fA^6nDqJ+7m<2{rF5`>wzjSb7a@6n=mujsgn1#fr3 zs8-oAlpXmbqm*)})}&0flJTnR%KFMSlKFJE(pC-y^me5@*8&6H459>gn%cgkt~u4o zsN|y)Jc2TRcU1U$NTVxH?npcCl?Eg{%SI6h5F{0&o z)7oUjU6!MozHHXm;@*f+O-pX{HNz>ZwPKaih52$ZQEsf;74w26htcrAd@hd4su8GI zXAc)@hU1uyhOY$d8UNr%n&HH-CHi_6zqye44o@=*z{PVb@Z)f1tb+>EBaciuR|=k1?2wKSO3I z9Pu`X%G~ws*J($6dq3@%Zy%(s`Sx&`7>9GCkCFXdrIF)ripc>PL}+D@W+M!tihUSW zdnzG};RxTDn*2gAT_M}aPkWw8%WL-J{=nhP_|W)odB7G3$edhaUdQ*KWAsF1T<27Y^XU0o+Nv?Zd4QAwryFc*e`}`OMFV zTp4=A{Sa@|i&K7#e&v@{Z@onC<2@x4Ui!%(Ueb>jqQ^Ua`W!ZXyr0Oad%yoA7YEc!`3B%a2k(zzCHOvVOdxy(=tOD!z7 zU<}4O;rmqXb1Yv0yKzp1y67DZ?w=0$PWyZlnELokolRpEYl_Jx_d0zSF@PHi|BQDs zxMC_`H-&X_Dw9hoPNk|+iqifgc5Pcixi_|o2`T>*>2q__UKP+xYK}bymQlwB0tt@eL?4@j#dM$gCw5Rfy zxTF$Dh%-M5F?QTUl~BZGXLo1jy?Hb9`_K2E0A9f=Aj8m<;h7}^?gwHhmF4(eD1~?C zM%Kr{Id@ejl#_^u1!NgEQ?KO&fpz36F&65IA^%4BLcL|sT87P#?MjcApy8g59P$k1 zzVP|+=wiUbQ)e*b43)lgouTc7B7UczS@lIk46XkERn%rEO1~R&M-k$7tAAUZjI7Sc z_lCS}*l`)_I#yBEt~Ia{NQ90pY%{DzTy>?dxUX!%CscQDa+z2K}?} zy*QwA)$?MWo-t<{)3+7-+66pesNYsFp$2kgy}JzPCsx=OQ9@F{Q-;^e^rh{-n|kCq zf#P8aHPqvtK4+*d^tv+B zjrJPI(2e$v&H}wGvW#rbyg~6>;x5q{yMZEB=+tKcWbf09HUnik7hFe?wHc=!v|;~%JfBGhLe4)&*LEU8rl#kHy a5-nn^QJw*l1Z+_Sd)Oy-h6BRN;P5Y5N$Z;c diff --git a/androidgcs/bin/org/openpilot/androidgcs/R$attr.class b/androidgcs/bin/org/openpilot/androidgcs/R$attr.class deleted file mode 100644 index f69a8e17560897ad1adaae18fd15a3f75ac850a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 358 zcmaiwPfG(a5XIlL`$yN+*6KwsB6v^_2G2?_g@UjsROvmt8`hLHDcRKTsA1!MGu0k9OlKHP>NSvbYLNg#6AJ{Bb5Pbt2CkTT036(JxV&TPFV?$y>LNq}`Yxa%}EUvp`Z%<2qla+~uKfoVl zoI5FOjLn<8*|%?I-sji*2Y@s5LX-#x*3BZjlxC^4^^q`BXVr9;q|x{&vD&&26+(L< zo+ap9r1F@=E|(iJs@m7Yz`q7s@DqNhlxp zCxpttPGucsv>I4PgU}i&Bd@c^Sh_nAYf0#gY$EhTIF<8Nv*PC}B^-|a+y0zTzqOf5 z0mR{7!2kdN diff --git a/androidgcs/bin/org/openpilot/androidgcs/R$drawable.class b/androidgcs/bin/org/openpilot/androidgcs/R$drawable.class deleted file mode 100644 index 43d486e461eb753c8772c3c239c81b3a83a13216..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 418 zcma)2O-sW-5Pg%jNsXzk^|M}8upSJa6)ypyP!y`f z20aR1-pm_j-n^O5ulElC=hzS65e|(lVzZQbsY+AFLg&_~yvV9}c9dK3Eas&Q&?XEP z;z`7%&_#SZU&yQ`v{hy_fhL4rVsuptU8ka4$<~Vp5d2G}ReeQhos3g%PfRXDw9t#N zhLF&oDlKnTk8^47-5$blYBEu#!YapqitYMARfOZ|KdfF5!aK9FnY>m`(4U<---KwQ zwX{hos!CP?b_oZ6%MrT2xAUXeKR=8xLI*y_fSHFbXXNf+T<1#MaG-PghUm3v*Bb5Pib|rwD@hfzTN()WVCk#^w?e5~2wj`n_X=OO{=-x2Li4H(8lj_yhb= z#<|17#@M{cd;8|?%zS>me*iegAVh_5VBIXTOKFx$TOSECbyiJhX%>x-w0O3;4^bs_ z=HgLAT9{dMo6KeE3Dt#AhCo9?E4C){!uW~MxeQ(cfJIvx6K9_?=?aku^-E=xzaj+3 zClk(y?Nl}ppxwjG$;Z(tY#HxQ#8R2mB@AMah#+}Vw zDz8-$S0A4hs}Pz)W2B3<$TFFQ*e4AB4&%PnG5BsgJKwK@K5D2l3rn`feEk=1@Cy|? tF}Bzdl^m#@zG3sVZ0Rr-0YDF1jD?jA=wh2|1v@3~Vvp-8uE(GBzX5PkVHf}a diff --git a/androidgcs/bin/org/openpilot/androidgcs/R$string.class b/androidgcs/bin/org/openpilot/androidgcs/R$string.class deleted file mode 100644 index d473cb81c8c6db44be5035f5848de2cfe8504c66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 445 zcmaiwy-or_6ot=)g+&BG`~@qc1zNbV*4U7kkPuDK(3)YHEJKEw&CFu!Gg+Bf_y9hX z@$O<_V{FdNH*@c~Kc8Rk9{?`V3sE8*TbD#Ol_pi%W|1&6XVol;eKbDxnNubS5fIu7 z@hl=OOcLEs7c$NWHIb%IMl2MXk$0=*RJuno)$H3D*;wd_a4P4Y#~_<4PdFL9d9xD|%C^A%sO3SgGdiTks_zeO>@9G{XprRHgYIaOv)g&O0kk^hq#v3*V9-6I3;+NC diff --git a/androidgcs/bin/org/openpilot/uavtalk/UAVDataObject.class b/androidgcs/bin/org/openpilot/uavtalk/UAVDataObject.class deleted file mode 100644 index 95af7d70364676903cbaee10411198d19f52394b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1127 zcma)6UvCmY5dRH5pqx~cTC`SeYc(ECyLY?3*$?!sgtRH;fJl6cMUw++nG)jFPb-tX|-Y8@Nbv)=R|5X_(F<7fbN%xRi+1H?FWA=W2N` z|6he0P)RYfmE(^oz z_4#Sbmr+KQch9pztl&CF+=3czFqqxlMBPMj{pDw diff --git a/androidgcs/bin/org/openpilot/uavtalk/UAVMetaObject.class b/androidgcs/bin/org/openpilot/uavtalk/UAVMetaObject.class deleted file mode 100644 index 7234b135ec1e4b601e8d271c48caf5fa07bd47ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1440 zcma)6T~8B16g|@xT9yi0KvYCl5!pqc@zolQh$c-cCi0OOo~G@z3~YCr+1*Bc^!NCn zPb8Y?yFbc!XSei&v}&5n&fLBC+;h*F?XTb8egJrcViqZeRi&Fn)fRqRdMYeNyc2To zta$kR=(Py>o9d~kg;``6R>meKNeq)uq%Xs#46akIobnDYdfaaoca-u3_e%qz{ZLE4 zS#pmUGA~qJSV&_kj|ogN%vPi?_M%o*=mTE$1Vf>sYTP^GTAFh=mO~hSJb{-SBuKyZk~(nmCK= zG-Dt1rPfO4aD(B~p|3@typE{bHPs?Ncqo-`x3!|NTaRsPs@!UOvL-`2h}uF^77d`I zTBx*5h9y2Yt}O#Q^6R2OLe{tK*HIAK;(b!-eXyn9QD?&Dz6wu>SCOuXS2DhnLm$Yt!N*+?6n$Dij&^jJY0c8<02%sGbYp3A>m0eSv`@jJ)uJaT zFH05EwA)DXkjE7|8Jro+5{lVf#kDv)hXUrPkLfVq?eLb)ri1kz3-1bx=eYTkPDu~L z!gT86TRnWMhi~CFp&B+8mT@P>UxD4le@1aL8S7I|U<)y$+}uUfX$Z$cQi`kN62MTHGEKoAzkPkg7KtO-*~Z->koUv)?*s zGHk2=Pg-VJ2r=w+)IP&pv(s&7dv&$j)EIW&PRAFk=$2`lew9JW<$DZ~2C0u>HUUbe zAcb2D(aJbvIj2ra(tOvn2jy127pK@o1+$38APZwzfsCkF-Bu7ooTyaOHaer>q2V6z zL(5=DtB%gC9(PS)2b&2AV8KBY?y*K~c4c%Tm9BA^U4|hc%RjHW+oBJb|oYfGY09U4wTBTG<%eDz~6C8@S58U>)4dIU(Vi4Gx8gysb1C{7`(N4EHOzk&7B z^U?*9=ST;}QY0`kv){=joguCDBWK8H=UDkdh#9QXKN)0O!aOoq!y*mg5rbNKoTEfB zLX%wB+PJ{_1RSLRj6q7Uma!qklF&Q2JBGiYLIiyI3@iQDQsJs!5sKQ<`Xx5EKa=NL w$~7Cikr1a#e>~jfxNVCEvp8Np&J5E9&;M~G?Fz;YjAPG-z1f|;QZ!=dG&j0`b diff --git a/androidgcs/bin/org/openpilot/uavtalk/UAVObject$UpdateMode.class b/androidgcs/bin/org/openpilot/uavtalk/UAVObject$UpdateMode.class deleted file mode 100644 index 5e520fa0eb6d9ad0cf329fa2572250588a3e365e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1333 zcmb7D+j7!S6kVqQ0yMqRN-eF{OSM2R5w-OK(}AH;8M$@O@?7jBdJL~-T`Q-vY3eQE1FeF=cQ*O0&t8JJqNA7CJ zj%I$4tGQZb|4?r@OV##)=IEu?fiA+wFn*{VYqF_XO0l;66d@(I;7`VGrKx%#juys33MX^(;{_CYt?mSm~0 z+UnX3{e{5?I)3Hnbsk7vsz%e&oUTnDw>*42IWvsZEh;4yEK9dtZF)zpSM@bu~ z{un8UQT1ioJti;TaU*yXU6sC~6!pV95|b+nXSh2c2~Ys~Ns_x4vBX=WvwOJTPv4|c zJU!aOV*Ry{yr^fm%91dDj^)))^yO00B^$ev5F*R0_c@Xj!)t{jEO`$3JJ{dz1Uz&( UA5lY`djp$1lkyp!;8}L=7v>5tU;qFB diff --git a/androidgcs/bin/org/openpilot/uavtalk/UAVObject.class b/androidgcs/bin/org/openpilot/uavtalk/UAVObject.class deleted file mode 100644 index 5e228155303a29cd063056a485473fdd564000c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2255 zcma)7+j84f6kW%5?8X*pE=`&XX_}I>veMQKv_P9Q#7R;+4w9T1 z_>|5tJo3T=x1xuNphhm`24GkU0s;aMRcmp@72&*p2M`p|R zm1_-CS$l;9{*Spz>^C)ZB2Vx9#};dkpPtyBh>m6`QpO3|?M<+a6c)%UPb|~6zNH`; zy;`iPV()0k;fz2hS*v+fQg+8J z!xEPBcz{|C>jFLT$VA&Te1cCoA$z9XlB>WYy!s0Uo}q8VIKYMP zQTP*=9zMs!UqN)>8l#g3C_aln7+3dEG8muU$E~>BaKL_)uoqZpjED6i-o`lQd2J{P zMpzJUF{=K`xXq4K7v-SyRPc5OGt@(17I!16bEK-iWsQ-2%*FNcL3EP2mjnEPa90~Y z8|cV;n+%l7O0^Q7s$z%n8|HrGOHwI4fYHJY5sVQ+`Vb9;X1Uy!)7R{#J2 diff --git a/androidgcs/bin/org/openpilot/uavtalk/UAVObjectManager.class b/androidgcs/bin/org/openpilot/uavtalk/UAVObjectManager.class deleted file mode 100644 index f4a6dd7e4e5820644e459a4aa5652e5f2a69beba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5422 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 diff --git a/androidgcs/bin/resources.ap_ b/androidgcs/bin/resources.ap_ deleted file mode 100644 index 2452fd26f12793bb5445461ce339266070961506..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140460 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¾q8|{@x1yCdLS19 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 diff --git a/androidgcs/default.properties b/androidgcs/default.properties index e2e8061f2..46769a720 100644 --- a/androidgcs/default.properties +++ b/androidgcs/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-8 +target=android-7 diff --git a/androidgcs/gen/org/openpilot/androidgcs/R.java b/androidgcs/gen/org/openpilot/androidgcs/R.java deleted file mode 100644 index 31e90ffd1..000000000 --- a/androidgcs/gen/org/openpilot/androidgcs/R.java +++ /dev/null @@ -1,31 +0,0 @@ -/* AUTO-GENERATED FILE. DO NOT MODIFY. - * - * This class was automatically generated by the - * aapt tool from the resource data it found. It - * should not be modified by hand. - */ - -package org.openpilot.androidgcs; - -public final class R { - public static final class attr { - } - public static final class color { - public static final int all_black=0x7f050001; - public static final int all_white=0x7f050000; - } - public static final class drawable { - public static final int icon=0x7f020000; - } - public static final class id { - public static final int objects=0x7f060000; - } - public static final class layout { - public static final int main=0x7f030000; - public static final int objectbrowser=0x7f030001; - } - public static final class string { - public static final int app_name=0x7f040001; - public static final int hello=0x7f040000; - } -} diff --git a/androidgcs/res/drawable-hdpi/icon.png b/androidgcs/res/drawable-hdpi/icon.png index eab1fc68fd7ad531ac025a53956f78de8d4e5180..8074c4c571b8cd19e27f4ee5545df367420686d7 100644 GIT binary patch literal 4147 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 literal 48558 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
r;9m-R5IG*#GkMUl(F+3 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 H&ZK_;Db+pY diff --git a/androidgcs/res/drawable-ldpi/icon.png b/androidgcs/res/drawable-ldpi/icon.png index eab1fc68fd7ad531ac025a53956f78de8d4e5180..1095584ec21f71cd0afc9e0993aa2209671b590c 100644 GIT binary patch literal 1723 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 H&ZK_;Db+pY diff --git a/androidgcs/res/drawable-mdpi/icon.png b/androidgcs/res/drawable-mdpi/icon.png index eab1fc68fd7ad531ac025a53956f78de8d4e5180..a07c69fa5a0f4da5d5efe96eea12a543154dbab6 100644 GIT binary patch literal 2574 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 H&ZK_;Db+pY diff --git a/androidgcs/res/layout/objectbrowser.xml b/androidgcs/res/layout/objectbrowser.xml deleted file mode 100644 index 02a3f5dd6..000000000 --- a/androidgcs/res/layout/objectbrowser.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index eba6becf8..0d9f93bc2 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -1,7 +1,5 @@ - OpenPilot Android GCS - OpieMobi - #FFFFFF - #000000 + Hello World! + OpenPilot GCS diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.java b/androidgcs/src/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.java deleted file mode 100644 index 190668d80..000000000 --- a/androidgcs/src/org/openpilot/androidgcs/ObjBrowserExpandableListAdapter.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * - */ -package org.openpilot.androidgcs; - -import android.widget.AbsListView; -import android.widget.TextView; -import android.content.Context; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseExpandableListAdapter; - -/** - * @author jcotton81 - * - */ -public class ObjBrowserExpandableListAdapter extends BaseExpandableListAdapter { - - // Sample data set. children[i] contains the children (String[]) for - // groups[i]. - private String[] groups = { "Parent1", "Parent2", "Parent3" }; - private String[][] children = { { "Child1" },{ "Child2" }, { "Child3" },{ "Child4" }, { "Child5" } }; - - private Context context; - - public ObjBrowserExpandableListAdapter(Context context) { - this.context = context; - } - - public Object getChild(int groupPosition, int childPosition) { - return children[groupPosition][childPosition]; - } - - public long getChildId(int groupPosition, int childPosition) { - return childPosition; - } - - public int getChildrenCount(int groupPosition) { - int i = 0; - try { - i = children[groupPosition].length; - - } catch (Exception e) { - } - - return i; - } - - public TextView getGenericView() { - // Layout parameters for the ExpandableListView - AbsListView.LayoutParams lp = new AbsListView.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, 64); - - TextView textView = new TextView(context); - textView.setLayoutParams(lp); - // Center the text vertically - textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); - // Set the text starting position - textView.setPadding(36, 0, 0, 0); - return textView; - } - - public View getChildView(int groupPosition, int childPosition, - boolean isLastChild, View convertView, ViewGroup parent) { - TextView textView = getGenericView(); - textView.setText(getChild(groupPosition, childPosition).toString()); - return textView; - } - - public Object getGroup(int groupPosition) { - return groups[groupPosition]; - } - - public int getGroupCount() { - return groups.length; - } - - public long getGroupId(int groupPosition) { - return groupPosition; - } - - public View getGroupView(int groupPosition, boolean isExpanded, - View convertView, ViewGroup parent) { - TextView textView = getGenericView(); - textView.setText(getGroup(groupPosition).toString()); - return textView; - } - - public boolean isChildSelectable(int groupPosition, int childPosition) { - return true; - } - - public boolean hasStableIds() { - return true; - } - - -} diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java deleted file mode 100644 index 19e9b2812..000000000 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.openpilot.androidgcs; - -import android.app.Activity; -import android.os.Bundle; - -import android.widget.*; - -public class ObjectBrowser extends Activity { - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.objectbrowser); - ExpandableListAdapter mAdapter; - ExpandableListView epView = (ExpandableListView) findViewById(R.id.objects); - mAdapter = new ObjBrowserExpandableListAdapter(this); - epView.setAdapter(mAdapter); - - } -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java index a1e5773b9..e5197b02e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java @@ -2,13 +2,11 @@ package org.openpilot.uavtalk; public class UAVMetaObject extends UAVObject { - public UAVMetaObject(int objID, Boolean isSingleInst, String name) { - super(objID, isSingleInst, name); - // TODO Auto-generated constructor stub - } - - public UAVMetaObject(int objID, String mname, UAVDataObject obj) { - // TODO Auto-generated constructor stub + private UAVDataObject parent; + + public UAVMetaObject(int objID, String mname, UAVDataObject parent) { + super(objID, true, mname); + this.parent = parent; } @Override From 7ab3f5b47eebe4a1f6ee3396b4cdbaab4dd793b8 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 1 Mar 2011 22:27:58 -0600 Subject: [PATCH 003/284] Update the object template to be more consistent with ground code --- .../templates/uavobjecttemplate.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java index 285ad03aa..13eeeb724 100644 --- a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java +++ b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java @@ -29,30 +29,31 @@ package org.openpilot.uavtalk.uavobjects; import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVObjectMetaData; -import org.openpilot.uavtalk.UAVObjectFieldDescription; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVMetaObject; + /** $(DESCRIPTION) generated from $(XMLFILE) **/ -public class $(NAME) extends UAVObject{ +public class $(NAME) extends UAVDataObject{ $(FIELDSINIT) public void setGeneratedMetaData() { - getMetaData().gcsAccess = UAVObjectMetaData.$(GCSACCESS); - getMetaData().gcsTelemetryAcked = UAVObjectMetaData.$(GCSTELEM_ACKEDTF); - getMetaData().gcsTelemetryUpdateMode = UAVObjectMetaData.$(GCSTELEM_UPDATEMODE); + getMetaData().gcsAccess = UAVMetaObject.$(GCSACCESS); + getMetaData().gcsTelemetryAcked = UAVMetaObject.$(GCSTELEM_ACKEDTF); + getMetaData().gcsTelemetryUpdateMode = UAVMetaObject.$(GCSTELEM_UPDATEMODE); getMetaData().gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD); - getMetaData().flightAccess = UAVObjectMetaData.$(FLIGHTACCESS); - getMetaData().flightTelemetryAcked = UAVObjectMetaData.$(FLIGHTTELEM_ACKEDTF); - getMetaData().flightTelemetryUpdateMode = UAVObjectMetaData.$(FLIGHTTELEM_UPDATEMODE); + getMetaData().flightAccess = UAVMetaObject.$(FLIGHTACCESS); + getMetaData().flightTelemetryAcked = UAVMetaObject.$(FLIGHTTELEM_ACKEDTF); + getMetaData().flightTelemetryUpdateMode = UAVMetaObject.$(FLIGHTTELEM_UPDATEMODE); getMetaData().flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD); - getMetaData().loggingUpdateMode = UAVObjectMetaData.$(LOGGING_UPDATEMODE); + getMetaData().loggingUpdateMode = UAVMetaObject.$(LOGGING_UPDATEMODE); getMetaData().loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD); } @@ -65,7 +66,7 @@ $(FIELDSINIT) return "$(NAME)"; } - public String getObjDescription() { + public String getDescription() { return "$(DESCRIPTION)"; } From 0abd2ee6719138e3dc36d2ee1117d935c877acdd Mon Sep 17 00:00:00 2001 From: James Cotton Date: Wed, 2 Mar 2011 20:23:27 -0600 Subject: [PATCH 004/284] Continuing to work on the java code to be more consistent with GCS code --- androidgcs/.classpath | 1 + .../org/openpilot/uavtalk/UAVDataObject.java | 34 +++++++++++--- .../org/openpilot/uavtalk/UAVMetaObject.java | 47 +++++++++++++++---- .../src/org/openpilot/uavtalk/UAVObject.java | 36 ++++++++++---- .../templates/uavobjecttemplate.java | 30 ++++++++---- 5 files changed, 117 insertions(+), 31 deletions(-) diff --git a/androidgcs/.classpath b/androidgcs/.classpath index 609aa00eb..b24a2abf5 100644 --- a/androidgcs/.classpath +++ b/androidgcs/.classpath @@ -3,5 +3,6 @@ + diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java index 12a4263c0..a2e6acf9e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java @@ -2,17 +2,20 @@ package org.openpilot.uavtalk; public abstract class UAVDataObject extends UAVObject { + /** + * @brief Constructor for UAVDataObject + * @param objID the object id to be created + * @param isSingleInst + * @param isSet + * @param name + */ public UAVDataObject(int objID, Boolean isSingleInst, Boolean isSet, String name) { super(objID, isSingleInst, name); } - public void initialize(int instID, UAVMetaObject mobj) { - - } + public abstract void initialize(int instID, UAVMetaObject mobj); - public void initialize(UAVMetaObject mobj) { - - } + public abstract void initialize(UAVMetaObject mobj); Boolean isSettings() { return null; @@ -22,6 +25,23 @@ public abstract class UAVDataObject extends UAVObject { return null; } - public abstract UAVDataObject clone(int instID); + public UAVDataObject clone(int instID) { + try { + return (UAVDataObject) super.clone(); + } catch (CloneNotSupportedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + +public: + static int OBJID = $(OBJIDHEX); + static String NAME; + static String DESCRIPTION; + static boolean ISSINGLEINST = $(ISSINGLEINST); + static boolean ISSETTINGS = $(ISSETTINGS); + static int NUMBYTES = sizeof(DataFields); + } diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java index e5197b02e..9c2e3b12d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java @@ -2,23 +2,41 @@ package org.openpilot.uavtalk; public class UAVMetaObject extends UAVObject { - private UAVDataObject parent; - - public UAVMetaObject(int objID, String mname, UAVDataObject parent) { - super(objID, true, mname); + public UAVMetaObject(int objID, String name, UAVDataObject parent) { + super(objID, true, name); this.parent = parent; + + ownMetadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + ownMetadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + ownMetadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + ownMetadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + ownMetadata.flightTelemetryUpdatePeriod = 0; + ownMetadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + ownMetadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + ownMetadata.gcsTelemetryUpdatePeriod = 0; + ownMetadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + ownMetadata.loggingUpdatePeriod = 0; + + } + + UAVObject getParentObject() { + return parent; } @Override public void deserialize(byte[] arr, int offset) { // TODO Auto-generated method stub - + } @Override - public UAVMetaObject getDefaultMetadata() { - // TODO Auto-generated method stub - return null; + public Metadata getMetadata() { + return ownMetadata; + } + + @Override + public Metadata getDefaultMetadata() { + return ownMetadata; } @Override @@ -45,4 +63,17 @@ public class UAVMetaObject extends UAVObject { return null; } + + public UAVMetaObject(quint32 objID, const QString& name, UAVObject* parent); + UAVObject* getParentObject(); + void setMetadata(const Metadata& mdata); + void setData(const Metadata& mdata); + Metadata getData(); + + + private UAVObject parent; + private Metadata ownMetadata; + private Metadata parentMetadata; + + } diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index c5ffc9d21..1decf3563 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -20,11 +20,27 @@ public abstract class UAVObject { ACCESS_READWRITE, ACCESS_READONLY } ; - - - private Boolean isSingleInst; - private int instID; - private UAVMetaObject meta; + + /** + * Access mode + */ + public enum Acked{ + FALSE, + TRUE + } ; + + final class Metadata { + public AccessMode flightAccess; /** Defines the access level for the local flight transactions (readonly and readwrite) */ + public AccessMode gcsAccess; /** Defines the access level for the local GCS transactions (readonly and readwrite) */ + public Acked flightTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */ + public UpdateMode flightTelemetryUpdateMode; /** Update mode used by the autopilot (UpdateMode) */ + public int flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */ + public Acked gcsTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */ + public UpdateMode gcsTelemetryUpdateMode; /** Update mode used by the GCS (UpdateMode) */ + public int gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ + public UpdateMode loggingUpdateMode; /** Update mode used by the logging module (UpdateMode) */ + public int loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */ + } ; public UAVObject(int objID, Boolean isSingleInst, String name) { assert(objID == getObjID()); // ID is in implementation code, make sure it matches object @@ -62,9 +78,13 @@ public abstract class UAVObject { return true; } - public void setMetadata(UAVMetaObject obj) { meta = obj; } - public UAVMetaObject getMetadata() { return meta; } - public abstract UAVMetaObject getDefaultMetadata(); + public abstract void setMetadata(Metadata obj); + public abstract Metadata getMetadata(); + public abstract Metadata getDefaultMetadata(); + + private Boolean isSingleInst; + private int instID; + private UAVMetaObject meta; /* // Unported code from QT diff --git a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java index 13eeeb724..fa09f782f 100644 --- a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java +++ b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java @@ -31,29 +31,34 @@ package org.openpilot.uavtalk.uavobjects; import org.openpilot.uavtalk.UAVObject; import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVMetaObject; +import org.openpilot.uavtalk.UAVObjectField; /** $(DESCRIPTION) generated from $(XMLFILE) **/ -public class $(NAME) extends UAVDataObject{ +public class $(NAME) extends UAVDataObject { $(FIELDSINIT) + public $(NAME) (int objID, Boolean isSingleInst, Boolean isSet, String name) { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + } + public void setGeneratedMetaData() { - getMetaData().gcsAccess = UAVMetaObject.$(GCSACCESS); - getMetaData().gcsTelemetryAcked = UAVMetaObject.$(GCSTELEM_ACKEDTF); - getMetaData().gcsTelemetryUpdateMode = UAVMetaObject.$(GCSTELEM_UPDATEMODE); + getMetaData().gcsAccess = UAVObject.AccessMode.$(GCSACCESS); + getMetaData().gcsTelemetryAcked = UAVObject.Acked.$(GCSTELEM_ACKEDTF); + getMetaData().gcsTelemetryUpdateMode = UAVObject.UpdateMode.$(GCSTELEM_UPDATEMODE); getMetaData().gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD); - getMetaData().flightAccess = UAVMetaObject.$(FLIGHTACCESS); - getMetaData().flightTelemetryAcked = UAVMetaObject.$(FLIGHTTELEM_ACKEDTF); - getMetaData().flightTelemetryUpdateMode = UAVMetaObject.$(FLIGHTTELEM_UPDATEMODE); + getMetaData().flightAccess = UAVObject.AccessMode.$(FLIGHTACCESS); + getMetaData().flightTelemetryAcked = UAVObject.Acked.$(FLIGHTTELEM_ACKEDTF); + getMetaData().flightTelemetryUpdateMode = UAVObject.UpdateMode.$(FLIGHTTELEM_UPDATEMODE); getMetaData().flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD); - getMetaData().loggingUpdateMode = UAVMetaObject.$(LOGGING_UPDATEMODE); + getMetaData().loggingUpdateMode = UAVObject.UpdateMode.$(LOGGING_UPDATEMODE); getMetaData().loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD); } @@ -69,6 +74,15 @@ $(FIELDSINIT) public String getDescription() { return "$(DESCRIPTION)"; } +protected: + // Constants + static final int OBJID = $(OBJIDHEX); + static final String NAME; + static final String DESCRIPTION; + static final boolean ISSINGLEINST = $(ISSINGLEINST); + static final boolean ISSETTINGS = $(ISSETTINGS); + static final int NUMBYTES = sizeof(DataFields); + $(GETTERSETTER) } \ No newline at end of file From 180f87dae5131db611264e24be570c9ba1306265 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Fri, 4 Mar 2011 00:06:17 -0600 Subject: [PATCH 005/284] Import of UAVObjectField object. This differs a bit from the GCS implementation in that the data is stored within the field instead of being packed back into a continugious memory region. This is because java doesn't allow casting to struct so the memory access isn't a useful feature. --- .../org/openpilot/uavtalk/UAVObjectField.java | 468 ++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java new file mode 100644 index 000000000..832e7048a --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -0,0 +1,468 @@ +package org.openpilot.uavtalk; + +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; + +public class UAVObjectField { + + public enum FieldType { INT8, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, STRING }; + + public UAVObjectField(String name, String units, FieldType type, int numElements, List options) { + List elementNames = new ArrayList(); + // Set element names + for (int n = 0; n < numElements; ++n) + { + elementNames.add(String.valueOf(n)); + } + // Initialize + constructorInitialize(name, units, type, elementNames, options); + } + + public UAVObjectField(String name, String units, FieldType type, List elementNames, List options) { + constructorInitialize(name, units, type, elementNames, options); + } + + public void initialize(byte[] data, int dataOffset, UAVObject obj){ + this.data = data; + this.offset = dataOffset; + this.obj = obj; + clear(); + + } + + public UAVObject getObject() { + return obj; + } + + public FieldType getType() { + return type; + } + + public String getTypeAsString() { + switch (type) + { + case INT8: + return "int8"; + case INT16: + return "int16"; + case INT32: + return "int32"; + case UINT8: + return "uint8"; + case UINT16: + return "uint16"; + case UINT32: + return "uint32"; + case FLOAT32: + return "float32"; + case ENUM: + return "enum"; + case STRING: + return "string"; + default: + return ""; + } + } + + public String getName() { + return name; + } + + public String getUnits() { + return units; + } + + public int getNumElements() { + return numElements; + } + + public List getElementNames() { + return elementNames; + } + + public List getOptions() { + return options; + } + + /** + * This function copies this field from the internal storage of the parent object + * to a new ByteBuffer for UAVTalk. It also converts from the java standard (big endian) + * to the arm/uavtalk standard (little endian) + * @param dataOut + * @return +] + * @throws Exception */ + public int pack(ByteBuffer dataOut) throws Exception { + //QMutexLocker locker(obj->getMutex()); + // Pack each element in output buffer + dataOut.order(ByteOrder.LITTLE_ENDIAN); + switch (type) + { + case INT8: + for (int index = 0; index < numElements; ++index) + dataOut.put((Byte) getValue(index)); + break; + case INT16: + for (int index = 0; index < numElements; ++index) + dataOut.putShort((Short) getValue(index)); + break; + case INT32: + for (int index = 0; index < numElements; ++index) + dataOut.putInt((Integer) getValue(index)); + break; + case UINT8: + // TODO: Deal properly with unsigned + for (int index = 0; index < numElements; ++index) + dataOut.put((Byte) getValue(index)); + break; + case UINT16: + // TODO: Deal properly with unsigned + for (int index = 0; index < numElements; ++index) + dataOut.putShort((Short) getValue(index)); + break; + case UINT32: + // TODO: Deal properly with unsigned + for (int index = 0; index < numElements; ++index) + dataOut.putInt((Integer) getValue(index)); + break; + case FLOAT32: + for (int index = 0; index < numElements; ++index) + dataOut.putFloat((Float) getValue(index)); + break; + case ENUM: + List l = (List) data; + for (int index = 0; index < numElements; ++index) + dataOut.put((Byte) l.get(index)); + break; + case STRING: + // TODO: Implement strings + throw new Exception("Strings not yet implemented"); + } + // Done + return getNumBytes(); + } + + public int unpack(ByteBuffer dataIn) throws Exception { + // Unpack each element from input buffer + dataIn.order(ByteOrder.LITTLE_ENDIAN); + switch (type) + { + case INT8: + for (int index = 0 ; index < numElements; ++index) { + setValue((Byte) dataIn.get(), index); + } + break; + case INT16: + for (int index = 0 ; index < numElements; ++index) { + setValue((Short) dataIn.getShort(), index); + } + break; + case INT32: + for (int index = 0 ; index < numElements; ++index) { + setValue((Integer) dataIn.getInt(), index); + } + break; + case UINT8: + // TODO: Deal with unsigned + for (int index = 0 ; index < numElements; ++index) { + setValue((Byte) dataIn.get(), index); + } + break; + case UINT16: + // TODO: Deal with unsigned + for (int index = 0 ; index < numElements; ++index) { + setValue((Short) dataIn.getShort(), index); + } + break; + case UINT32: + // TODO: Deal with unsigned + for (int index = 0 ; index < numElements; ++index) { + setValue((Integer) dataIn.getInt(), index); + } + break; + case FLOAT32: + for (int index = 0 ; index < numElements; ++index) { + setValue((Float) dataIn.getFloat(), index); + } + break; + case ENUM: + List l = (List) data; + for (int index = 0 ; index < numElements; ++index) { + l.set(index, dataIn.get(index)); + } + break; + case STRING: + throw new Exception("Strings not handled"); + } + // Done + return getNumBytes(); + } + + Object getValue() throws Exception { return getValue(0); }; + Object getValue(int index) throws Exception { +// QMutexLocker locker(obj->getMutex()); + // Check that index is not out of bounds + if ( index >= numElements ) + { + return null; + } + + switch (type) + { + case INT8: + case INT16: + case INT32: + { + List l = (List) data; + return l.get(index); + } + case UINT8: + case UINT16: + case UINT32: + { + // TODO: Correctly deal with unsigned values + List l = (List) data; + return l.get(index); + } + case FLOAT32: + { + List l = (List) data; + return l.get(index); + } + case ENUM: + { + List l = (List) data; + Byte val = l.get(index); + + if(val >= options.size() || val < 0) + throw new Exception("Invalid value for" + name); + + return options.get(val); + } + case STRING: + { + throw new Exception("Shit I should do this"); + } + } + // If this point is reached then we got an invalid type + return null; + } + + public void setValue(Object data) throws Exception { setValue(data,0); } + public void setValue(Object data, int index) throws Exception { + // QMutexLocker locker(obj->getMutex()); + // Check that index is not out of bounds + if ( index >= numElements ) + throw new Exception("Index out of bounds"); + + // Get metadata + UAVObject.Metadata mdata = obj.getMetadata(); + // Update value if the access mode permits + if ( mdata.gcsAccess == UAVObject.AccessMode.ACCESS_READWRITE ) + { + ByteBuffer bbuf = ByteBuffer.allocate(numBytesPerElement); + switch (type) + { + case INT8: + case INT16: + case INT32: + { + List l = (List) data; + l.set(index, (Integer) data); + break; + } + case UINT8: + case UINT16: + case UINT32: + { + List l = (List) data; + l.set(index, (Integer) data); + break; + } + case FLOAT32: + { + List l = (List) data; + l.set(index, (Float) data); + break; + } + case ENUM: + { + byte val = (byte) options.indexOf((String) data); + if(val < 0) throw new Exception("Enumerated value not found"); + List l = (List) data; + l.set(index, val); + break; + } + case STRING: + { + throw new Exception("Sorry I haven't implemented strings yet"); + } + } + } + } + + public double getDouble() throws Exception { return getDouble(0); }; + public double getDouble(int index) throws Exception { + return Double.valueOf((Double) getValue(index)); + } + + void setDouble(double value) throws Exception { setDouble(value, 0); }; + void setDouble(double value, int index) throws Exception { + setValue(value, index); + } + + int getDataOffset() { + return offset; + } + + int getNumBytes() { + return numBytesPerElement * numElements; + } + + int getNumBytesElement() { + return numBytesPerElement; + } + + boolean isNumeric() { + switch (type) + { + case INT8: + return true; + case INT16: + return true; + case INT32: + return true; + case UINT8: + return true; + case UINT16: + return true; + case UINT32: + return true; + case FLOAT32: + return true; + case ENUM: + return false; + case STRING: + return false; + default: + return false; + } + } + + boolean isText() { + switch (type) + { + case INT8: + return false; + case INT16: + return false; + case INT32: + return false; + case UINT8: + return false; + case UINT16: + return false; + case UINT32: + return false; + case FLOAT32: + return false; + case ENUM: + return true; + case STRING: + return true; + default: + return false; + } + } + + public String toString() { + String sout = new String(); + sout += name + ": [ "; + for (int n = 0; n < numElements; ++n) + { + sout += String.valueOf(n) + " "; + } + + sout += "] " + units + "\n"; + return sout; + } + + void fieldUpdated(UAVObjectField field) { + + } + + public void clear() { + // TODO: This accesses a shared array of the parent + } + + public void constructorInitialize(String name, String units, FieldType type, List elementNames, List options) { + // Copy params + this.name = name; + this.units = units; + this.type = type; + this.options = options; + this.numElements = elementNames.size(); + this.offset = 0; + this.data = null; + this.obj = null; + this.elementNames = elementNames; + // Set field size + switch (type) + { + case INT8: + data = (Object) new ArrayList(); + numBytesPerElement = 1; + break; + case INT16: + data = (Object) new ArrayList(); + numBytesPerElement = 2; + break; + case INT32: + data = (Object) new ArrayList(); + numBytesPerElement = 4; + break; + case UINT8: + data = (Object) new ArrayList(); + numBytesPerElement = 1; + break; + case UINT16: + data = (Object) new ArrayList(); + numBytesPerElement = 2; + break; + case UINT32: + data = (Object) new ArrayList(); + numBytesPerElement = 4; + break; + case FLOAT32: + data = (Object) new ArrayList(); + numBytesPerElement = 4; + break; + case ENUM: + data = (Object) new ArrayList(); + numBytesPerElement = 1; + break; + case STRING: + data = (Object) new ArrayList(); + numBytesPerElement = 1; + break; + default: + numBytesPerElement = 0; + } + } + + + private String name; + private String units; + private FieldType type; + private List elementNames; + private List options; + private int numElements; + private int numBytesPerElement; + private int offset; + private Object data; + private UAVObject obj; + +} From b5e1d3bf2969fee97c756cee0f5af278a884375f Mon Sep 17 00:00:00 2001 From: James Cotton Date: Fri, 4 Mar 2011 10:22:11 -0600 Subject: [PATCH 006/284] Some changes to the object field to get it to initialze the array to be the right length --- .../src/org/openpilot/uavtalk/UAVObject.java | 2 +- .../org/openpilot/uavtalk/UAVObjectField.java | 75 ++++++++++++++----- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 1decf3563..aaf32151f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -84,7 +84,7 @@ public abstract class UAVObject { private Boolean isSingleInst; private int instID; - private UAVMetaObject meta; + private Metadata meta; /* // Unported code from QT diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 832e7048a..d09008cbe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -25,10 +25,8 @@ public class UAVObjectField { constructorInitialize(name, units, type, elementNames, options); } - public void initialize(byte[] data, int dataOffset, UAVObject obj){ - this.data = data; - this.offset = dataOffset; - this.obj = obj; + public void initialize(UAVObject obj){ + this.obj = obj; clear(); } @@ -258,10 +256,13 @@ public class UAVObjectField { if ( index >= numElements ) throw new Exception("Index out of bounds"); + System.out.println(data.toString()); + System.out.println(this.data.toString()); + // Get metadata - UAVObject.Metadata mdata = obj.getMetadata(); + //UAVObject.Metadata mdata = obj.getMetadata(); // Update value if the access mode permits - if ( mdata.gcsAccess == UAVObject.AccessMode.ACCESS_READWRITE ) + if ( true ) //mdata.gcsAccess == UAVObject.AccessMode.ACCESS_READWRITE ) { ByteBuffer bbuf = ByteBuffer.allocate(numBytesPerElement); switch (type) @@ -270,7 +271,7 @@ public class UAVObjectField { case INT16: case INT32: { - List l = (List) data; + List l = (List) this.data; l.set(index, (Integer) data); break; } @@ -278,13 +279,13 @@ public class UAVObjectField { case UINT16: case UINT32: { - List l = (List) data; + List l = (List) this.data; l.set(index, (Integer) data); break; } case FLOAT32: { - List l = (List) data; + List l = (List) this.data; l.set(index, (Float) data); break; } @@ -292,7 +293,7 @@ public class UAVObjectField { { byte val = (byte) options.indexOf((String) data); if(val < 0) throw new Exception("Enumerated value not found"); - List l = (List) data; + List l = (List) this.data; l.set(index, val); break; } @@ -395,7 +396,37 @@ public class UAVObjectField { } public void clear() { - // TODO: This accesses a shared array of the parent + switch (type) + { + case INT8: + case INT16: + case INT32: + case UINT8: + case UINT16: + case UINT32: + ((ArrayList) data).clear(); + for(int index = 0; index < numElements; ++index) { + ((ArrayList) data).add(0); + } + break; + case FLOAT32: + ((ArrayList) data).clear(); + for(int index = 0; index < numElements; ++index) { + ((ArrayList) data).add((float) 0); + } + break; + case ENUM: + ((ArrayList) data).clear(); + for(int index = 0; index < numElements; ++index) { + ((ArrayList) data).add((byte)0); + } + break; + case STRING: + // TODO: Add string + break; + default: + numBytesPerElement = 0; + } } public void constructorInitialize(String name, String units, FieldType type, List elementNames, List options) { @@ -410,47 +441,51 @@ public class UAVObjectField { this.obj = null; this.elementNames = elementNames; // Set field size + System.out.println("Initializing: type " + type + this.numElements); + switch (type) { case INT8: - data = (Object) new ArrayList(); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 1; break; case INT16: - data = (Object) new ArrayList(); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 2; break; case INT32: - data = (Object) new ArrayList(); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 4; break; case UINT8: - data = (Object) new ArrayList(); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 1; break; case UINT16: - data = (Object) new ArrayList(); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 2; break; case UINT32: - data = (Object) new ArrayList(); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 4; break; case FLOAT32: - data = (Object) new ArrayList(); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 4; break; case ENUM: - data = (Object) new ArrayList(); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 1; break; case STRING: - data = (Object) new ArrayList(); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 1; break; default: numBytesPerElement = 0; } + clear(); + System.out.println("Initialized: " + this.data.toString()); } From 1c2eb1bf222906c5c70997c5d69ee4d9ccad9925 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 5 Mar 2011 12:29:48 -0600 Subject: [PATCH 007/284] More updates to UAVObject and Field for android app --- .../src/org/openpilot/uavtalk/UAVObject.java | 598 ++++++++++++++---- .../org/openpilot/uavtalk/UAVObjectField.java | 3 +- 2 files changed, 475 insertions(+), 126 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index aaf32151f..f987a03a9 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -1,137 +1,487 @@ package org.openpilot.uavtalk; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.ListIterator; + public abstract class UAVObject { - - - /** - * Object update mode - */ - public enum UpdateMode { - UPDATEMODE_PERIODIC, /** Automatically update object at periodic intervals */ - UPDATEMODE_ONCHANGE, /** Only update object when its data changes */ - UPDATEMODE_MANUAL, /** Manually update object, by calling the updated() function */ - UPDATEMODE_NEVER /** Object is never updated */ - } ; - /** - * Access mode - */ - public enum AccessMode{ - ACCESS_READWRITE, - ACCESS_READONLY - } ; - - /** - * Access mode - */ - public enum Acked{ - FALSE, - TRUE - } ; - - final class Metadata { - public AccessMode flightAccess; /** Defines the access level for the local flight transactions (readonly and readwrite) */ - public AccessMode gcsAccess; /** Defines the access level for the local GCS transactions (readonly and readwrite) */ - public Acked flightTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */ - public UpdateMode flightTelemetryUpdateMode; /** Update mode used by the autopilot (UpdateMode) */ - public int flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */ - public Acked gcsTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */ - public UpdateMode gcsTelemetryUpdateMode; /** Update mode used by the GCS (UpdateMode) */ - public int gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ - public UpdateMode loggingUpdateMode; /** Update mode used by the logging module (UpdateMode) */ - public int loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */ - } ; - public UAVObject(int objID, Boolean isSingleInst, String name) { - assert(objID == getObjID()); // ID is in implementation code, make sure it matches object - assert(name.equals(getName())); - this.isSingleInst = isSingleInst; - meta = getDefaultMetadata(); - }; - - public void initialize(int instID) { - this.instID = instID; - } - - public int getInstID() { return instID; } - public Boolean isSingleInstance() { return isSingleInst; } - public String getName() { return getObjName(); } // matching QT API to the current autogen code - - public abstract int getObjID(); - public abstract String getDescription(); - public abstract String getObjName(); - - int getNumBytes() { - return serialize().length; - } + /** + * Object update mode + */ + public enum UpdateMode { + UPDATEMODE_PERIODIC, /** Automatically update object at periodic intervals */ + UPDATEMODE_ONCHANGE, /** Only update object when its data changes */ + UPDATEMODE_MANUAL, /** Manually update object, by calling the updated() function */ + UPDATEMODE_NEVER /** Object is never updated */ + } ; - // The name of the serializer and deserialize from the autogenerated code - public abstract byte[] serialize(); - public abstract void deserialize(byte[] arr,int offset); - - byte [] pack() { - return serialize(); - } - - Boolean unpack(byte [] data) { - deserialize(data, 0); - return true; - } - - public abstract void setMetadata(Metadata obj); - public abstract Metadata getMetadata(); - public abstract Metadata getDefaultMetadata(); + /** + * Access mode + */ + public enum AccessMode{ + ACCESS_READWRITE, + ACCESS_READONLY + } ; - private Boolean isSingleInst; - private int instID; - private Metadata meta; + /** + * Access mode + */ + public enum Acked{ + FALSE, + TRUE + } ; - /* - // Unported code from QT - bool save(); - bool save(QFile& file); - bool load(); - bool load(QFile& file); - virtual void setMetadata(const Metadata& mdata) = 0; - virtual Metadata getMetadata() = 0; - virtual Metadata getDefaultMetadata() = 0; - void requestUpdate(); - void updated(); - void lock(); - void lock(int timeoutMs); - void unlock(); - QMutex* getMutex(); - qint32 getNumFields(); - QList getFields(); - UAVObjectField* getField(const QString& name); - QString toString(); - QString toStringBrief(); - QString toStringData(); - void emitTransactionCompleted(bool success); + protected final class Metadata { + public AccessMode flightAccess; /** Defines the access level for the local flight transactions (readonly and readwrite) */ + public AccessMode gcsAccess; /** Defines the access level for the local GCS transactions (readonly and readwrite) */ + public Acked flightTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */ + public UpdateMode flightTelemetryUpdateMode; /** Update mode used by the autopilot (UpdateMode) */ + public int flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */ + public Acked gcsTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */ + public UpdateMode gcsTelemetryUpdateMode; /** Update mode used by the GCS (UpdateMode) */ + public int gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ + public UpdateMode loggingUpdateMode; /** Update mode used by the logging module (UpdateMode) */ + public int loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */ + } ; - signals: - void objectUpdated(UAVObject* obj); - void objectUpdatedAuto(UAVObject* obj); - void objectUpdatedManual(UAVObject* obj); - void objectUnpacked(UAVObject* obj); - void updateRequested(UAVObject* obj); - void transactionCompleted(UAVObject* obj, bool success); + public UAVObject(int objID, Boolean isSingleInst, String name) { + this.objID = objID; + this.instID = 0; + this.isSingleInst = isSingleInst; + this.name = name; + // this.mutex = new QMutex(QMutex::Recursive); + }; - private slots: - void fieldUpdated(UAVObjectField* field); + public void initialize(int instID) { + //QMutexLocker locker(mutex); + this.instID = instID; + } - protected: - quint32 objID; - quint32 instID; - bool isSingleInst; - QString name; - QString description; - quint32 numBytes; - QMutex* mutex; - quint8* data; - QList fields; + /** + * Initialize objects' data fields + * @param fields List of fields held by the object + * @param data Pointer to that actual object data, this is needed by the fields to access the data + * @param numBytes Number of bytes in the object (total, including all fields) + * @throws Exception When unable to unpack a field + */ + public void initializeFields(List fields, ByteBuffer data, int numBytes) throws Exception + { + // TODO: QMutexLocker locker(mutex); + this.numBytes = numBytes; + this.data = data; + this.fields = fields; + // Initialize fields + for (int n = 0; n < fields.size(); ++n) + { + fields.get(n).initialize(this); + } + unpack(data); + } - void initializeFields(QList& fields, quint8* data, quint32 numBytes); - void setDescription(const QString& description); - */ + /** + * Get the object ID + */ + public int getObjID() + { + return objID; + } + + /** + * Get the instance ID + */ + public int getInstID() + { + return instID; + } + + /** + * Returns true if this is a single instance object + */ + public boolean isSingleInstance() + { + return isSingleInst; + } + + /** + * Get the name of the object + */ + public String getName() + { + return name; + } + + /** + * Get the description of the object + * @return The description of the object + */ + public String getDescription() + { + return description; + } + + /** + * Set the description of the object + * @param The description of the object + * @return + */ + public void setDescription(String description) + { + this.description = description; + } + + + /** + * Get the total number of bytes of the object's data + */ + public int getNumBytes() + { + return numBytes; + } + + // /** + // * Request that this object is updated with the latest values from the autopilot + // */ + // /* void UAVObject::requestUpdate() + // { + // emit updateRequested(this); + // } */ + // + // /** + // * Signal that the object has been updated + // */ + // /* void UAVObject::updated() + // { + // emit objectUpdatedManual(this); + // emit objectUpdated(this); + // } */ + // + // /** + // * Lock mutex of this object + // */ + // /* void UAVObject::lock() + // { + // mutex->lock(); + // } */ + // + // /** + // * Lock mutex of this object + // */ + // /* void UAVObject::lock(int timeoutMs) + // { + // mutex->tryLock(timeoutMs); + // } */ + // + // /** + // * Unlock mutex of this object + // */ + // /* void UAVObject::unlock() + // { + // mutex->unlock(); + // } */ + // + // /** + // * Get object's mutex + // */ + // QMutex* UAVObject::getMutex() + // { + // return mutex; + // } + + /** + * Get the number of fields held by this object + */ + public int getNumFields() + { + //QMutexLocker locker(mutex); + return fields.size(); + } + + /** + * Get the object's fields + */ + public List getFields() + { + //QMutexLocker locker(mutex); + return fields; + } + + /** + * Get a specific field + * @throws Exception + * @returns The field or NULL if not found + */ + public UAVObjectField getField(String name) throws Exception + { + //QMutexLocker locker(mutex); + // Look for field + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + UAVObjectField field = li.next(); + if(field.getName().equals(name)) + return field; + } + throw new Exception("Field not found"); + } + + /** + * Pack the object data into a byte array + * @param dataOut ByteBuffer to receive the data. + * @throws Exception + * @returns The number of bytes copied + * @note The array must already have enough space allocated for the object + */ + public int pack(ByteBuffer dataOut) throws Exception + { + // QMutexLocker locker(mutex); + if(dataOut.remaining() < getNumBytes()) + throw new Exception("Not enough bytes in ByteBuffer to pack object"); + int numBytes = 0; + + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + UAVObjectField field = li.next(); + numBytes += field.pack(dataOut); + } + return numBytes; + } + + /** + * Unpack the object data from a byte array + * @param dataIn The ByteBuffer to pull data from + * @throws Exception + * @returns The number of bytes copied + */ + public int unpack(ByteBuffer dataIn) throws Exception + { + // QMutexLocker locker(mutex); + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + UAVObjectField field = li.next(); + numBytes += field.unpack(dataIn); + } + return numBytes; + // TODO: Callbacks + //emit objectUnpacked(this); // trigger object updated event + //emit objectUpdated(this); + } + + // /** + // * Save the object data to the file. + // * The file will be created in the current directory + // * and its name will be the same as the object with + // * the .uavobj extension. + // * @returns True on success, false on failure + // */ + // bool UAVObject::save() + // { + // QMutexLocker locker(mutex); + // + // // Open file + // QFile file(name + ".uavobj"); + // if (!file.open(QFile::WriteOnly)) + // { + // return false; + // } + // + // // Write object + // if ( !save(file) ) + // { + // return false; + // } + // + // // Close file + // file.close(); + // return true; + // } + // + // /** + // * Save the object data to the file. + // * The file is expected to be already open for writting. + // * The data will be appended and the file will not be closed. + // * @returns True on success, false on failure + // */ + // bool UAVObject::save(QFile& file) + // { + // QMutexLocker locker(mutex); + // quint8 buffer[numBytes]; + // quint8 tmpId[4]; + // + // // Write the object ID + // qToLittleEndian(objID, tmpId); + // if ( file.write((const char*)tmpId, 4) == -1 ) + // { + // return false; + // } + // + // // Write the instance ID + // if (!isSingleInst) + // { + // qToLittleEndian(instID, tmpId); + // if ( file.write((const char*)tmpId, 2) == -1 ) + // { + // return false; + // } + // } + // + // // Write the data + // pack(buffer); + // if ( file.write((const char*)buffer, numBytes) == -1 ) + // { + // return false; + // } + // + // // Done + // return true; + // } + // + // /** + // * Load the object data from a file. + // * The file will be openned in the current directory + // * and its name will be the same as the object with + // * the .uavobj extension. + // * @returns True on success, false on failure + // */ + // bool UAVObject::load() + // { + // QMutexLocker locker(mutex); + // + // // Open file + // QFile file(name + ".uavobj"); + // if (!file.open(QFile::ReadOnly)) + // { + // return false; + // } + // + // // Load object + // if ( !load(file) ) + // { + // return false; + // } + // + // // Close file + // file.close(); + // return true; + // } + // + // /** + // * Load the object data from file. + // * The file is expected to be already open for reading. + // * The data will be read and the file will not be closed. + // * @returns True on success, false on failure + // */ + // bool UAVObject::load(QFile& file) + // { + // QMutexLocker locker(mutex); + // quint8 buffer[numBytes]; + // quint8 tmpId[4]; + // + // // Read the object ID + // if ( file.read((char*)tmpId, 4) != 4 ) + // { + // return false; + // } + // + // // Check that the IDs match + // if (qFromLittleEndian(tmpId) != objID) + // { + // return false; + // } + // + // // Read the instance ID + // if ( file.read((char*)tmpId, 2) != 2 ) + // { + // return false; + // } + // + // // Check that the IDs match + // if (qFromLittleEndian(tmpId) != instID) + // { + // return false; + // } + // + // // Read and unpack the data + // if ( file.read((char*)buffer, numBytes) != numBytes ) + // { + // return false; + // } + // unpack(buffer); + // + // // Done + // return true; + // } + + /** + * Return a string with the object information + */ + @Override + public String toString() + { + return toStringBrief() + toStringData(); + } + + /** + * Return a string with the object information (only the header) + */ + public String toStringBrief() + { + return String.format("%1 (ID: %2, InstID: %3, NumBytes: %4, SInst: %5)\n", + getName(), + getObjID(), + getInstID(), + getNumBytes(), + isSingleInstance()); + } + + /** + * Return a string with the object information (only the data) + */ + public String toStringData() + { + String s = new String(); + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + UAVObjectField field = li.next(); + s += field.toString(); + } + return s; + } + + // /** + // * Emit the transactionCompleted event (used by the UAVTalk plugin) + // */ + // void UAVObject::emitTransactionCompleted(bool success) + // { + // emit transactionCompleted(this, success); + // } + + /** + * Java specific functions + */ + public UAVObject clone() { + return (UAVObject) clone(); + } + /** + * Abstract functions + */ + public abstract void setMetadata(Metadata mdata); + public abstract Metadata getMetadata(); + public abstract Metadata getDefaultMetadata(); + public abstract UAVDataObject clone(int instID); + protected abstract void setDefaultFieldValues(); + + /** + * Private data for the object, common to all + */ + protected int objID; + protected int instID; + protected boolean isSingleInst; + protected String name; + protected String description; + protected int numBytes; + // TODO: QMutex* mutex; + protected ByteBuffer data; + protected List fields; } diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index d09008cbe..c7c774199 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -90,8 +90,7 @@ public class UAVObjectField { * to a new ByteBuffer for UAVTalk. It also converts from the java standard (big endian) * to the arm/uavtalk standard (little endian) * @param dataOut - * @return -] + * @return the number of bytes added * @throws Exception */ public int pack(ByteBuffer dataOut) throws Exception { //QMutexLocker locker(obj->getMutex()); From a2e93f19716524d9237037f354472a32888827b2 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 00:03:20 -0600 Subject: [PATCH 008/284] More work on the java UAVObject implementation --- .../org/openpilot/uavtalk/UAVDataObject.java | 93 ++- .../org/openpilot/uavtalk/UAVMetaObject.java | 140 +++-- .../src/org/openpilot/uavtalk/UAVObject.java | 581 +++++++++--------- .../org/openpilot/uavtalk/UAVObjectField.java | 35 +- .../openpilot/uavtalk/UAVObjectManager.java | 30 +- 5 files changed, 497 insertions(+), 382 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java index a2e6acf9e..f0a2248f5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java @@ -9,39 +9,78 @@ public abstract class UAVDataObject extends UAVObject { * @param isSet * @param name */ - public UAVDataObject(int objID, Boolean isSingleInst, Boolean isSet, String name) { + public UAVDataObject(int objID, Boolean isSingleInst, Boolean isSet, String name) throws Exception { super(objID, isSingleInst, name); + mobj = null; + this.isSet = isSet; } - - public abstract void initialize(int instID, UAVMetaObject mobj); - - public abstract void initialize(UAVMetaObject mobj); - - Boolean isSettings() { - return null; + /** + * Initialize instance ID and assign a metaobject + */ + public void initialize(int instID, UAVMetaObject mobj) + { + //QMutexLocker locker(mutex); + this.mobj = mobj; + super.initialize(instID); + } + + /** + * Assign a metaobject + */ + public void initialize(UAVMetaObject mobj) + { + //QMutexLocker locker(mutex); + this.mobj = mobj; + } + + /** + * Returns true if this is a data object holding module settings + */ + public boolean isSettings() + { + return isSet; + } + + /** + * Set the object's metadata + */ + public void setMetadata(Metadata mdata) + { + if ( mobj != null ) + { + mobj.setData(mdata); + } + } + + /** + * Get the object's metadata + */ + public Metadata getMetadata() + { + if ( mobj != null) + { + return mobj.getData(); + } + else + { + return getDefaultMetadata(); + } + } + + /** + * Get the metaobject + */ + public UAVMetaObject getMetaObject() + { + return mobj; } - - UAVMetaObject getMetaObject() { - return null; - } + // TODO: Make abstract public UAVDataObject clone(int instID) { - try { - return (UAVDataObject) super.clone(); - } catch (CloneNotSupportedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return null; + return (UAVDataObject) super.clone(); } -public: - static int OBJID = $(OBJIDHEX); - static String NAME; - static String DESCRIPTION; - static boolean ISSINGLEINST = $(ISSINGLEINST); - static boolean ISSETTINGS = $(ISSETTINGS); - static int NUMBYTES = sizeof(DataFields); - + private UAVMetaObject mobj; + private boolean isSet; } diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java index 9c2e3b12d..70e661d46 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java @@ -1,76 +1,116 @@ package org.openpilot.uavtalk; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + public class UAVMetaObject extends UAVObject { - public UAVMetaObject(int objID, String name, UAVDataObject parent) { + public UAVMetaObject(int objID, String name, UAVDataObject parent) throws Exception { super(objID, true, name); this.parent = parent; - - ownMetadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - ownMetadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - ownMetadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - ownMetadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - ownMetadata.flightTelemetryUpdatePeriod = 0; - ownMetadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - ownMetadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - ownMetadata.gcsTelemetryUpdatePeriod = 0; - ownMetadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - ownMetadata.loggingUpdatePeriod = 0; - + + ownMetadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + ownMetadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + ownMetadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + ownMetadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + ownMetadata.flightTelemetryUpdatePeriod = 0; + ownMetadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + ownMetadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + ownMetadata.gcsTelemetryUpdatePeriod = 0; + ownMetadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + ownMetadata.loggingUpdatePeriod = 0; + + // Setup fields + List boolEnum = new ArrayList(); + boolEnum.add("False"); + boolEnum.add("True"); + + List updateModeEnum = new ArrayList(); + updateModeEnum.add("Periodic"); + updateModeEnum.add("On Change"); + updateModeEnum.add("Manual"); + updateModeEnum.add("Never"); + + List accessModeEnum = new ArrayList(); + accessModeEnum.add("Read/Write"); + accessModeEnum.add("Read Only"); + + List fields = new ArrayList(); + fields.add( new UAVObjectField("Flight Access Mode", "", UAVObjectField.FieldType.ENUM, 1, accessModeEnum) ); + fields.add( new UAVObjectField("GCS Access Mode", "", UAVObjectField.FieldType.ENUM, 1, accessModeEnum) ); + fields.add( new UAVObjectField("Flight Telemetry Acked", "", UAVObjectField.FieldType.ENUM, 1, boolEnum) ); + fields.add( new UAVObjectField("Flight Telemetry Update Mode", "", UAVObjectField.FieldType.ENUM, 1, updateModeEnum) ); + fields.add( new UAVObjectField("Flight Telemetry Update Period", "", UAVObjectField.FieldType.UINT32, 1, null) ); + fields.add( new UAVObjectField("GCS Telemetry Acked", "", UAVObjectField.FieldType.ENUM, 1, boolEnum) ); + fields.add( new UAVObjectField("GCS Telemetry Update Mode", "", UAVObjectField.FieldType.ENUM, 1, updateModeEnum) ); + fields.add( new UAVObjectField("GCS Telemetry Update Period", "", UAVObjectField.FieldType.UINT32, 1, null ) ); + fields.add( new UAVObjectField("Logging Update Mode", "", UAVObjectField.FieldType.ENUM, 1, updateModeEnum) ); + fields.add( new UAVObjectField("Logging Update Period", "", UAVObjectField.FieldType.UINT32, 1, null ) ); + + // Initialize parent + super.initialize(0); + super.initializeFields(fields, ByteBuffer.allocate(10), 10); + + // Setup metadata of parent + parentMetadata = parent.getDefaultMetadata(); } - UAVObject getParentObject() { + /** + * Get the parent object + */ + public UAVObject getParentObject() + { return parent; } - @Override - public void deserialize(byte[] arr, int offset) { - // TODO Auto-generated method stub - + /** + * Set the metadata of the metaobject, this function will + * do nothing since metaobjects have read-only metadata. + */ + public void setMetadata(Metadata mdata) + { + return; // can not update metaobject's metadata } - @Override - public Metadata getMetadata() { + /** + * Get the metadata of the metaobject + */ + public Metadata getMetadata() + { return ownMetadata; } - @Override - public Metadata getDefaultMetadata() { - return ownMetadata; + /** + * Get the default metadata + */ + public Metadata getDefaultMetadata() + { + return ownMetadata; } - @Override - public String getDescription() { - // TODO Auto-generated method stub - return null; + /** + * Set the metadata held by the metaobject + */ + public void setData(Metadata mdata) + { + //QMutexLocker locker(mutex); + parentMetadata = mdata; + // TODO: Callbacks + // emit objectUpdatedAuto(this); // trigger object updated event + // emit objectUpdated(this); } - @Override - public int getObjID() { - // TODO Auto-generated method stub - return 0; + /** + * Get the metadata held by the metaobject + */ + public Metadata getData() + { +// QMutexLocker locker(mutex); + return parentMetadata; } - @Override - public String getObjName() { - // TODO Auto-generated method stub - return null; - } - @Override - public byte[] serialize() { - // TODO Auto-generated method stub - return null; - } - - - public UAVMetaObject(quint32 objID, const QString& name, UAVObject* parent); - UAVObject* getParentObject(); - void setMetadata(const Metadata& mdata); - void setData(const Metadata& mdata); - Metadata getData(); - - private UAVObject parent; private Metadata ownMetadata; private Metadata parentMetadata; diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index f987a03a9..926440805 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -6,241 +6,274 @@ import java.util.ListIterator; public abstract class UAVObject { - /** * Object update mode */ public enum UpdateMode { - UPDATEMODE_PERIODIC, /** Automatically update object at periodic intervals */ + UPDATEMODE_PERIODIC, /** + * Automatically update object at periodic + * intervals + */ UPDATEMODE_ONCHANGE, /** Only update object when its data changes */ - UPDATEMODE_MANUAL, /** Manually update object, by calling the updated() function */ - UPDATEMODE_NEVER /** Object is never updated */ - } ; + UPDATEMODE_MANUAL, /** + * Manually update object, by calling the updated() + * function + */ + UPDATEMODE_NEVER + /** Object is never updated */ + }; /** * Access mode */ - public enum AccessMode{ - ACCESS_READWRITE, - ACCESS_READONLY - } ; + public enum AccessMode { + ACCESS_READWRITE, ACCESS_READONLY + }; /** * Access mode */ - public enum Acked{ - FALSE, - TRUE - } ; + public enum Acked { + FALSE, TRUE + }; - protected final class Metadata { - public AccessMode flightAccess; /** Defines the access level for the local flight transactions (readonly and readwrite) */ - public AccessMode gcsAccess; /** Defines the access level for the local GCS transactions (readonly and readwrite) */ - public Acked flightTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */ - public UpdateMode flightTelemetryUpdateMode; /** Update mode used by the autopilot (UpdateMode) */ - public int flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */ - public Acked gcsTelemetryAcked; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */ - public UpdateMode gcsTelemetryUpdateMode; /** Update mode used by the GCS (UpdateMode) */ - public int gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ - public UpdateMode loggingUpdateMode; /** Update mode used by the logging module (UpdateMode) */ - public int loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */ - } ; + public final class Metadata { + public AccessMode flightAccess; + /** + * Defines the access level for the local flight transactions (readonly + * and readwrite) + */ + public AccessMode gcsAccess; + /** + * Defines the access level for the local GCS transactions (readonly and + * readwrite) + */ + public Acked flightTelemetryAcked; + /** + * Defines if an ack is required for the transactions of this object + * (1:acked, 0:not acked) + */ + public UpdateMode flightTelemetryUpdateMode; + /** Update mode used by the autopilot (UpdateMode) */ + public int flightTelemetryUpdatePeriod; + /** + * Update period used by the autopilot (only if telemetry mode is + * PERIODIC) + */ + public Acked gcsTelemetryAcked; + /** + * Defines if an ack is required for the transactions of this object + * (1:acked, 0:not acked) + */ + public UpdateMode gcsTelemetryUpdateMode; + /** Update mode used by the GCS (UpdateMode) */ + public int gcsTelemetryUpdatePeriod; + /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ + public UpdateMode loggingUpdateMode; + /** Update mode used by the logging module (UpdateMode) */ + public int loggingUpdatePeriod; + /** + * Update period used by the logging module (only if logging mode is + * PERIODIC) + */ + }; public UAVObject(int objID, Boolean isSingleInst, String name) { this.objID = objID; this.instID = 0; this.isSingleInst = isSingleInst; this.name = name; - // this.mutex = new QMutex(QMutex::Recursive); + // this.mutex = new QMutex(QMutex::Recursive); }; public void initialize(int instID) { - //QMutexLocker locker(mutex); + // QMutexLocker locker(mutex); this.instID = instID; } /** * Initialize objects' data fields - * @param fields List of fields held by the object - * @param data Pointer to that actual object data, this is needed by the fields to access the data - * @param numBytes Number of bytes in the object (total, including all fields) - * @throws Exception When unable to unpack a field + * + * @param fields + * List of fields held by the object + * @param data + * Pointer to that actual object data, this is needed by the + * fields to access the data + * @param numBytes + * Number of bytes in the object (total, including all fields) + * @throws Exception + * When unable to unpack a field */ - public void initializeFields(List fields, ByteBuffer data, int numBytes) throws Exception - { - // TODO: QMutexLocker locker(mutex); + public void initializeFields(List fields, ByteBuffer data, + int numBytes) throws Exception { + // TODO: QMutexLocker locker(mutex); this.numBytes = numBytes; - this.data = data; +// this.data = data; this.fields = fields; // Initialize fields - for (int n = 0; n < fields.size(); ++n) - { + for (int n = 0; n < fields.size(); ++n) { fields.get(n).initialize(this); } - unpack(data); +// unpack(data); } /** * Get the object ID */ - public int getObjID() - { + public int getObjID() { return objID; } /** * Get the instance ID */ - public int getInstID() - { + public int getInstID() { return instID; } /** * Returns true if this is a single instance object */ - public boolean isSingleInstance() - { + public boolean isSingleInstance() { return isSingleInst; } /** * Get the name of the object */ - public String getName() - { + public String getName() { return name; } /** * Get the description of the object + * * @return The description of the object */ - public String getDescription() - { + public String getDescription() { return description; } /** * Set the description of the object - * @param The description of the object - * @return + * + * @param The + * description of the object + * @return */ - public void setDescription(String description) - { + public void setDescription(String description) { this.description = description; } - /** * Get the total number of bytes of the object's data */ - public int getNumBytes() - { + public int getNumBytes() { return numBytes; } - // /** - // * Request that this object is updated with the latest values from the autopilot - // */ - // /* void UAVObject::requestUpdate() - // { - // emit updateRequested(this); - // } */ + // /** + // * Request that this object is updated with the latest values from the + // autopilot + // */ + // /* void UAVObject::requestUpdate() + // { + // emit updateRequested(this); + // } */ // - // /** - // * Signal that the object has been updated - // */ - // /* void UAVObject::updated() - // { - // emit objectUpdatedManual(this); - // emit objectUpdated(this); - // } */ + // /** + // * Signal that the object has been updated + // */ + // /* void UAVObject::updated() + // { + // emit objectUpdatedManual(this); + // emit objectUpdated(this); + // } */ // - // /** - // * Lock mutex of this object - // */ - // /* void UAVObject::lock() - // { - // mutex->lock(); - // } */ + // /** + // * Lock mutex of this object + // */ + // /* void UAVObject::lock() + // { + // mutex->lock(); + // } */ // - // /** - // * Lock mutex of this object - // */ - // /* void UAVObject::lock(int timeoutMs) - // { - // mutex->tryLock(timeoutMs); - // } */ + // /** + // * Lock mutex of this object + // */ + // /* void UAVObject::lock(int timeoutMs) + // { + // mutex->tryLock(timeoutMs); + // } */ // - // /** - // * Unlock mutex of this object - // */ - // /* void UAVObject::unlock() - // { - // mutex->unlock(); - // } */ + // /** + // * Unlock mutex of this object + // */ + // /* void UAVObject::unlock() + // { + // mutex->unlock(); + // } */ // - // /** - // * Get object's mutex - // */ - // QMutex* UAVObject::getMutex() - // { - // return mutex; - // } + // /** + // * Get object's mutex + // */ + // QMutex* UAVObject::getMutex() + // { + // return mutex; + // } /** * Get the number of fields held by this object */ - public int getNumFields() - { - //QMutexLocker locker(mutex); + public int getNumFields() { + // QMutexLocker locker(mutex); return fields.size(); } /** * Get the object's fields */ - public List getFields() - { - //QMutexLocker locker(mutex); + public List getFields() { + // QMutexLocker locker(mutex); return fields; } /** * Get a specific field - * @throws Exception + * + * @throws Exception * @returns The field or NULL if not found */ - public UAVObjectField getField(String name) throws Exception - { - //QMutexLocker locker(mutex); + public UAVObjectField getField(String name) { + // QMutexLocker locker(mutex); // Look for field ListIterator li = fields.listIterator(); - while(li.hasNext()) { + while (li.hasNext()) { UAVObjectField field = li.next(); - if(field.getName().equals(name)) + if (field.getName().equals(name)) return field; } - throw new Exception("Field not found"); + //throw new Exception("Field not found"); + return null; } /** * Pack the object data into a byte array - * @param dataOut ByteBuffer to receive the data. - * @throws Exception + * + * @param dataOut + * ByteBuffer to receive the data. + * @throws Exception * @returns The number of bytes copied * @note The array must already have enough space allocated for the object */ - public int pack(ByteBuffer dataOut) throws Exception - { + public int pack(ByteBuffer dataOut) throws Exception { // QMutexLocker locker(mutex); - if(dataOut.remaining() < getNumBytes()) + if (dataOut.remaining() < getNumBytes()) throw new Exception("Not enough bytes in ByteBuffer to pack object"); int numBytes = 0; ListIterator li = fields.listIterator(); - while(li.hasNext()) { + while (li.hasNext()) { UAVObjectField field = li.next(); numBytes += field.pack(dataOut); } @@ -249,232 +282,232 @@ public abstract class UAVObject { /** * Unpack the object data from a byte array - * @param dataIn The ByteBuffer to pull data from - * @throws Exception + * + * @param dataIn + * The ByteBuffer to pull data from + * @throws Exception * @returns The number of bytes copied */ - public int unpack(ByteBuffer dataIn) throws Exception - { + public int unpack(ByteBuffer dataIn) throws Exception { + if( dataIn == null ) + return 0; + System.out.println( dataIn.toString() ); // QMutexLocker locker(mutex); int numBytes = 0; ListIterator li = fields.listIterator(); - while(li.hasNext()) { + while (li.hasNext()) { UAVObjectField field = li.next(); + System.out.println(field.toString()); numBytes += field.unpack(dataIn); } return numBytes; // TODO: Callbacks - //emit objectUnpacked(this); // trigger object updated event - //emit objectUpdated(this); + // emit objectUnpacked(this); // trigger object updated event + // emit objectUpdated(this); } - // /** - // * Save the object data to the file. - // * The file will be created in the current directory - // * and its name will be the same as the object with - // * the .uavobj extension. - // * @returns True on success, false on failure - // */ - // bool UAVObject::save() - // { - // QMutexLocker locker(mutex); + // /** + // * Save the object data to the file. + // * The file will be created in the current directory + // * and its name will be the same as the object with + // * the .uavobj extension. + // * @returns True on success, false on failure + // */ + // bool UAVObject::save() + // { + // QMutexLocker locker(mutex); // - // // Open file - // QFile file(name + ".uavobj"); - // if (!file.open(QFile::WriteOnly)) - // { - // return false; - // } + // // Open file + // QFile file(name + ".uavobj"); + // if (!file.open(QFile::WriteOnly)) + // { + // return false; + // } // - // // Write object - // if ( !save(file) ) - // { - // return false; - // } + // // Write object + // if ( !save(file) ) + // { + // return false; + // } // - // // Close file - // file.close(); - // return true; - // } + // // Close file + // file.close(); + // return true; + // } // - // /** - // * Save the object data to the file. - // * The file is expected to be already open for writting. - // * The data will be appended and the file will not be closed. - // * @returns True on success, false on failure - // */ - // bool UAVObject::save(QFile& file) - // { - // QMutexLocker locker(mutex); - // quint8 buffer[numBytes]; - // quint8 tmpId[4]; + // /** + // * Save the object data to the file. + // * The file is expected to be already open for writting. + // * The data will be appended and the file will not be closed. + // * @returns True on success, false on failure + // */ + // bool UAVObject::save(QFile& file) + // { + // QMutexLocker locker(mutex); + // quint8 buffer[numBytes]; + // quint8 tmpId[4]; // - // // Write the object ID - // qToLittleEndian(objID, tmpId); - // if ( file.write((const char*)tmpId, 4) == -1 ) - // { - // return false; - // } + // // Write the object ID + // qToLittleEndian(objID, tmpId); + // if ( file.write((const char*)tmpId, 4) == -1 ) + // { + // return false; + // } // - // // Write the instance ID - // if (!isSingleInst) - // { - // qToLittleEndian(instID, tmpId); - // if ( file.write((const char*)tmpId, 2) == -1 ) - // { - // return false; - // } - // } + // // Write the instance ID + // if (!isSingleInst) + // { + // qToLittleEndian(instID, tmpId); + // if ( file.write((const char*)tmpId, 2) == -1 ) + // { + // return false; + // } + // } // - // // Write the data - // pack(buffer); - // if ( file.write((const char*)buffer, numBytes) == -1 ) - // { - // return false; - // } + // // Write the data + // pack(buffer); + // if ( file.write((const char*)buffer, numBytes) == -1 ) + // { + // return false; + // } // - // // Done - // return true; - // } + // // Done + // return true; + // } // - // /** - // * Load the object data from a file. - // * The file will be openned in the current directory - // * and its name will be the same as the object with - // * the .uavobj extension. - // * @returns True on success, false on failure - // */ - // bool UAVObject::load() - // { - // QMutexLocker locker(mutex); + // /** + // * Load the object data from a file. + // * The file will be openned in the current directory + // * and its name will be the same as the object with + // * the .uavobj extension. + // * @returns True on success, false on failure + // */ + // bool UAVObject::load() + // { + // QMutexLocker locker(mutex); // - // // Open file - // QFile file(name + ".uavobj"); - // if (!file.open(QFile::ReadOnly)) - // { - // return false; - // } + // // Open file + // QFile file(name + ".uavobj"); + // if (!file.open(QFile::ReadOnly)) + // { + // return false; + // } // - // // Load object - // if ( !load(file) ) - // { - // return false; - // } + // // Load object + // if ( !load(file) ) + // { + // return false; + // } // - // // Close file - // file.close(); - // return true; - // } + // // Close file + // file.close(); + // return true; + // } // - // /** - // * Load the object data from file. - // * The file is expected to be already open for reading. - // * The data will be read and the file will not be closed. - // * @returns True on success, false on failure - // */ - // bool UAVObject::load(QFile& file) - // { - // QMutexLocker locker(mutex); - // quint8 buffer[numBytes]; - // quint8 tmpId[4]; + // /** + // * Load the object data from file. + // * The file is expected to be already open for reading. + // * The data will be read and the file will not be closed. + // * @returns True on success, false on failure + // */ + // bool UAVObject::load(QFile& file) + // { + // QMutexLocker locker(mutex); + // quint8 buffer[numBytes]; + // quint8 tmpId[4]; // - // // Read the object ID - // if ( file.read((char*)tmpId, 4) != 4 ) - // { - // return false; - // } + // // Read the object ID + // if ( file.read((char*)tmpId, 4) != 4 ) + // { + // return false; + // } // - // // Check that the IDs match - // if (qFromLittleEndian(tmpId) != objID) - // { - // return false; - // } + // // Check that the IDs match + // if (qFromLittleEndian(tmpId) != objID) + // { + // return false; + // } // - // // Read the instance ID - // if ( file.read((char*)tmpId, 2) != 2 ) - // { - // return false; - // } + // // Read the instance ID + // if ( file.read((char*)tmpId, 2) != 2 ) + // { + // return false; + // } // - // // Check that the IDs match - // if (qFromLittleEndian(tmpId) != instID) - // { - // return false; - // } + // // Check that the IDs match + // if (qFromLittleEndian(tmpId) != instID) + // { + // return false; + // } // - // // Read and unpack the data - // if ( file.read((char*)buffer, numBytes) != numBytes ) - // { - // return false; - // } - // unpack(buffer); + // // Read and unpack the data + // if ( file.read((char*)buffer, numBytes) != numBytes ) + // { + // return false; + // } + // unpack(buffer); // - // // Done - // return true; - // } + // // Done + // return true; + // } /** * Return a string with the object information */ @Override - public String toString() - { + public String toString() { return toStringBrief() + toStringData(); } /** * Return a string with the object information (only the header) */ - public String toStringBrief() - { - return String.format("%1 (ID: %2, InstID: %3, NumBytes: %4, SInst: %5)\n", - getName(), - getObjID(), - getInstID(), - getNumBytes(), - isSingleInstance()); + public String toStringBrief() { + return getName() + " ( " + getObjID() + " " + getInstID() + " " + getNumBytes() + ")\n"; + // getName(), getObjID(), getInstID(), getNumBytes(), + // isSingleInstance()); } /** * Return a string with the object information (only the data) */ - public String toStringData() - { + public String toStringData() { String s = new String(); ListIterator li = fields.listIterator(); - while(li.hasNext()) { + while (li.hasNext()) { UAVObjectField field = li.next(); s += field.toString(); } return s; } - // /** - // * Emit the transactionCompleted event (used by the UAVTalk plugin) - // */ - // void UAVObject::emitTransactionCompleted(bool success) - // { - // emit transactionCompleted(this, success); - // } + // /** + // * Emit the transactionCompleted event (used by the UAVTalk plugin) + // */ + // void UAVObject::emitTransactionCompleted(bool success) + // { + // emit transactionCompleted(this, success); + // } - /** + /** * Java specific functions */ public UAVObject clone() { return (UAVObject) clone(); } + /** * Abstract functions */ public abstract void setMetadata(Metadata mdata); + public abstract Metadata getMetadata(); + public abstract Metadata getDefaultMetadata(); - public abstract UAVDataObject clone(int instID); - protected abstract void setDefaultFieldValues(); /** * Private data for the object, common to all - */ + */ protected int objID; protected int instID; protected boolean isSingleInst; @@ -482,6 +515,6 @@ public abstract class UAVObject { protected String description; protected int numBytes; // TODO: QMutex* mutex; - protected ByteBuffer data; +// protected ByteBuffer data; protected List fields; } diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index c7c774199..b37c992fb 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -248,34 +248,37 @@ public class UAVObjectField { return null; } - public void setValue(Object data) throws Exception { setValue(data,0); } - public void setValue(Object data, int index) throws Exception { + public void setValue(Object data) { setValue(data,0); } + public void setValue(Object data, int index) { // QMutexLocker locker(obj->getMutex()); // Check that index is not out of bounds if ( index >= numElements ) - throw new Exception("Index out of bounds"); + //throw new Exception("Index out of bounds"); System.out.println(data.toString()); System.out.println(this.data.toString()); // Get metadata - //UAVObject.Metadata mdata = obj.getMetadata(); + UAVObject.Metadata mdata = obj.getMetadata(); // Update value if the access mode permits - if ( true ) //mdata.gcsAccess == UAVObject.AccessMode.ACCESS_READWRITE ) + if ( mdata.gcsAccess == UAVObject.AccessMode.ACCESS_READWRITE ) { - ByteBuffer bbuf = ByteBuffer.allocate(numBytesPerElement); switch (type) { case INT8: + data = new Integer((Byte) data); case INT16: + data = new Integer((Short) data); case INT32: { List l = (List) this.data; - l.set(index, (Integer) data); + l.set(index,(Integer) data); break; } case UINT8: + data = new Integer((Byte) data); case UINT16: + data = new Integer((Short) data); case UINT32: { List l = (List) this.data; @@ -291,14 +294,14 @@ public class UAVObjectField { case ENUM: { byte val = (byte) options.indexOf((String) data); - if(val < 0) throw new Exception("Enumerated value not found"); + //if(val < 0) throw new Exception("Enumerated value not found"); List l = (List) this.data; l.set(index, val); break; } case STRING: { - throw new Exception("Sorry I haven't implemented strings yet"); + //throw new Exception("Sorry I haven't implemented strings yet"); } } } @@ -309,24 +312,24 @@ public class UAVObjectField { return Double.valueOf((Double) getValue(index)); } - void setDouble(double value) throws Exception { setDouble(value, 0); }; - void setDouble(double value, int index) throws Exception { + public void setDouble(double value) throws Exception { setDouble(value, 0); }; + public void setDouble(double value, int index) throws Exception { setValue(value, index); } - int getDataOffset() { + public int getDataOffset() { return offset; } - int getNumBytes() { + public int getNumBytes() { return numBytesPerElement * numElements; } - int getNumBytesElement() { + public int getNumBytesElement() { return numBytesPerElement; } - boolean isNumeric() { + public boolean isNumeric() { switch (type) { case INT8: @@ -352,7 +355,7 @@ public class UAVObjectField { } } - boolean isText() { + public boolean isText() { switch (type) { case INT8: diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java index 3091595f0..d75b14b85 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java @@ -21,8 +21,9 @@ public class UAVObjectManager { * A new instance can be created directly by instantiating a new object or by calling clone() of * an existing object. The object will be registered and will be properly initialized so that it can accept * updates. + * @throws Exception */ - Boolean registerObject(UAVDataObject obj) + public boolean registerObject(UAVDataObject obj) throws Exception { // QMutexLocker locker(mutex); @@ -126,7 +127,7 @@ public class UAVObjectManager { return true; } - void addObject(UAVObject obj) + public void addObject(UAVObject obj) { // Add to list List ls = new ArrayList(); @@ -139,7 +140,7 @@ public class UAVObjectManager { * Get all objects. A two dimentional QList is returned. Objects are grouped by * instances of the same object type. */ - List> getObjects() + public List> getObjects() { //QMutexLocker locker(mutex); return objects; @@ -148,7 +149,7 @@ public class UAVObjectManager { /** * Same as getObjects() but will only return DataObjects. */ - List< List > getDataObjects() + public List< List > getDataObjects() { return new ArrayList>(); @@ -186,7 +187,7 @@ public class UAVObjectManager { /** * Same as getObjects() but will only return MetaObjects. */ - List > getMetaObjects() + public List > getMetaObjects() { return new ArrayList< List >(); /* @@ -227,7 +228,7 @@ public class UAVObjectManager { * Get a specific object given its name and instance ID * @returns The object is found or NULL if not */ - UAVObject getObject(String name, int instId) + public UAVObject getObject(String name, int instId) { return getObject(name, 0, instId); } @@ -236,7 +237,7 @@ public class UAVObjectManager { * Get a specific object given its object and instance ID * @returns The object is found or NULL if not */ - UAVObject getObject(int objId, int instId) + public UAVObject getObject(int objId, int instId) { return getObject(null, objId, instId); } @@ -244,7 +245,7 @@ public class UAVObjectManager { /** * Helper function for the public getObject() functions. */ - UAVObject getObject(String name, int objId, int instId) + public UAVObject getObject(String name, int objId, int instId) { //QMutexLocker locker(mutex); // Check if this object type is already in the list @@ -271,7 +272,7 @@ public class UAVObjectManager { /** * Get all the instances of the object specified by name */ - List getObjectInstances(String name) + public List getObjectInstances(String name) { return getObjectInstances(name, 0); } @@ -279,7 +280,7 @@ public class UAVObjectManager { /** * Get all the instances of the object specified by its ID */ - List getObjectInstances(int objId) + public List getObjectInstances(int objId) { return getObjectInstances(null, objId); } @@ -287,7 +288,7 @@ public class UAVObjectManager { /** * Helper function for the public getObjectInstances() */ - List getObjectInstances(String name, int objId) + public List getObjectInstances(String name, int objId) { //QMutexLocker locker(mutex); // Check if this object type is already in the list @@ -307,7 +308,7 @@ public class UAVObjectManager { /** * Get the number of instances for an object given its name */ - int getNumInstances(String name) + public int getNumInstances(String name) { return getNumInstances(name, 0); } @@ -315,7 +316,7 @@ public class UAVObjectManager { /** * Get the number of instances for an object given its ID */ - int getNumInstances(int objId) + public int getNumInstances(int objId) { return getNumInstances(null, objId); } @@ -323,10 +324,9 @@ public class UAVObjectManager { /** * Helper function for public getNumInstances */ - int getNumInstances(String name, int objId) + public int getNumInstances(String name, int objId) { return getObjectInstances(name,objId).size(); } - } From a9066494c76e87151b9bd1cccd808f7a2ae28f65 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 00:03:46 -0600 Subject: [PATCH 009/284] Java autogenerated code to be more compatible with gcs code --- .../templates/uavobjecttemplate.java | 127 +++-- .../java/uavobjectgeneratorjava.cpp | 434 ++++++++---------- .../generators/java/uavobjectgeneratorjava.h | 16 +- 3 files changed, 278 insertions(+), 299 deletions(-) diff --git a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java index fa09f782f..af8f48fce 100644 --- a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java +++ b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java @@ -28,61 +28,110 @@ package org.openpilot.uavtalk.uavobjects; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVMetaObject; -import org.openpilot.uavtalk.UAVObjectField; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVMetaObject; +import org.openpilot.uavtalk.UAVObjectField; /** $(DESCRIPTION) generated from $(XMLFILE) -**/ + **/ public class $(NAME) extends UAVDataObject { + public $(NAME)() throws Exception { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + $(FIELDSINIT) - public $(NAME) (int objID, Boolean isSingleInst, Boolean isSet, String name) { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - } + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytesElement(); + } + NUMBYTES = numBytes; + - public void setGeneratedMetaData() { + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } - getMetaData().gcsAccess = UAVObject.AccessMode.$(GCSACCESS); - getMetaData().gcsTelemetryAcked = UAVObject.Acked.$(GCSTELEM_ACKEDTF); - getMetaData().gcsTelemetryUpdateMode = UAVObject.UpdateMode.$(GCSTELEM_UPDATEMODE); - getMetaData().gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD); + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.$(GCSACCESS); + metadata.gcsTelemetryAcked = UAVObject.Acked.$(GCSTELEM_ACKEDTF); + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.$(GCSTELEM_UPDATEMODE); + metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD); - getMetaData().flightAccess = UAVObject.AccessMode.$(FLIGHTACCESS); - getMetaData().flightTelemetryAcked = UAVObject.Acked.$(FLIGHTTELEM_ACKEDTF); - getMetaData().flightTelemetryUpdateMode = UAVObject.UpdateMode.$(FLIGHTTELEM_UPDATEMODE); - getMetaData().flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD); + metadata.flightAccess = UAVObject.AccessMode.$(FLIGHTACCESS); + metadata.flightTelemetryAcked = UAVObject.Acked.$(FLIGHTTELEM_ACKEDTF); + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.$(FLIGHTTELEM_UPDATEMODE); + metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD); - getMetaData().loggingUpdateMode = UAVObject.UpdateMode.$(LOGGING_UPDATEMODE); - getMetaData().loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD); + metadata.loggingUpdateMode = UAVObject.UpdateMode.$(LOGGING_UPDATEMODE); + metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD); + return metadata; + } - } - - public int getObjID() { - return $(OBJIDHEX); - } - - public String getObjName() { - return "$(NAME)"; - } + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { +$(INITFIELDS) + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + $(NAME) obj = new $(NAME)(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public $(NAME) GetInstance(UAVObjectManager objMngr, int instID) + { + return ($(NAME))(objMngr.getObject($(NAME).OBJID, instID)); + } - public String getDescription() { - return "$(DESCRIPTION)"; - } -protected: // Constants - static final int OBJID = $(OBJIDHEX); - static final String NAME; - static final String DESCRIPTION; - static final boolean ISSINGLEINST = $(ISSINGLEINST); - static final boolean ISSETTINGS = $(ISSETTINGS); - static final int NUMBYTES = sizeof(DataFields); + protected static final int OBJID = $(OBJIDHEX); + protected static final String NAME = "$(NAME)"; + protected static String DESCRIPTION = "$(DESCRIPTION)"; + protected static final boolean ISSINGLEINST = $(ISSINGLEINST) == 1; + protected static final boolean ISSETTINGS = $(ISSETTINGS) == 1; + protected static int NUMBYTES = 0; -$(GETTERSETTER) } \ No newline at end of file diff --git a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp index 6ac45a07a..ce436e6af 100644 --- a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp +++ b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp @@ -24,313 +24,245 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "uavobjectgeneratorjava.h" using namespace std; bool UAVObjectGeneratorJava::generate(UAVObjectParser* parser,QString templatepath,QString outputpath) { - QDir javaTemplatePath = QDir( templatepath + QString(JAVA_TEMPLATE_DIR)); + fieldTypeStrCPP << "qint8" << "qint16" << "qint32" << + "quint8" << "quint16" << "quint32" << "float" << "quint8"; - javaCodePath = QDir ( outputpath + QString(JAVA_GENERATED_DIR)); + fieldTypeStrCPPClass << "INT8" << "INT16" << "INT32" + << "UINT8" << "UINT16" << "UINT32" << "FLOAT32" << "ENUM"; - javaCodeTemplate = readFile( javaTemplatePath.absoluteFilePath("uavobjecttemplate.java") ); - QString javaInitCodeTemplate = readFile( javaTemplatePath.absoluteFilePath("uavobjectsinittemplate.java") ); + javaCodePath = QDir( templatepath + QString(JAVA_TEMPLATE_DIR)); + javaOutputPath = QDir( outputpath + QString("java") ); + javaOutputPath.mkpath(javaOutputPath.absolutePath()); - if (javaCodeTemplate.isEmpty() || javaInitCodeTemplate.isEmpty()) { - std::cerr << "Problem reading java templates" << endl; + javaCodeTemplate = readFile( javaCodePath.absoluteFilePath("uavobjecttemplate.java") ); + QString javaInitTemplate = readFile( javaCodePath.absoluteFilePath("uavobjectsinittemplate.java") ); + + if (javaCodeTemplate.isEmpty() || javaInitTemplate.isEmpty()) { + std::cerr << "Problem reading java code templates" << endl; return false; } - QString javaObjInit,javaObjGetter; - javaCodePath.mkpath(javaCodePath.absolutePath() + "/uavobjects"); + QString objInc; + QString javaObjInit; for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) { ObjectInfo* info=parser->getObjectByIndex(objidx); process_object(info); - if (!javaObjInit.isNull()) - javaObjInit.append(",\n"); - - javaObjInit.append(" new " + info->name + "()"); - javaObjGetter.append(QString(" public static %1 get%1() { return (%1)uavobjects[%2];}\n").arg( info->name).arg(objidx)); + javaObjInit.append(" objMngr->registerObject( new " + info->name + "() );\n"); + objInc.append("#include \"" + info->namelc + ".h\"\n"); } - javaInitCodeTemplate.replace("$(OBJINIT)",javaObjInit); - javaInitCodeTemplate.replace("$(OBJGETTER)",javaObjGetter); - - replaceCommonTags(javaInitCodeTemplate); - - // Write the java object inialization files - bool res = writeFileIfDiffrent(javaCodePath.absolutePath() + "/UAVObjects.java", javaInitCodeTemplate ); + // Write the gcs object inialization files + javaInitTemplate.replace( QString("$(OBJINC)"), objInc); + javaInitTemplate.replace( QString("$(OBJINIT)"), javaObjInit); + bool res = writeFileIfDiffrent( javaOutputPath.absolutePath() + "/uavobjectsinit.java", javaInitTemplate ); if (!res) { - cerr << "Error: Could not write java init output files" << endl; + cout << "Error: Could not write output files" << endl; return false; } return true; // if we come here everything should be fine } -QString UAVObjectGeneratorJava::getFieldTypeStr(int type,bool as_obj) { - - switch(type) { - case FIELDTYPE_INT8: - return (QString(as_obj?"Byte":"byte")); - case FIELDTYPE_INT16: - case FIELDTYPE_INT32: - case FIELDTYPE_UINT8: - case FIELDTYPE_UINT16: - return (QString(as_obj?"Integer":"int")); - case FIELDTYPE_UINT32: - return (QString(as_obj?"Long":"long")); - case FIELDTYPE_FLOAT32: - return (QString(as_obj?"Float":"float")); - case FIELDTYPE_ENUM: - return (QString(as_obj?"Byte":"byte")); - default: - return QString("error: unknown type"); - } -} - -/** - * - * format a value from FieldInfo with a given index (idx) to a java code snippet - * - */ -QString UAVObjectGeneratorJava::formatJavaValue(FieldInfo* info,int idx) { - switch(info->type) { - case FIELDTYPE_ENUM: - return (info->name.toUpper() + QString("_") + info->defaultValues[idx].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "")); - case FIELDTYPE_FLOAT32: - return QString("%1f").arg( info->defaultValues[idx].toFloat() ); - default: - return QString("%1").arg( info->defaultValues[idx].toInt() ); - } -} - -QString UAVObjectGeneratorJava::QStringList2JavaArray(QStringList strl) { - QString csv=QString(); - for (int i = 0; i < strl.length(); i++){ - if (i!=0) - csv.append(QString(",")); - csv.append(QString("\"%1\"").arg(strl[i])); - } - return QString("new String[] { %1 }").arg(csv); -} - -QString UAVObjectGeneratorJava::serializeJavaValue(int type,QString name) -{ - QString res; - switch(type) { - case FIELDTYPE_ENUM: // OK - - case FIELDTYPE_INT8: - res=name; - break; - - case FIELDTYPE_UINT8: - res=QString("(byte)(%1&0xFF)").arg(name); - break; - - case FIELDTYPE_INT16: - case FIELDTYPE_UINT16: - res=QString("(byte)(("+name+">>0)&0xFF) , (byte)(("+name+">>8)&0xFF)"); - break; - - case FIELDTYPE_UINT32: - case FIELDTYPE_INT32: - res=QString("(byte)(("+name+">>0)&0xFF) , (byte)(("+name+">>8)&0xFF) , (byte)(("+name+">>16)&0xFF) , (byte)(("+name+">>24)&0xFF)"); - break; - - case FIELDTYPE_FLOAT32: - res=QString("(byte)((Float.floatToIntBits("+name+")>>0)&0xFF) , (byte)((Float.floatToIntBits("+name+")>>8)&0xFF) , (byte)((Float.floatToIntBits("+name+")>>16)&0xFF) , (byte)((Float.floatToIntBits("+name+")>>24)&0xFF) "); // OK - break; - - default: - res=QString("unresolved type"); - break; - } - - return res; -} - -/** - * this function is used to build the deserializing code - */ -QString UAVObjectGeneratorJava::deSerializeJavaValue(int type,QString name) -{ - switch(type) { - case FIELDTYPE_ENUM: // OK - case FIELDTYPE_INT8: - return (name.append("=arr[pos++];\n")); - - case FIELDTYPE_UINT8: - return (name.append("=arr[pos++]&0xFF;\n")); /*test */ - - case FIELDTYPE_INT16: - case FIELDTYPE_UINT16: - return (name.append("=((arr[pos++]&0xff)<<0) | ((arr[pos++]&0xff)<<8) ;\n")); /* test */ - - case FIELDTYPE_UINT32: - case FIELDTYPE_INT32: - return (name.append("=((arr[pos++]&0xff)<<0) | ((arr[pos++]&0xff)<<8) | ((arr[pos++]&0xff)<<16) | ((arr[pos++]&0xff)<<24) ;\n")); /*test */ - - case FIELDTYPE_FLOAT32: - return (name.append("=Float.intBitsToFloat(((arr[pos++]&0xff)<<0) | ((arr[pos++]&0xff)<<8) | ((arr[pos++]&0xff)<<16) | ((arr[pos++]&0xff)<<24) ); ")); // OK - - default: - cout << "Warning: unresolved type " << type << " for " << name.toStdString() << endl; - return(QString("unresolved type")); // will throw an arr when compiling then - } -} /** * Generate the java object files */ bool UAVObjectGeneratorJava::process_object(ObjectInfo* info) { - if (info == NULL) return false; + if (info == NULL) + return false; // Prepare output strings + QString outInclude = javaIncludeTemplate; QString outCode = javaCodeTemplate; // Replace common tags + replaceCommonTags(outInclude, info); replaceCommonTags(outCode, info); - QString type,fieldsinit,serialize_code,serialize_code_inner,deserialize_code,gettersetter; - - QString fielddesc=QString(" public final UAVObjectFieldDescription[] getFieldDescriptions() { return new UAVObjectFieldDescription[] {"); - QString fieldgetter=QString(" public Object getField(int fieldid,int arr_pos) { switch(fieldid) {\n"); - QString fieldsetter=QString(" public void setField(int fieldid,int arr_pos,Object obj) { switch(fieldid) {\n"); - - for (int n = 0; n < info->fields.length(); ++n) { - FieldInfo* act_field_info=info->fields[n]; - - bool is_array = info->fields[n]->numElements > 1; - type = getFieldTypeStr(act_field_info->type,false); // Determine type - - for (int enum_n = 0; enum_n < act_field_info->options.length(); ++enum_n) - fieldsinit.append(QString(" public final static byte %1 = %2;\n").arg(act_field_info->name.toUpper() + QString("_") + act_field_info->options[enum_n].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "")).arg(enum_n) ); - - fieldsinit.append(QString(" private ") + type); - - if ( is_array ) - fieldsinit.append(QString("[]")); - - fieldsinit.append(QString(" %1").arg(act_field_info->name)); - - if (!info->fields[n]->defaultValues.isEmpty()) { // if we have default vals - fieldsinit.append(QString("=")); - if ( is_array ) { - fieldsinit.append(QString("{")); - for (int val_n = 0; val_n < act_field_info->defaultValues.length(); ++val_n) - fieldsinit.append( ((val_n>0)?QString(","):QString() ) + formatJavaValue(act_field_info,val_n) ); - fieldsinit.append(QString("}")); - } - else - fieldsinit.append(formatJavaValue(act_field_info,0)); - } - else { - if ( is_array ) // when it is an array - fieldsinit.append(QString("= new ") + type + QString("[%1]").arg(info->fields[n]->numElements)); - } - - fieldsinit.append(QString(";\n")); - - if (n!=0) - serialize_code_inner.append(QString(",")); - - if ( is_array ) { - for (int el=0;elfields[n]->numElements;el++) { - if (el!=0) - serialize_code_inner.append(QString(",")); - - serialize_code_inner.append(serializeJavaValue(info->fields[n]->type,info->fields[n]->name+ QString("[%1]").arg(el))); - deserialize_code.append(deSerializeJavaValue(info->fields[n]->type,info->fields[n]->name+ QString("[%1]").arg(el))); - } - } - else { // no array - serialize_code_inner.append(serializeJavaValue(info->fields[n]->type,info->fields[n]->name)); - deserialize_code.append(deSerializeJavaValue(info->fields[n]->type,info->fields[n]->name)); - } - - serialize_code_inner.append(QString("//%1\n" ).arg(info->fields[n]->name)); - + // Replace the $(DATAFIELDS) tag + QString type; + QString fields; + for (int n = 0; n < info->fields.length(); ++n) + { // Determine type - type = getFieldTypeStr(act_field_info->type,false); - - QString typespec=type; - - if ( is_array ) { - typespec.append(QString("[]")); - fieldgetter.append(QString("case %1: return (Object)%2[arr_pos];\n").arg(n).arg(act_field_info->name)); - fieldsetter.append(QString("case %1: %2[arr_pos]=(%3)obj;break;\n").arg(n).arg(act_field_info->name).arg( getFieldTypeStr(act_field_info->type,true))); + type = fieldTypeStrCPP[info->fields[n]->type]; + // Append field + if ( info->fields[n]->numElements > 1 ) + { + fields.append( QString(" %1 %2[%3];\n").arg(type).arg(info->fields[n]->name) + .arg(info->fields[n]->numElements) ); } - else { // no array - fieldgetter.append(QString("case %1: return (Object)%2;\n").arg(n).arg(act_field_info->name)); - fieldsetter.append(QString("case %1: %2=(%3)obj;break;\n").arg(n).arg(act_field_info->name).arg(getFieldTypeStr(act_field_info->type,true))); + else + { + fields.append( QString(" %1 %2;\n").arg(type).arg(info->fields[n]->name) ); } + } + outInclude.replace(QString("$(DATAFIELDS)"), fields); + // Replace the $(FIELDSINIT) tag + QString finit; + for (int n = 0; n < info->fields.length(); ++n) + { + finit.append("\n"); - if (!act_field_info->units.isEmpty()) // when we have unit info - gettersetter.append(QString("\n /**\n * unit: %1\n */\n").arg(act_field_info->units)); + // Setup element names + QString varElemName = info->fields[n]->name + "ElemNames"; + finit.append( QString("\t\tList %1 = new ArrayList();\n").arg(varElemName) ); + QStringList elemNames = info->fields[n]->elementNames; + for (int m = 0; m < elemNames.length(); ++m) + finit.append( QString("\t\t%1.add(\"%2\");\n") + .arg(varElemName) + .arg(elemNames[m]) ); - gettersetter.append(QString(" public void set%1( %2 _%1 ) { %1=_%1; }\n").arg(act_field_info->name).arg(typespec)); - - if (n!=0) - fielddesc.append(QString("\t,")); - - fielddesc.append(QString("new UAVObjectFieldDescription(\"%1\",this.getObjID(),(byte)%2,(byte)%3,\"%4\",%5,%6)\n").arg(act_field_info->name).arg(n).arg(act_field_info->type).arg(act_field_info->units).arg(QStringList2JavaArray( act_field_info->options)).arg(QStringList2JavaArray( act_field_info->elementNames)) ); - - if (!act_field_info->units.isEmpty()) - gettersetter.append(QString("\n /**\n * unit: %1\n */\n").arg(act_field_info->units)); - - gettersetter.append(QString(" public ") + typespec); - - gettersetter.append(QString(" get%1() { return %1; }\n").arg(act_field_info->name)); - - if ( act_field_info->options.length()!=0) { - QString enumOptionsGetter=QString(" public final static String[] get%1EnumOptions() { return new String[] {").arg(act_field_info->name); - - // gettersetter.append(QString(" get%1s() { return %1; }\n").arg(act_field_info->name)); - for (int enum_n = 0; enum_n < act_field_info->options.length(); ++enum_n) { - if (enum_n!=0) - enumOptionsGetter.append(QString(",")); - enumOptionsGetter.append(QString("\"")+act_field_info->options[enum_n] +QString("\"")); + // Only for enum types + if (info->fields[n]->type == FIELDTYPE_ENUM) { + QString varOptionName = info->fields[n]->name + "EnumOptions"; + finit.append( QString("\t\tList %1 = new ArrayList();\n").arg(varOptionName) ); + QStringList options = info->fields[n]->options; + for (int m = 0; m < options.length(); ++m) + { + finit.append( QString("\t\t%1.add(\"%2\");\n") + .arg(varOptionName) + .arg(options[m]) ); } - - gettersetter.append(enumOptionsGetter+QString("};}\n")); + finit.append( QString("\t\tfields.add( new UAVObjectField(\"%1\", \"%2\", UAVObjectField.FieldType.ENUM, %3, %4) );\n") + .arg(info->fields[n]->name) + .arg(info->fields[n]->units) + .arg(varElemName) + .arg(varOptionName) ); } + // For all other types + else { + finit.append( QString("\t\tfields.add( new UAVObjectField(\"%1\", \"%2\", UAVObjectField.FieldType.%3, %4, null) );\n") + .arg(info->fields[n]->name) + .arg(info->fields[n]->units) + .arg(fieldTypeStrCPPClass[info->fields[n]->type]) + .arg(varElemName) ); + } + } + outCode.replace(QString("$(FIELDSINIT)"), finit); - if ( is_array ) { // when it is an array create getter for the element names - QString elementListGetter=QString(" public final static String[] get%1ElementNames() { return new String[] {").arg(act_field_info->name); + // Replace the $(DATAFIELDINFO) tag + QString name; + QString enums; + for (int n = 0; n < info->fields.length(); ++n) + { + enums.append(QString(" // Field %1 information\n").arg(info->fields[n]->name)); + // Only for enum types + if (info->fields[n]->type == FIELDTYPE_ENUM) + { + enums.append(QString(" /* Enumeration options for field %1 */\n").arg(info->fields[n]->name)); + enums.append(" typedef enum { "); + // Go through each option + QStringList options = info->fields[n]->options; + for (int m = 0; m < options.length(); ++m) { + QString s = (m != (options.length()-1)) ? "%1_%2=%3, " : "%1_%2=%3"; + enums.append( s.arg( info->fields[n]->name.toUpper() ) + .arg( options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "") ) + .arg(m) ); + + } + enums.append( QString(" } %1Options;\n") + .arg( info->fields[n]->name ) ); + } + // Generate element names (only if field has more than one element) + if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames) { + enums.append(QString(" /* Array element names for field %1 */\n").arg(info->fields[n]->name)); + enums.append(" typedef enum { "); + // Go through the element names QStringList elemNames = info->fields[n]->elementNames; for (int m = 0; m < elemNames.length(); ++m) { - gettersetter.append(QString(" public ") + type); - gettersetter.append(QString(" get%1%2() { return %1[%3]; }\n").arg(act_field_info->name).arg(elemNames[m]).arg(m)); - if (m!=0) - elementListGetter.append(QString(",")); + QString s = (m != (elemNames.length()-1)) ? "%1_%2=%3, " : "%1_%2=%3"; + enums.append( s.arg( info->fields[n]->name.toUpper() ) + .arg( elemNames[m].toUpper() ) + .arg(m) ); - elementListGetter.append(QString("\"") + elemNames[m]+QString("\"")); } - gettersetter.append(elementListGetter+QString("};}\n")); + enums.append( QString(" } %1Elem;\n") + .arg( info->fields[n]->name ) ); + } + // Generate array information + if (info->fields[n]->numElements > 1) { + enums.append(QString(" /* Number of elements for field %1 */\n").arg(info->fields[n]->name)); + enums.append( QString(" static const quint32 %1_NUMELEM = %2;\n") + .arg( info->fields[n]->name.toUpper() ) + .arg( info->fields[n]->numElements ) ); + } + } + outInclude.replace(QString("$(DATAFIELDINFO)"), enums); + + // Replace the $(INITFIELDS) tag + QString initfields; + for (int n = 0; n < info->fields.length(); ++n) + { + if (!info->fields[n]->defaultValues.isEmpty() ) + { + // For non-array fields + if ( info->fields[n]->numElements == 1) + { + if ( info->fields[n]->type == FIELDTYPE_ENUM ) + { + initfields.append( QString("\t\tgetField(\"%1\").setValue(%2);\n") + .arg( info->fields[n]->name ) + .arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[0] ) ) ); + } + else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 ) + { + initfields.append( QString("\t\tgetField(\"%1\").setValue(%2);\n") + .arg( info->fields[n]->name ) + .arg( info->fields[n]->defaultValues[0].toFloat() ) ); + } + else + { + initfields.append( QString("\t\tgetField(\"%1\").setValue(%2);\n") + .arg( info->fields[n]->name ) + .arg( info->fields[n]->defaultValues[0].toInt() ) ); + } + } + else + { + // Initialize all fields in the array + for (int idx = 0; idx < info->fields[n]->numElements; ++idx) + { + if ( info->fields[n]->type == FIELDTYPE_ENUM ) { + initfields.append( QString("\t\tgetField(\"%1\").setValue(%3,%2);\n") + .arg( info->fields[n]->name ) + .arg( idx ) + .arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[idx] ) ) ); + } + else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 ) { + initfields.append( QString("\t\tgetField(\"%1\").setValue(%3,%2);\n") + .arg( info->fields[n]->name ) + .arg( idx ) + .arg( info->fields[n]->defaultValues[idx].toFloat() ) ); + } + else { + initfields.append( QString("\t\tgetField(\"%1\").setValue(%3,%2);\n") + .arg( info->fields[n]->name ) + .arg( idx ) + .arg( info->fields[n]->defaultValues[idx].toInt() ) ); + } + } + } } } - serialize_code.append(QString(" public byte[] serialize() { return new byte[]{%1 } ;}; \n ").arg(serialize_code_inner)); + outCode.replace(QString("$(INITFIELDS)"), initfields); - serialize_code.append(QString(" public void deserialize(byte[] arr,int offset) {\nsuper.deserialize(arr,offset);\n int pos=offset;\n%1 };\n").arg(deserialize_code)); - - outCode.replace(QString("$(FIELDSINIT)"), fieldsinit); - - fielddesc.append(QString("};}")); - fieldgetter.append(QString("};\n return null;\n}\n")); - fieldsetter.append(QString("};\n}\n")); - outCode.replace(QString("$(GETTERSETTER)"), gettersetter + serialize_code+ fielddesc + fieldgetter + fieldsetter); - - bool res = writeFileIfDiffrent(javaCodePath.absolutePath() + "/uavobjects/" + info->name + ".java", outCode ); + // Write the java code + bool res = writeFileIfDiffrent( javaOutputPath.absolutePath() + "/" + info->namelc + ".java", outCode ); if (!res) { - cerr << "Error: Could not write java init output file " << info->name.toStdString()<< endl; + cout << "Error: Could not write gcs output files" << endl; return false; - } + } return true; } diff --git a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.h b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.h index 21fc4dc75..8d07484f6 100644 --- a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.h +++ b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.h @@ -28,7 +28,7 @@ #define UAVOBJECTGENERATORJAVA_H #define JAVA_TEMPLATE_DIR "ground/openpilotgcs/src/libs/juavobjects/templates/" -#define JAVA_GENERATED_DIR "java/src/org/openpilot/uavtalk" +#define JAVA_CODE_DIR "java/src/org/openpilot/uavtalk" #include "../generator_common.h" @@ -38,14 +38,12 @@ public: bool generate(UAVObjectParser* gen,QString templatepath,QString outputpath); private: - QString javaCodeTemplate; - QDir javaCodePath; bool process_object(ObjectInfo* info); - QString formatJavaValue(FieldInfo* info,int idx); - QString QStringList2JavaArray(QStringList strl); - QString serializeJavaValue(int type,QString name); - QString deSerializeJavaValue(int type,QString name); - QString getFieldTypeStr(int type,bool as_obj); -}; + + QString javaCodeTemplate, javaIncludeTemplate; + QStringList fieldTypeStrCPP,fieldTypeStrCPPClass; + QDir javaCodePath; + QDir javaOutputPath; + }; #endif From f41980c27631dfd8cbfa3d3b9c759195a10ad1f7 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 00:56:56 -0600 Subject: [PATCH 010/284] Remove some debugging lines, also use Number interface instead of explicit Byte, Integer, Short etc in setValue/getValue --- .../src/org/openpilot/uavtalk/UAVObject.java | 5 +- .../org/openpilot/uavtalk/UAVObjectField.java | 118 +++++++++++------- 2 files changed, 77 insertions(+), 46 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 926440805..fe478cf2e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -114,7 +114,7 @@ public abstract class UAVObject { for (int n = 0; n < fields.size(); ++n) { fields.get(n).initialize(this); } -// unpack(data); + unpack(data); } /** @@ -291,13 +291,12 @@ public abstract class UAVObject { public int unpack(ByteBuffer dataIn) throws Exception { if( dataIn == null ) return 0; - System.out.println( dataIn.toString() ); + // QMutexLocker locker(mutex); int numBytes = 0; ListIterator li = fields.listIterator(); while (li.hasNext()) { UAVObjectField field = li.next(); - System.out.println(field.toString()); numBytes += field.unpack(dataIn); } return numBytes; diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index b37c992fb..a9006e02f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -99,31 +99,43 @@ public class UAVObjectField { switch (type) { case INT8: - for (int index = 0; index < numElements; ++index) - dataOut.put((Byte) getValue(index)); + for (int index = 0; index < numElements; ++index) { + Integer val = (Integer) getValue(index); + dataOut.put(val.byteValue()); + } break; case INT16: - for (int index = 0; index < numElements; ++index) - dataOut.putShort((Short) getValue(index)); + for (int index = 0; index < numElements; ++index) { + Integer val = (Integer) getValue(index); + dataOut.putShort(val.shortValue()); + } break; case INT32: - for (int index = 0; index < numElements; ++index) - dataOut.putInt((Integer) getValue(index)); + for (int index = 0; index < numElements; ++index) { + Integer val = (Integer) getValue(index); + dataOut.putInt(val); + } break; case UINT8: // TODO: Deal properly with unsigned - for (int index = 0; index < numElements; ++index) - dataOut.put((Byte) getValue(index)); + for (int index = 0; index < numElements; ++index) { + Integer val = (Integer) getValue(index); + dataOut.put(val.byteValue()); + } break; case UINT16: // TODO: Deal properly with unsigned - for (int index = 0; index < numElements; ++index) - dataOut.putShort((Short) getValue(index)); + for (int index = 0; index < numElements; ++index) { + Integer val = (Integer) getValue(index); + dataOut.putShort(val.shortValue()); + } break; case UINT32: // TODO: Deal properly with unsigned - for (int index = 0; index < numElements; ++index) - dataOut.putInt((Integer) getValue(index)); + for (int index = 0; index < numElements; ++index) { + Integer val = (Integer) getValue(index); + dataOut.putInt(val); + } break; case FLOAT32: for (int index = 0; index < numElements; ++index) @@ -142,64 +154,93 @@ public class UAVObjectField { return getNumBytes(); } - public int unpack(ByteBuffer dataIn) throws Exception { + public int unpack(ByteBuffer dataIn) { // Unpack each element from input buffer dataIn.order(ByteOrder.LITTLE_ENDIAN); switch (type) { case INT8: + { + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - setValue((Byte) dataIn.get(), index); + Byte val = dataIn.get(); + l.set(index, val.intValue()); } break; + } case INT16: + { + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - setValue((Short) dataIn.getShort(), index); + Short val = dataIn.getShort(); + l.set(index, val.intValue()); } break; + } case INT32: + { + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - setValue((Integer) dataIn.getInt(), index); + Integer val = dataIn.getInt(); + l.set(index, val.intValue()); } break; + } case UINT8: - // TODO: Deal with unsigned + // TOOD: Deal with unsigned + { + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - setValue((Byte) dataIn.get(), index); + Byte val = dataIn.get(); + l.set(index, val.intValue()); } break; + } case UINT16: - // TODO: Deal with unsigned + { + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - setValue((Short) dataIn.getShort(), index); + Short val = dataIn.getShort(); + l.set(index, val.intValue()); } break; + } case UINT32: - // TODO: Deal with unsigned + { + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - setValue((Integer) dataIn.getInt(), index); + Integer val = dataIn.getInt(); + l.set(index, val.intValue()); } break; + } case FLOAT32: + { + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - setValue((Float) dataIn.getFloat(), index); + Float val = dataIn.getFloat(); + l.set(index, val); } break; + } case ENUM: + { List l = (List) data; for (int index = 0 ; index < numElements; ++index) { l.set(index, dataIn.get(index)); } break; + } case STRING: - throw new Exception("Strings not handled"); + // TODO: implement strings + //throw new Exception("Strings not handled"); } // Done return getNumBytes(); } - Object getValue() throws Exception { return getValue(0); }; - Object getValue(int index) throws Exception { + Object getValue() { return getValue(0); }; + Object getValue(int index) { // QMutexLocker locker(obj->getMutex()); // Check that index is not out of bounds if ( index >= numElements ) @@ -234,14 +275,14 @@ public class UAVObjectField { List l = (List) data; Byte val = l.get(index); - if(val >= options.size() || val < 0) - throw new Exception("Invalid value for" + name); + //if(val >= options.size() || val < 0) + // throw new Exception("Invalid value for" + name); return options.get(val); } case STRING: { - throw new Exception("Shit I should do this"); + //throw new Exception("Shit I should do this"); } } // If this point is reached then we got an invalid type @@ -252,12 +293,9 @@ public class UAVObjectField { public void setValue(Object data, int index) { // QMutexLocker locker(obj->getMutex()); // Check that index is not out of bounds - if ( index >= numElements ) + if ( index >= numElements ); //throw new Exception("Index out of bounds"); - System.out.println(data.toString()); - System.out.println(this.data.toString()); - // Get metadata UAVObject.Metadata mdata = obj.getMetadata(); // Update value if the access mode permits @@ -266,23 +304,19 @@ public class UAVObjectField { switch (type) { case INT8: - data = new Integer((Byte) data); case INT16: - data = new Integer((Short) data); case INT32: { List l = (List) this.data; - l.set(index,(Integer) data); + l.set(index,((Number) data).intValue()); break; } case UINT8: - data = new Integer((Byte) data); case UINT16: - data = new Integer((Short) data); case UINT32: { List l = (List) this.data; - l.set(index, (Integer) data); + l.set(index,((Number) data).intValue()); break; } case FLOAT32: @@ -386,7 +420,7 @@ public class UAVObjectField { sout += name + ": [ "; for (int n = 0; n < numElements; ++n) { - sout += String.valueOf(n) + " "; + sout += String.valueOf(n) + "(" + getValue(n) + ") "; } sout += "] " + units + "\n"; @@ -442,9 +476,8 @@ public class UAVObjectField { this.data = null; this.obj = null; this.elementNames = elementNames; - // Set field size - System.out.println("Initializing: type " + type + this.numElements); + // Set field size switch (type) { case INT8: @@ -487,7 +520,6 @@ public class UAVObjectField { numBytesPerElement = 0; } clear(); - System.out.println("Initialized: " + this.data.toString()); } From 5aa8eb522a96b93c2823731d1c7c92a22e1dd4eb Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 02:26:09 -0600 Subject: [PATCH 011/284] Make object store with the minimal amount of space and deal with unsigned values --- .../src/org/openpilot/uavtalk/UAVObject.java | 4 +- .../org/openpilot/uavtalk/UAVObjectField.java | 203 +++++++++++++----- .../java/uavobjectgeneratorjava.cpp | 4 +- 3 files changed, 148 insertions(+), 63 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index fe478cf2e..bf2c87d7e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -462,9 +462,7 @@ public abstract class UAVObject { * Return a string with the object information (only the header) */ public String toStringBrief() { - return getName() + " ( " + getObjID() + " " + getInstID() + " " + getNumBytes() + ")\n"; - // getName(), getObjID(), getInstID(), getNumBytes(), - // isSingleInstance()); + return getName() + " ( " + Integer.toHexString(getObjID()) + " " + Integer.toHexString(getInstID()) + " " + getNumBytes() + ")\n"; } /** diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index a9006e02f..78ebd7b52 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -27,8 +27,7 @@ public class UAVObjectField { public void initialize(UAVObject obj){ this.obj = obj; - clear(); - + //clear(); } public UAVObject getObject() { @@ -161,19 +160,19 @@ public class UAVObjectField { { case INT8: { - List l = (List) this.data; + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - Byte val = dataIn.get(); - l.set(index, val.intValue()); + Long val = bound(dataIn.get()); + l.set(index, val.byteValue()); } break; } case INT16: { - List l = (List) this.data; + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - Short val = dataIn.getShort(); - l.set(index, val.intValue()); + Long val = bound(dataIn.getShort()); + l.set(index, val.shortValue()); } break; } @@ -181,18 +180,18 @@ public class UAVObjectField { { List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - Integer val = dataIn.getInt(); + Long val = bound(dataIn.getInt()); l.set(index, val.intValue()); } break; } case UINT8: - // TOOD: Deal with unsigned { - List l = (List) this.data; + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - Byte val = dataIn.get(); - l.set(index, val.intValue()); + int signedval = (int) dataIn.get(); // this sign extends it + int unsignedval = signedval & 0xff; // drop sign extension + l.set(index, (short) unsignedval); } break; } @@ -200,17 +199,19 @@ public class UAVObjectField { { List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - Short val = dataIn.getShort(); - l.set(index, val.intValue()); + int signedval = (int) dataIn.getShort(); // this sign extends it + int unsignedval = signedval & 0xffff; // drop sign extension + l.set(index, unsignedval); } break; } case UINT32: { - List l = (List) this.data; + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - Integer val = dataIn.getInt(); - l.set(index, val.intValue()); + long signedval = (long) dataIn.getInt(); // this sign extends it + long unsignedval = signedval & 0xffffffffL; // drop sign extension + l.set(index, unsignedval); } break; } @@ -240,36 +241,31 @@ public class UAVObjectField { } Object getValue() { return getValue(0); }; - Object getValue(int index) { + @SuppressWarnings("unchecked") + Object getValue(int index) { // QMutexLocker locker(obj->getMutex()); // Check that index is not out of bounds if ( index >= numElements ) { return null; } - + switch (type) { case INT8: + return ((List) data).get(index).intValue(); case INT16: + return ((List) data).get(index).intValue(); case INT32: - { - List l = (List) data; - return l.get(index); - } + return ((List) data).get(index).intValue(); case UINT8: + return ((List) data).get(index).intValue(); case UINT16: + return ((List) data).get(index).intValue(); case UINT32: - { - // TODO: Correctly deal with unsigned values - List l = (List) data; - return l.get(index); - } + return ((List) data).get(index); case FLOAT32: - { - List l = (List) data; - return l.get(index); - } + return ((List) data).get(index); case ENUM: { List l = (List) data; @@ -290,10 +286,11 @@ public class UAVObjectField { } public void setValue(Object data) { setValue(data,0); } - public void setValue(Object data, int index) { + @SuppressWarnings("unchecked") + public void setValue(Object data, int index) { // QMutexLocker locker(obj->getMutex()); // Check that index is not out of bounds - if ( index >= numElements ); + //if ( index >= numElements ); //throw new Exception("Index out of bounds"); // Get metadata @@ -304,25 +301,45 @@ public class UAVObjectField { switch (type) { case INT8: + { + List l = (List) this.data; + l.set(index, bound(data).byteValue()); + break; + } case INT16: + { + List l = (List) this.data; + l.set(index, bound(data).shortValue()); + break; + } case INT32: { List l = (List) this.data; - l.set(index,((Number) data).intValue()); + l.set(index, bound(data).intValue()); break; } case UINT8: + { + List l = (List) this.data; + l.set(index, bound(data).shortValue()); + break; + } case UINT16: - case UINT32: { List l = (List) this.data; - l.set(index,((Number) data).intValue()); + l.set(index, bound(data).intValue()); + break; + } + case UINT32: + { + List l = (List) this.data; + l.set(index, bound(data)); break; } case FLOAT32: { List l = (List) this.data; - l.set(index, (Float) data); + l.set(index, ((Number) data).floatValue()); break; } case ENUM: @@ -431,37 +448,46 @@ public class UAVObjectField { } - public void clear() { + @SuppressWarnings("unchecked") + public void clear() { switch (type) { case INT8: + ((ArrayList) data).clear(); + for(int index = 0; index < numElements; ++index) { + ((ArrayList) data).add((byte) 0); + } + break; case INT16: + ((ArrayList) data).clear(); + for(int index = 0; index < numElements; ++index) { + ((ArrayList) data).add((short) 0); + } + break; case INT32: - case UINT8: - case UINT16: - case UINT32: ((ArrayList) data).clear(); for(int index = 0; index < numElements; ++index) { ((ArrayList) data).add(0); } break; - case FLOAT32: - ((ArrayList) data).clear(); + case UINT8: + ((ArrayList) data).clear(); for(int index = 0; index < numElements; ++index) { - ((ArrayList) data).add((float) 0); + ((ArrayList) data).add((short) 0); } break; - case ENUM: - ((ArrayList) data).clear(); + case UINT16: + ((ArrayList) data).clear(); for(int index = 0; index < numElements; ++index) { - ((ArrayList) data).add((byte)0); + ((ArrayList) data).add(0); } break; - case STRING: - // TODO: Add string + case UINT32: + ((ArrayList) data).clear(); + for(int index = 0; index < numElements; ++index) { + ((ArrayList) data).add((long) 0); + } break; - default: - numBytesPerElement = 0; } } @@ -481,11 +507,11 @@ public class UAVObjectField { switch (type) { case INT8: - data = (Object) new ArrayList(this.numElements); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 1; break; case INT16: - data = (Object) new ArrayList(this.numElements); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 2; break; case INT32: @@ -493,7 +519,7 @@ public class UAVObjectField { numBytesPerElement = 4; break; case UINT8: - data = (Object) new ArrayList(this.numElements); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 1; break; case UINT16: @@ -501,11 +527,11 @@ public class UAVObjectField { numBytesPerElement = 2; break; case UINT32: - data = (Object) new ArrayList(this.numElements); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 4; break; case FLOAT32: - data = (Object) new ArrayList(this.numElements); + data = (Object) new ArrayList(this.numElements); numBytesPerElement = 4; break; case ENUM: @@ -520,8 +546,69 @@ public class UAVObjectField { numBytesPerElement = 0; } clear(); + + System.out.println(this); } + /** + * For numerical types bounds the data appropriately + * @param val Can be any object, for numerical tries to cast to Number + * @return long value with the right range (for float rounds) + * @note This is mostly needed because java has no unsigned integer + */ + protected Long bound (Object val) { + + switch(type) { + case ENUM: + case STRING: + return 0L; + case FLOAT32: + return ((Number) val).longValue(); + } + + long num = ((Number) val).longValue(); + + switch(type) { + case INT8: + if(num < Byte.MIN_VALUE) + return (long) Byte.MAX_VALUE; + if(num > Byte.MAX_VALUE) + return (long) Byte.MAX_VALUE; + return num; + case INT16: + if(num < Short.MIN_VALUE) + return (long) Short.MIN_VALUE; + if(num > Short.MAX_VALUE) + return (long) Short.MAX_VALUE; + return num; + case INT32: + if(num < Integer.MIN_VALUE) + return (long) Integer.MIN_VALUE; + if(num > Integer.MAX_VALUE) + return (long) Integer.MAX_VALUE; + return num; + case UINT8: + if(num < 0) + return (long) 0; + if(num > 255) + return (long) 255; + return num; + case UINT16: + if(num < 0) + return (long) 0; + if(num > 65535) + return (long) 65535; + return num; + case UINT32: + if(num < 0) + return (long) 0; + if(num > 4294967295L) + return 4294967295L; + return num; + } + + return num; + } private String name; private String units; diff --git a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp index ce436e6af..7319b7767 100644 --- a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp +++ b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp @@ -29,8 +29,8 @@ using namespace std; bool UAVObjectGeneratorJava::generate(UAVObjectParser* parser,QString templatepath,QString outputpath) { - fieldTypeStrCPP << "qint8" << "qint16" << "qint32" << - "quint8" << "quint16" << "quint32" << "float" << "quint8"; + fieldTypeStrCPP << "Byte" << "Short" << "Int" << + "Short" << "Int" << "Long" << "Float" << "Byte"; fieldTypeStrCPPClass << "INT8" << "INT16" << "INT32" << "UINT8" << "UINT16" << "UINT32" << "FLOAT32" << "ENUM"; From 5220ddc2014b917372b4657bd519334b4c4c5c04 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 13:10:48 -0600 Subject: [PATCH 012/284] Added unit tests --- .../org/openpilot/uavtalk/FieldTest.java | 121 ++++++++++++++++++ .../org/openpilot/uavtalk/SettingsTest.java | 34 +++++ 2 files changed, 155 insertions(+) create mode 100644 androidgcs/tests/org/openpilot/uavtalk/FieldTest.java create mode 100644 androidgcs/tests/org/openpilot/uavtalk/SettingsTest.java diff --git a/androidgcs/tests/org/openpilot/uavtalk/FieldTest.java b/androidgcs/tests/org/openpilot/uavtalk/FieldTest.java new file mode 100644 index 000000000..2d161fc25 --- /dev/null +++ b/androidgcs/tests/org/openpilot/uavtalk/FieldTest.java @@ -0,0 +1,121 @@ +package org.openpilot.uavtalk; + +import static org.junit.Assert.*; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; + +import org.openpilot.uavtalk.UAVObjectField; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.uavobjects.*; + +public class FieldTest { + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @Test + public void testPackUint16() { + // Need an object initialized to the field to provide metadata + UAVObject obj = null; + try { + obj = new ActuatorCommand(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + UAVObjectField field = new UAVObjectField("TestField", "No Units", UAVObjectField.FieldType.UINT16, 3, null); + field.initialize(obj); + field.setValue(3,0); + field.setValue(-50,1); + field.setValue(5003585,2); + + ByteBuffer bbuf = ByteBuffer.allocate(field.getNumBytes()); + + try { + field.pack(bbuf); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Buffer size incorrect"); + } + + // Expect data to come out as little endian + byte[] expected = {3,0,0,0,(byte) 0xff,(byte) 0xff}; + for(int i = 0; i < expected.length && i < bbuf.array().length; i++) { + System.out.println("Expected: " + expected[i] + " (" + i + ")"); + System.out.println("Received: " + bbuf.array()[i] + " (" + i + ")"); + assertEquals(bbuf.array()[i],expected[i]); + } + } + + @Test + public void testUnpackUint16() { + // Need an object initialized to the field to provide metadata + UAVObject obj = null; + obj = new ActuatorCommand(); + UAVObjectField field = new UAVObjectField("TestField", "No Units", UAVObjectField.FieldType.UINT16, 3, null); + field.initialize(obj); + + ByteBuffer bbuf = ByteBuffer.allocate(field.getNumBytes()); + byte[] expected = {3,0,0,0,(byte) 0xff,(byte) 0xff}; + bbuf.put(expected); + bbuf.position(0); + field.unpack(bbuf); + + assertEquals(field.getValue(0), 3); + assertEquals(field.getValue(1), 0); + assertEquals(field.getValue(2), 65535); + } + + @Test + public void testEnumSetGetValue() { + List options = new ArrayList(); + options.add("Opt1"); + options.add("Opt2"); + options.add("Opt3"); + + // Need an object initialized to the field to provide metadata + UAVObject obj = null; + try { + obj = new ActuatorCommand(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + UAVObjectField field = new UAVObjectField("TestField", "No Units", UAVObjectField.FieldType.ENUM, 3, options); + field.initialize(obj); + field.setValue("Opt1",0); + field.setValue("Opt2",1); + field.setValue("Opt3",2); + assertEquals(field.getValue(0), "Opt1"); + assertEquals(field.getValue(1), "Opt2"); + assertEquals(field.getValue(2), "Opt3"); + } + + @Test + public void testUint16SetGetValue() { + + // Need an object initialized to the field to provide metadata + UAVObject obj = null; + try { + obj = new ActuatorCommand(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + UAVObjectField field = new UAVObjectField("TestField", "No Units", UAVObjectField.FieldType.UINT16, 3, null); + field.initialize(obj); + field.setValue(3,0); + field.setValue(-50,1); + field.setValue(5003585,2); + assertEquals(field.getValue(0), 3); + assertEquals(field.getValue(1), 0); + assertEquals(field.getValue(2), 65535); + } +} diff --git a/androidgcs/tests/org/openpilot/uavtalk/SettingsTest.java b/androidgcs/tests/org/openpilot/uavtalk/SettingsTest.java new file mode 100644 index 000000000..5a805ae88 --- /dev/null +++ b/androidgcs/tests/org/openpilot/uavtalk/SettingsTest.java @@ -0,0 +1,34 @@ +package org.openpilot.uavtalk; + +import static org.junit.Assert.*; + +import org.junit.BeforeClass; +import org.junit.Test; + +public class SettingsTest { + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @Test + public void testGetDefaultMetadata() { + fail("Not yet implemented"); + } + + @Test + public void testSetDefaultFieldValues() { + fail("Not yet implemented"); + } + + @Test + public void testIsSettings() { + fail("Not yet implemented"); + } + + @Test + public void testGetField() { + fail("Not yet implemented"); + } + +} From b98bdb9be0fd1bebea973871d0538cd33fb02c3e Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 13:11:07 -0600 Subject: [PATCH 013/284] More updates to the java objects. Also checking in the auto generated code for now to make things easier. --- .../uavtalk/uavobjects/AHRSCalibration.java | 243 ++++++++++ .../uavtalk/uavobjects/AHRSSettings.java | 178 +++++++ .../uavtalk/uavobjects/ActuatorCommand.java | 158 ++++++ .../uavtalk/uavobjects/ActuatorDesired.java | 159 ++++++ .../uavtalk/uavobjects/ActuatorSettings.java | 455 ++++++++++++++++++ .../uavtalk/uavobjects/AhrsStatus.java | 201 ++++++++ .../uavtalk/uavobjects/AttitudeActual.java | 163 +++++++ .../uavtalk/uavobjects/AttitudeRaw.java | 158 ++++++ .../uavtalk/uavobjects/AttitudeSettings.java | 159 ++++++ .../uavtalk/uavobjects/BaroAltitude.java | 147 ++++++ .../uavtalk/uavobjects/BatterySettings.java | 163 +++++++ .../uavtalk/uavobjects/FirmwareIAPObj.java | 258 ++++++++++ .../uavobjects/FlightBatteryState.java | 165 +++++++ .../uavtalk/uavobjects/FlightPlanControl.java | 144 ++++++ .../uavobjects/FlightPlanSettings.java | 140 ++++++ .../uavtalk/uavobjects/FlightPlanStatus.java | 187 +++++++ .../uavobjects/FlightTelemetryStats.java | 164 +++++++ .../uavtalk/uavobjects/GCSTelemetryStats.java | 164 +++++++ .../uavtalk/uavobjects/GPSPosition.java | 184 +++++++ .../uavtalk/uavobjects/GPSSatellites.java | 215 +++++++++ .../openpilot/uavtalk/uavobjects/GPSTime.java | 159 ++++++ .../uavtalk/uavobjects/GuidanceSettings.java | 197 ++++++++ .../uavtalk/uavobjects/HomeLocation.java | 197 ++++++++ .../uavtalk/uavobjects/I2CStats.java | 238 +++++++++ .../uavobjects/ManualControlCommand.java | 199 ++++++++ .../uavobjects/ManualControlSettings.java | 395 +++++++++++++++ .../uavtalk/uavobjects/MixerSettings.java | 357 ++++++++++++++ .../uavtalk/uavobjects/MixerStatus.java | 167 +++++++ .../uavtalk/uavobjects/NedAccel.java | 147 ++++++ .../uavtalk/uavobjects/ObjectPersistence.java | 160 ++++++ .../uavtalk/uavobjects/PositionActual.java | 147 ++++++ .../uavtalk/uavobjects/PositionDesired.java | 147 ++++++ .../uavtalk/uavobjects/RateDesired.java | 147 ++++++ .../uavtalk/uavobjects/SonarAltitude.java | 139 ++++++ .../uavobjects/StabilizationDesired.java | 161 +++++++ .../uavobjects/StabilizationSettings.java | 222 +++++++++ .../uavtalk/uavobjects/SystemAlarms.java | 176 +++++++ .../uavtalk/uavobjects/SystemSettings.java | 157 ++++++ .../uavtalk/uavobjects/SystemStats.java | 151 ++++++ .../uavtalk/uavobjects/TaskInfo.java | 170 +++++++ .../uavtalk/uavobjects/TelemetrySettings.java | 148 ++++++ .../uavobjects/UAVObjectsInitialize.java | 87 ++++ .../uavtalk/uavobjects/VelocityActual.java | 147 ++++++ .../uavtalk/uavobjects/VelocityDesired.java | 147 ++++++ .../uavtalk/uavobjects/WatchdogStatus.java | 143 ++++++ 45 files changed, 8310 insertions(+) create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java new file mode 100644 index 000000000..a3096ad39 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java @@ -0,0 +1,243 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Contains the calibration settings for the @ref AHRSCommsModule + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Contains the calibration settings for the @ref AHRSCommsModule + +generated from ahrscalibration.xml + **/ +public class AHRSCalibration extends UAVDataObject { + + public AHRSCalibration() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List measure_varElemNames = new ArrayList(); + measure_varElemNames.add("0"); + List measure_varEnumOptions = new ArrayList(); + measure_varEnumOptions.add("SET"); + measure_varEnumOptions.add("MEASURE"); + fields.add( new UAVObjectField("measure_var", "", UAVObjectField.FieldType.ENUM, measure_varElemNames, measure_varEnumOptions) ); + + List accel_biasElemNames = new ArrayList(); + accel_biasElemNames.add("X"); + accel_biasElemNames.add("Y"); + accel_biasElemNames.add("Z"); + fields.add( new UAVObjectField("accel_bias", "m/s^2", UAVObjectField.FieldType.FLOAT32, accel_biasElemNames, null) ); + + List accel_scaleElemNames = new ArrayList(); + accel_scaleElemNames.add("X"); + accel_scaleElemNames.add("Y"); + accel_scaleElemNames.add("Z"); + fields.add( new UAVObjectField("accel_scale", "(m/s^2)/lsb", UAVObjectField.FieldType.FLOAT32, accel_scaleElemNames, null) ); + + List accel_varElemNames = new ArrayList(); + accel_varElemNames.add("X"); + accel_varElemNames.add("Y"); + accel_varElemNames.add("Z"); + fields.add( new UAVObjectField("accel_var", "(m/s^2)^2", UAVObjectField.FieldType.FLOAT32, accel_varElemNames, null) ); + + List gyro_biasElemNames = new ArrayList(); + gyro_biasElemNames.add("X"); + gyro_biasElemNames.add("Y"); + gyro_biasElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_bias", "rad/s", UAVObjectField.FieldType.FLOAT32, gyro_biasElemNames, null) ); + + List gyro_scaleElemNames = new ArrayList(); + gyro_scaleElemNames.add("X"); + gyro_scaleElemNames.add("Y"); + gyro_scaleElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_scale", "(rad/s)/lsb", UAVObjectField.FieldType.FLOAT32, gyro_scaleElemNames, null) ); + + List gyro_varElemNames = new ArrayList(); + gyro_varElemNames.add("X"); + gyro_varElemNames.add("Y"); + gyro_varElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_var", "(rad/s)^2", UAVObjectField.FieldType.FLOAT32, gyro_varElemNames, null) ); + + List gyro_tempcompfactorElemNames = new ArrayList(); + gyro_tempcompfactorElemNames.add("X"); + gyro_tempcompfactorElemNames.add("Y"); + gyro_tempcompfactorElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_tempcompfactor", "raw/raw", UAVObjectField.FieldType.FLOAT32, gyro_tempcompfactorElemNames, null) ); + + List mag_biasElemNames = new ArrayList(); + mag_biasElemNames.add("X"); + mag_biasElemNames.add("Y"); + mag_biasElemNames.add("Z"); + fields.add( new UAVObjectField("mag_bias", "mGau", UAVObjectField.FieldType.FLOAT32, mag_biasElemNames, null) ); + + List mag_scaleElemNames = new ArrayList(); + mag_scaleElemNames.add("X"); + mag_scaleElemNames.add("Y"); + mag_scaleElemNames.add("Z"); + fields.add( new UAVObjectField("mag_scale", "(mGau)/lsb", UAVObjectField.FieldType.FLOAT32, mag_scaleElemNames, null) ); + + List mag_varElemNames = new ArrayList(); + mag_varElemNames.add("X"); + mag_varElemNames.add("Y"); + mag_varElemNames.add("Z"); + fields.add( new UAVObjectField("mag_var", "mGau^2", UAVObjectField.FieldType.FLOAT32, mag_varElemNames, null) ); + + List vel_varElemNames = new ArrayList(); + vel_varElemNames.add("0"); + fields.add( new UAVObjectField("vel_var", "(m/s)^2", UAVObjectField.FieldType.FLOAT32, vel_varElemNames, null) ); + + List pos_varElemNames = new ArrayList(); + pos_varElemNames.add("0"); + fields.add( new UAVObjectField("pos_var", "m^2", UAVObjectField.FieldType.FLOAT32, pos_varElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("measure_var").setValue(0); + getField("accel_bias").setValue(-73.5,0); + getField("accel_bias").setValue(-73.5,1); + getField("accel_bias").setValue(73.5,2); + getField("accel_scale").setValue(0.0359,0); + getField("accel_scale").setValue(0.0359,1); + getField("accel_scale").setValue(-0.0359,2); + getField("accel_var").setValue(0.0005,0); + getField("accel_var").setValue(0.0005,1); + getField("accel_var").setValue(0.0005,2); + getField("gyro_bias").setValue(23,0); + getField("gyro_bias").setValue(-23,1); + getField("gyro_bias").setValue(23,2); + getField("gyro_scale").setValue(-0.017,0); + getField("gyro_scale").setValue(0.017,1); + getField("gyro_scale").setValue(-0.017,2); + getField("gyro_var").setValue(0.0001,0); + getField("gyro_var").setValue(0.0001,1); + getField("gyro_var").setValue(0.0001,2); + getField("gyro_tempcompfactor").setValue(0,0); + getField("gyro_tempcompfactor").setValue(0,1); + getField("gyro_tempcompfactor").setValue(0,2); + getField("mag_bias").setValue(0,0); + getField("mag_bias").setValue(0,1); + getField("mag_bias").setValue(0,2); + getField("mag_scale").setValue(-2,0); + getField("mag_scale").setValue(-2,1); + getField("mag_scale").setValue(-2,2); + getField("mag_var").setValue(50,0); + getField("mag_var").setValue(50,1); + getField("mag_var").setValue(50,2); + getField("vel_var").setValue(0.4); + getField("pos_var").setValue(0.4); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AHRSCalibration obj = new AHRSCalibration(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AHRSCalibration GetInstance(UAVObjectManager objMngr, int instID) + { + return (AHRSCalibration)(objMngr.getObject(AHRSCalibration.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x30101BB2; + protected static final String NAME = "AHRSCalibration"; + protected static String DESCRIPTION = "Contains the calibration settings for the @ref AHRSCommsModule"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java new file mode 100644 index 000000000..a38915c28 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java @@ -0,0 +1,178 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref AHRSCommsModule to control the algorithm and what is updated + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref AHRSCommsModule to control the algorithm and what is updated + +generated from ahrssettings.xml + **/ +public class AHRSSettings extends UAVDataObject { + + public AHRSSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AlgorithmElemNames = new ArrayList(); + AlgorithmElemNames.add("0"); + List AlgorithmEnumOptions = new ArrayList(); + AlgorithmEnumOptions.add("SIMPLE"); + AlgorithmEnumOptions.add("INSGPS_INDOOR_NOMAG"); + AlgorithmEnumOptions.add("INSGPS_INDOOR"); + AlgorithmEnumOptions.add("INSGPS_OUTDOOR"); + fields.add( new UAVObjectField("Algorithm", "", UAVObjectField.FieldType.ENUM, AlgorithmElemNames, AlgorithmEnumOptions) ); + + List DownsamplingElemNames = new ArrayList(); + DownsamplingElemNames.add("0"); + fields.add( new UAVObjectField("Downsampling", "", UAVObjectField.FieldType.UINT8, DownsamplingElemNames, null) ); + + List UpdatePeriodElemNames = new ArrayList(); + UpdatePeriodElemNames.add("0"); + fields.add( new UAVObjectField("UpdatePeriod", "ms", UAVObjectField.FieldType.UINT8, UpdatePeriodElemNames, null) ); + + List BiasCorrectedRawElemNames = new ArrayList(); + BiasCorrectedRawElemNames.add("0"); + List BiasCorrectedRawEnumOptions = new ArrayList(); + BiasCorrectedRawEnumOptions.add("TRUE"); + BiasCorrectedRawEnumOptions.add("FALSE"); + fields.add( new UAVObjectField("BiasCorrectedRaw", "", UAVObjectField.FieldType.ENUM, BiasCorrectedRawElemNames, BiasCorrectedRawEnumOptions) ); + + List YawBiasElemNames = new ArrayList(); + YawBiasElemNames.add("0"); + fields.add( new UAVObjectField("YawBias", "", UAVObjectField.FieldType.FLOAT32, YawBiasElemNames, null) ); + + List PitchBiasElemNames = new ArrayList(); + PitchBiasElemNames.add("0"); + fields.add( new UAVObjectField("PitchBias", "", UAVObjectField.FieldType.FLOAT32, PitchBiasElemNames, null) ); + + List RollBiasElemNames = new ArrayList(); + RollBiasElemNames.add("0"); + fields.add( new UAVObjectField("RollBias", "", UAVObjectField.FieldType.FLOAT32, RollBiasElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Algorithm").setValue(1); + getField("Downsampling").setValue(20); + getField("UpdatePeriod").setValue(1); + getField("BiasCorrectedRaw").setValue(0); + getField("YawBias").setValue(0); + getField("PitchBias").setValue(0); + getField("RollBias").setValue(0); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AHRSSettings obj = new AHRSSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AHRSSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (AHRSSettings)(objMngr.getObject(AHRSSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xDEFC5548; + protected static final String NAME = "AHRSSettings"; + protected static String DESCRIPTION = "Settings for the @ref AHRSCommsModule to control the algorithm and what is updated"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java new file mode 100644 index 000000000..a5d6230ac --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java @@ -0,0 +1,158 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Contains the pulse duration sent to each of the channels. Set by @ref ActuatorModule + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Contains the pulse duration sent to each of the channels. Set by @ref ActuatorModule + +generated from actuatorcommand.xml + **/ +public class ActuatorCommand extends UAVDataObject { + + public ActuatorCommand() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List ChannelElemNames = new ArrayList(); + ChannelElemNames.add("0"); + ChannelElemNames.add("1"); + ChannelElemNames.add("2"); + ChannelElemNames.add("3"); + ChannelElemNames.add("4"); + ChannelElemNames.add("5"); + ChannelElemNames.add("6"); + ChannelElemNames.add("7"); + fields.add( new UAVObjectField("Channel", "us", UAVObjectField.FieldType.INT16, ChannelElemNames, null) ); + + List UpdateTimeElemNames = new ArrayList(); + UpdateTimeElemNames.add("0"); + fields.add( new UAVObjectField("UpdateTime", "ms", UAVObjectField.FieldType.UINT8, UpdateTimeElemNames, null) ); + + List MaxUpdateTimeElemNames = new ArrayList(); + MaxUpdateTimeElemNames.add("0"); + fields.add( new UAVObjectField("MaxUpdateTime", "ms", UAVObjectField.FieldType.UINT16, MaxUpdateTimeElemNames, null) ); + + List NumFailedUpdatesElemNames = new ArrayList(); + NumFailedUpdatesElemNames.add("0"); + fields.add( new UAVObjectField("NumFailedUpdates", "", UAVObjectField.FieldType.UINT8, NumFailedUpdatesElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + ActuatorCommand obj = new ActuatorCommand(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public ActuatorCommand GetInstance(UAVObjectManager objMngr, int instID) + { + return (ActuatorCommand)(objMngr.getObject(ActuatorCommand.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xE8E077D8; + protected static final String NAME = "ActuatorCommand"; + protected static String DESCRIPTION = "Contains the pulse duration sent to each of the channels. Set by @ref ActuatorModule"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java new file mode 100644 index 000000000..b81ca29da --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java @@ -0,0 +1,159 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Desired raw, pitch and yaw actuator settings. Comes from either @ref StabilizationModule or @ref ManualControlModule depending on FlightMode. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Desired raw, pitch and yaw actuator settings. Comes from either @ref StabilizationModule or @ref ManualControlModule depending on FlightMode. + +generated from actuatordesired.xml + **/ +public class ActuatorDesired extends UAVDataObject { + + public ActuatorDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "%", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "%", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "%", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + List ThrottleElemNames = new ArrayList(); + ThrottleElemNames.add("0"); + fields.add( new UAVObjectField("Throttle", "%", UAVObjectField.FieldType.FLOAT32, ThrottleElemNames, null) ); + + List UpdateTimeElemNames = new ArrayList(); + UpdateTimeElemNames.add("0"); + fields.add( new UAVObjectField("UpdateTime", "ms", UAVObjectField.FieldType.FLOAT32, UpdateTimeElemNames, null) ); + + List NumLongUpdatesElemNames = new ArrayList(); + NumLongUpdatesElemNames.add("0"); + fields.add( new UAVObjectField("NumLongUpdates", "ms", UAVObjectField.FieldType.FLOAT32, NumLongUpdatesElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + ActuatorDesired obj = new ActuatorDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public ActuatorDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (ActuatorDesired)(objMngr.getObject(ActuatorDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xD4516782; + protected static final String NAME = "ActuatorDesired"; + protected static String DESCRIPTION = "Desired raw, pitch and yaw actuator settings. Comes from either @ref StabilizationModule or @ref ManualControlModule depending on FlightMode."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java new file mode 100644 index 000000000..ebbfaeb17 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java @@ -0,0 +1,455 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType + +generated from actuatorsettings.xml + **/ +public class ActuatorSettings extends UAVDataObject { + + public ActuatorSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List FixedWingRoll1ElemNames = new ArrayList(); + FixedWingRoll1ElemNames.add("0"); + List FixedWingRoll1EnumOptions = new ArrayList(); + FixedWingRoll1EnumOptions.add("Channel1"); + FixedWingRoll1EnumOptions.add("Channel2"); + FixedWingRoll1EnumOptions.add("Channel3"); + FixedWingRoll1EnumOptions.add("Channel4"); + FixedWingRoll1EnumOptions.add("Channel5"); + FixedWingRoll1EnumOptions.add("Channel6"); + FixedWingRoll1EnumOptions.add("Channel7"); + FixedWingRoll1EnumOptions.add("Channel8"); + FixedWingRoll1EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingRoll1", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll1ElemNames, FixedWingRoll1EnumOptions) ); + + List FixedWingRoll2ElemNames = new ArrayList(); + FixedWingRoll2ElemNames.add("0"); + List FixedWingRoll2EnumOptions = new ArrayList(); + FixedWingRoll2EnumOptions.add("Channel1"); + FixedWingRoll2EnumOptions.add("Channel2"); + FixedWingRoll2EnumOptions.add("Channel3"); + FixedWingRoll2EnumOptions.add("Channel4"); + FixedWingRoll2EnumOptions.add("Channel5"); + FixedWingRoll2EnumOptions.add("Channel6"); + FixedWingRoll2EnumOptions.add("Channel7"); + FixedWingRoll2EnumOptions.add("Channel8"); + FixedWingRoll2EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingRoll2", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll2ElemNames, FixedWingRoll2EnumOptions) ); + + List FixedWingPitch1ElemNames = new ArrayList(); + FixedWingPitch1ElemNames.add("0"); + List FixedWingPitch1EnumOptions = new ArrayList(); + FixedWingPitch1EnumOptions.add("Channel1"); + FixedWingPitch1EnumOptions.add("Channel2"); + FixedWingPitch1EnumOptions.add("Channel3"); + FixedWingPitch1EnumOptions.add("Channel4"); + FixedWingPitch1EnumOptions.add("Channel5"); + FixedWingPitch1EnumOptions.add("Channel6"); + FixedWingPitch1EnumOptions.add("Channel7"); + FixedWingPitch1EnumOptions.add("Channel8"); + FixedWingPitch1EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingPitch1", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch1ElemNames, FixedWingPitch1EnumOptions) ); + + List FixedWingPitch2ElemNames = new ArrayList(); + FixedWingPitch2ElemNames.add("0"); + List FixedWingPitch2EnumOptions = new ArrayList(); + FixedWingPitch2EnumOptions.add("Channel1"); + FixedWingPitch2EnumOptions.add("Channel2"); + FixedWingPitch2EnumOptions.add("Channel3"); + FixedWingPitch2EnumOptions.add("Channel4"); + FixedWingPitch2EnumOptions.add("Channel5"); + FixedWingPitch2EnumOptions.add("Channel6"); + FixedWingPitch2EnumOptions.add("Channel7"); + FixedWingPitch2EnumOptions.add("Channel8"); + FixedWingPitch2EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingPitch2", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch2ElemNames, FixedWingPitch2EnumOptions) ); + + List FixedWingYawElemNames = new ArrayList(); + FixedWingYawElemNames.add("0"); + List FixedWingYawEnumOptions = new ArrayList(); + FixedWingYawEnumOptions.add("Channel1"); + FixedWingYawEnumOptions.add("Channel2"); + FixedWingYawEnumOptions.add("Channel3"); + FixedWingYawEnumOptions.add("Channel4"); + FixedWingYawEnumOptions.add("Channel5"); + FixedWingYawEnumOptions.add("Channel6"); + FixedWingYawEnumOptions.add("Channel7"); + FixedWingYawEnumOptions.add("Channel8"); + FixedWingYawEnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingYaw", "channel", UAVObjectField.FieldType.ENUM, FixedWingYawElemNames, FixedWingYawEnumOptions) ); + + List FixedWingThrottleElemNames = new ArrayList(); + FixedWingThrottleElemNames.add("0"); + List FixedWingThrottleEnumOptions = new ArrayList(); + FixedWingThrottleEnumOptions.add("Channel1"); + FixedWingThrottleEnumOptions.add("Channel2"); + FixedWingThrottleEnumOptions.add("Channel3"); + FixedWingThrottleEnumOptions.add("Channel4"); + FixedWingThrottleEnumOptions.add("Channel5"); + FixedWingThrottleEnumOptions.add("Channel6"); + FixedWingThrottleEnumOptions.add("Channel7"); + FixedWingThrottleEnumOptions.add("Channel8"); + FixedWingThrottleEnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingThrottle", "channel", UAVObjectField.FieldType.ENUM, FixedWingThrottleElemNames, FixedWingThrottleEnumOptions) ); + + List VTOLMotorNElemNames = new ArrayList(); + VTOLMotorNElemNames.add("0"); + List VTOLMotorNEnumOptions = new ArrayList(); + VTOLMotorNEnumOptions.add("Channel1"); + VTOLMotorNEnumOptions.add("Channel2"); + VTOLMotorNEnumOptions.add("Channel3"); + VTOLMotorNEnumOptions.add("Channel4"); + VTOLMotorNEnumOptions.add("Channel5"); + VTOLMotorNEnumOptions.add("Channel6"); + VTOLMotorNEnumOptions.add("Channel7"); + VTOLMotorNEnumOptions.add("Channel8"); + VTOLMotorNEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorN", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNElemNames, VTOLMotorNEnumOptions) ); + + List VTOLMotorNEElemNames = new ArrayList(); + VTOLMotorNEElemNames.add("0"); + List VTOLMotorNEEnumOptions = new ArrayList(); + VTOLMotorNEEnumOptions.add("Channel1"); + VTOLMotorNEEnumOptions.add("Channel2"); + VTOLMotorNEEnumOptions.add("Channel3"); + VTOLMotorNEEnumOptions.add("Channel4"); + VTOLMotorNEEnumOptions.add("Channel5"); + VTOLMotorNEEnumOptions.add("Channel6"); + VTOLMotorNEEnumOptions.add("Channel7"); + VTOLMotorNEEnumOptions.add("Channel8"); + VTOLMotorNEEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorNE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNEElemNames, VTOLMotorNEEnumOptions) ); + + List VTOLMotorEElemNames = new ArrayList(); + VTOLMotorEElemNames.add("0"); + List VTOLMotorEEnumOptions = new ArrayList(); + VTOLMotorEEnumOptions.add("Channel1"); + VTOLMotorEEnumOptions.add("Channel2"); + VTOLMotorEEnumOptions.add("Channel3"); + VTOLMotorEEnumOptions.add("Channel4"); + VTOLMotorEEnumOptions.add("Channel5"); + VTOLMotorEEnumOptions.add("Channel6"); + VTOLMotorEEnumOptions.add("Channel7"); + VTOLMotorEEnumOptions.add("Channel8"); + VTOLMotorEEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorEElemNames, VTOLMotorEEnumOptions) ); + + List VTOLMotorSEElemNames = new ArrayList(); + VTOLMotorSEElemNames.add("0"); + List VTOLMotorSEEnumOptions = new ArrayList(); + VTOLMotorSEEnumOptions.add("Channel1"); + VTOLMotorSEEnumOptions.add("Channel2"); + VTOLMotorSEEnumOptions.add("Channel3"); + VTOLMotorSEEnumOptions.add("Channel4"); + VTOLMotorSEEnumOptions.add("Channel5"); + VTOLMotorSEEnumOptions.add("Channel6"); + VTOLMotorSEEnumOptions.add("Channel7"); + VTOLMotorSEEnumOptions.add("Channel8"); + VTOLMotorSEEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorSE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSEElemNames, VTOLMotorSEEnumOptions) ); + + List VTOLMotorSElemNames = new ArrayList(); + VTOLMotorSElemNames.add("0"); + List VTOLMotorSEnumOptions = new ArrayList(); + VTOLMotorSEnumOptions.add("Channel1"); + VTOLMotorSEnumOptions.add("Channel2"); + VTOLMotorSEnumOptions.add("Channel3"); + VTOLMotorSEnumOptions.add("Channel4"); + VTOLMotorSEnumOptions.add("Channel5"); + VTOLMotorSEnumOptions.add("Channel6"); + VTOLMotorSEnumOptions.add("Channel7"); + VTOLMotorSEnumOptions.add("Channel8"); + VTOLMotorSEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorS", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSElemNames, VTOLMotorSEnumOptions) ); + + List VTOLMotorSWElemNames = new ArrayList(); + VTOLMotorSWElemNames.add("0"); + List VTOLMotorSWEnumOptions = new ArrayList(); + VTOLMotorSWEnumOptions.add("Channel1"); + VTOLMotorSWEnumOptions.add("Channel2"); + VTOLMotorSWEnumOptions.add("Channel3"); + VTOLMotorSWEnumOptions.add("Channel4"); + VTOLMotorSWEnumOptions.add("Channel5"); + VTOLMotorSWEnumOptions.add("Channel6"); + VTOLMotorSWEnumOptions.add("Channel7"); + VTOLMotorSWEnumOptions.add("Channel8"); + VTOLMotorSWEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorSW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSWElemNames, VTOLMotorSWEnumOptions) ); + + List VTOLMotorWElemNames = new ArrayList(); + VTOLMotorWElemNames.add("0"); + List VTOLMotorWEnumOptions = new ArrayList(); + VTOLMotorWEnumOptions.add("Channel1"); + VTOLMotorWEnumOptions.add("Channel2"); + VTOLMotorWEnumOptions.add("Channel3"); + VTOLMotorWEnumOptions.add("Channel4"); + VTOLMotorWEnumOptions.add("Channel5"); + VTOLMotorWEnumOptions.add("Channel6"); + VTOLMotorWEnumOptions.add("Channel7"); + VTOLMotorWEnumOptions.add("Channel8"); + VTOLMotorWEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorWElemNames, VTOLMotorWEnumOptions) ); + + List VTOLMotorNWElemNames = new ArrayList(); + VTOLMotorNWElemNames.add("0"); + List VTOLMotorNWEnumOptions = new ArrayList(); + VTOLMotorNWEnumOptions.add("Channel1"); + VTOLMotorNWEnumOptions.add("Channel2"); + VTOLMotorNWEnumOptions.add("Channel3"); + VTOLMotorNWEnumOptions.add("Channel4"); + VTOLMotorNWEnumOptions.add("Channel5"); + VTOLMotorNWEnumOptions.add("Channel6"); + VTOLMotorNWEnumOptions.add("Channel7"); + VTOLMotorNWEnumOptions.add("Channel8"); + VTOLMotorNWEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorNW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNWElemNames, VTOLMotorNWEnumOptions) ); + + List ChannelUpdateFreqElemNames = new ArrayList(); + ChannelUpdateFreqElemNames.add("0"); + ChannelUpdateFreqElemNames.add("1"); + ChannelUpdateFreqElemNames.add("2"); + ChannelUpdateFreqElemNames.add("3"); + fields.add( new UAVObjectField("ChannelUpdateFreq", "Hz", UAVObjectField.FieldType.UINT16, ChannelUpdateFreqElemNames, null) ); + + List ChannelMaxElemNames = new ArrayList(); + ChannelMaxElemNames.add("0"); + ChannelMaxElemNames.add("1"); + ChannelMaxElemNames.add("2"); + ChannelMaxElemNames.add("3"); + ChannelMaxElemNames.add("4"); + ChannelMaxElemNames.add("5"); + ChannelMaxElemNames.add("6"); + ChannelMaxElemNames.add("7"); + fields.add( new UAVObjectField("ChannelMax", "us", UAVObjectField.FieldType.INT16, ChannelMaxElemNames, null) ); + + List ChannelNeutralElemNames = new ArrayList(); + ChannelNeutralElemNames.add("0"); + ChannelNeutralElemNames.add("1"); + ChannelNeutralElemNames.add("2"); + ChannelNeutralElemNames.add("3"); + ChannelNeutralElemNames.add("4"); + ChannelNeutralElemNames.add("5"); + ChannelNeutralElemNames.add("6"); + ChannelNeutralElemNames.add("7"); + fields.add( new UAVObjectField("ChannelNeutral", "us", UAVObjectField.FieldType.INT16, ChannelNeutralElemNames, null) ); + + List ChannelMinElemNames = new ArrayList(); + ChannelMinElemNames.add("0"); + ChannelMinElemNames.add("1"); + ChannelMinElemNames.add("2"); + ChannelMinElemNames.add("3"); + ChannelMinElemNames.add("4"); + ChannelMinElemNames.add("5"); + ChannelMinElemNames.add("6"); + ChannelMinElemNames.add("7"); + fields.add( new UAVObjectField("ChannelMin", "us", UAVObjectField.FieldType.INT16, ChannelMinElemNames, null) ); + + List ChannelTypeElemNames = new ArrayList(); + ChannelTypeElemNames.add("0"); + ChannelTypeElemNames.add("1"); + ChannelTypeElemNames.add("2"); + ChannelTypeElemNames.add("3"); + ChannelTypeElemNames.add("4"); + ChannelTypeElemNames.add("5"); + ChannelTypeElemNames.add("6"); + ChannelTypeElemNames.add("7"); + List ChannelTypeEnumOptions = new ArrayList(); + ChannelTypeEnumOptions.add("PWM"); + ChannelTypeEnumOptions.add("MK"); + ChannelTypeEnumOptions.add("ASTEC4"); + fields.add( new UAVObjectField("ChannelType", "", UAVObjectField.FieldType.ENUM, ChannelTypeElemNames, ChannelTypeEnumOptions) ); + + List ChannelAddrElemNames = new ArrayList(); + ChannelAddrElemNames.add("0"); + ChannelAddrElemNames.add("1"); + ChannelAddrElemNames.add("2"); + ChannelAddrElemNames.add("3"); + ChannelAddrElemNames.add("4"); + ChannelAddrElemNames.add("5"); + ChannelAddrElemNames.add("6"); + ChannelAddrElemNames.add("7"); + fields.add( new UAVObjectField("ChannelAddr", "", UAVObjectField.FieldType.UINT8, ChannelAddrElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("FixedWingRoll1").setValue(8); + getField("FixedWingRoll2").setValue(8); + getField("FixedWingPitch1").setValue(8); + getField("FixedWingPitch2").setValue(8); + getField("FixedWingYaw").setValue(8); + getField("FixedWingThrottle").setValue(8); + getField("VTOLMotorN").setValue(8); + getField("VTOLMotorNE").setValue(8); + getField("VTOLMotorE").setValue(8); + getField("VTOLMotorSE").setValue(8); + getField("VTOLMotorS").setValue(8); + getField("VTOLMotorSW").setValue(8); + getField("VTOLMotorW").setValue(8); + getField("VTOLMotorNW").setValue(8); + getField("ChannelUpdateFreq").setValue(50,0); + getField("ChannelUpdateFreq").setValue(50,1); + getField("ChannelUpdateFreq").setValue(50,2); + getField("ChannelUpdateFreq").setValue(50,3); + getField("ChannelMax").setValue(1000,0); + getField("ChannelMax").setValue(1000,1); + getField("ChannelMax").setValue(1000,2); + getField("ChannelMax").setValue(1000,3); + getField("ChannelMax").setValue(1000,4); + getField("ChannelMax").setValue(1000,5); + getField("ChannelMax").setValue(1000,6); + getField("ChannelMax").setValue(1000,7); + getField("ChannelNeutral").setValue(1000,0); + getField("ChannelNeutral").setValue(1000,1); + getField("ChannelNeutral").setValue(1000,2); + getField("ChannelNeutral").setValue(1000,3); + getField("ChannelNeutral").setValue(1000,4); + getField("ChannelNeutral").setValue(1000,5); + getField("ChannelNeutral").setValue(1000,6); + getField("ChannelNeutral").setValue(1000,7); + getField("ChannelMin").setValue(1000,0); + getField("ChannelMin").setValue(1000,1); + getField("ChannelMin").setValue(1000,2); + getField("ChannelMin").setValue(1000,3); + getField("ChannelMin").setValue(1000,4); + getField("ChannelMin").setValue(1000,5); + getField("ChannelMin").setValue(1000,6); + getField("ChannelMin").setValue(1000,7); + getField("ChannelType").setValue(0,0); + getField("ChannelType").setValue(0,1); + getField("ChannelType").setValue(0,2); + getField("ChannelType").setValue(0,3); + getField("ChannelType").setValue(0,4); + getField("ChannelType").setValue(0,5); + getField("ChannelType").setValue(0,6); + getField("ChannelType").setValue(0,7); + getField("ChannelAddr").setValue(0,0); + getField("ChannelAddr").setValue(1,1); + getField("ChannelAddr").setValue(2,2); + getField("ChannelAddr").setValue(3,3); + getField("ChannelAddr").setValue(4,4); + getField("ChannelAddr").setValue(5,5); + getField("ChannelAddr").setValue(6,6); + getField("ChannelAddr").setValue(7,7); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + ActuatorSettings obj = new ActuatorSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public ActuatorSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (ActuatorSettings)(objMngr.getObject(ActuatorSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x1BF864C2; + protected static final String NAME = "ActuatorSettings"; + protected static String DESCRIPTION = "Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java new file mode 100644 index 000000000..3ee8304ae --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java @@ -0,0 +1,201 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Status for the @ref AHRSCommsModule, including communication errors + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Status for the @ref AHRSCommsModule, including communication errors + +generated from ahrsstatus.xml + **/ +public class AhrsStatus extends UAVDataObject { + + public AhrsStatus() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List SerialNumberElemNames = new ArrayList(); + SerialNumberElemNames.add("0"); + SerialNumberElemNames.add("1"); + SerialNumberElemNames.add("2"); + SerialNumberElemNames.add("3"); + SerialNumberElemNames.add("4"); + SerialNumberElemNames.add("5"); + SerialNumberElemNames.add("6"); + SerialNumberElemNames.add("7"); + fields.add( new UAVObjectField("SerialNumber", "", UAVObjectField.FieldType.UINT8, SerialNumberElemNames, null) ); + + List CPULoadElemNames = new ArrayList(); + CPULoadElemNames.add("0"); + fields.add( new UAVObjectField("CPULoad", "count", UAVObjectField.FieldType.UINT8, CPULoadElemNames, null) ); + + List RunningTimeElemNames = new ArrayList(); + RunningTimeElemNames.add("0"); + fields.add( new UAVObjectField("RunningTime", "ms", UAVObjectField.FieldType.UINT32, RunningTimeElemNames, null) ); + + List IdleTimePerCyleElemNames = new ArrayList(); + IdleTimePerCyleElemNames.add("0"); + fields.add( new UAVObjectField("IdleTimePerCyle", "10x ms", UAVObjectField.FieldType.UINT8, IdleTimePerCyleElemNames, null) ); + + List RunningTimePerCyleElemNames = new ArrayList(); + RunningTimePerCyleElemNames.add("0"); + fields.add( new UAVObjectField("RunningTimePerCyle", "10x ms", UAVObjectField.FieldType.UINT8, RunningTimePerCyleElemNames, null) ); + + List DroppedUpdatesElemNames = new ArrayList(); + DroppedUpdatesElemNames.add("0"); + fields.add( new UAVObjectField("DroppedUpdates", "count", UAVObjectField.FieldType.UINT8, DroppedUpdatesElemNames, null) ); + + List LinkRunningElemNames = new ArrayList(); + LinkRunningElemNames.add("0"); + List LinkRunningEnumOptions = new ArrayList(); + LinkRunningEnumOptions.add("FALSE"); + LinkRunningEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("LinkRunning", "", UAVObjectField.FieldType.ENUM, LinkRunningElemNames, LinkRunningEnumOptions) ); + + List AhrsKickstartsElemNames = new ArrayList(); + AhrsKickstartsElemNames.add("0"); + fields.add( new UAVObjectField("AhrsKickstarts", "count", UAVObjectField.FieldType.UINT8, AhrsKickstartsElemNames, null) ); + + List AhrsCrcErrorsElemNames = new ArrayList(); + AhrsCrcErrorsElemNames.add("0"); + fields.add( new UAVObjectField("AhrsCrcErrors", "count", UAVObjectField.FieldType.UINT8, AhrsCrcErrorsElemNames, null) ); + + List AhrsRetriesElemNames = new ArrayList(); + AhrsRetriesElemNames.add("0"); + fields.add( new UAVObjectField("AhrsRetries", "count", UAVObjectField.FieldType.UINT8, AhrsRetriesElemNames, null) ); + + List AhrsInvalidPacketsElemNames = new ArrayList(); + AhrsInvalidPacketsElemNames.add("0"); + fields.add( new UAVObjectField("AhrsInvalidPackets", "count", UAVObjectField.FieldType.UINT8, AhrsInvalidPacketsElemNames, null) ); + + List OpCrcErrorsElemNames = new ArrayList(); + OpCrcErrorsElemNames.add("0"); + fields.add( new UAVObjectField("OpCrcErrors", "count", UAVObjectField.FieldType.UINT8, OpCrcErrorsElemNames, null) ); + + List OpRetriesElemNames = new ArrayList(); + OpRetriesElemNames.add("0"); + fields.add( new UAVObjectField("OpRetries", "count", UAVObjectField.FieldType.UINT8, OpRetriesElemNames, null) ); + + List OpInvalidPacketsElemNames = new ArrayList(); + OpInvalidPacketsElemNames.add("0"); + fields.add( new UAVObjectField("OpInvalidPackets", "count", UAVObjectField.FieldType.UINT8, OpInvalidPacketsElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AhrsStatus obj = new AhrsStatus(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AhrsStatus GetInstance(UAVObjectManager objMngr, int instID) + { + return (AhrsStatus)(objMngr.getObject(AhrsStatus.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x37A5F7A2; + protected static final String NAME = "AhrsStatus"; + protected static String DESCRIPTION = "Status for the @ref AHRSCommsModule, including communication errors"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java new file mode 100644 index 000000000..714c18571 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java @@ -0,0 +1,163 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The updated Attitude estimation from @ref AHRSCommsModule. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The updated Attitude estimation from @ref AHRSCommsModule. + +generated from attitudeactual.xml + **/ +public class AttitudeActual extends UAVDataObject { + + public AttitudeActual() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List q1ElemNames = new ArrayList(); + q1ElemNames.add("0"); + fields.add( new UAVObjectField("q1", "", UAVObjectField.FieldType.FLOAT32, q1ElemNames, null) ); + + List q2ElemNames = new ArrayList(); + q2ElemNames.add("0"); + fields.add( new UAVObjectField("q2", "", UAVObjectField.FieldType.FLOAT32, q2ElemNames, null) ); + + List q3ElemNames = new ArrayList(); + q3ElemNames.add("0"); + fields.add( new UAVObjectField("q3", "", UAVObjectField.FieldType.FLOAT32, q3ElemNames, null) ); + + List q4ElemNames = new ArrayList(); + q4ElemNames.add("0"); + fields.add( new UAVObjectField("q4", "", UAVObjectField.FieldType.FLOAT32, q4ElemNames, null) ); + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "degrees", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "degrees", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "degrees", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 500; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AttitudeActual obj = new AttitudeActual(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AttitudeActual GetInstance(UAVObjectManager objMngr, int instID) + { + return (AttitudeActual)(objMngr.getObject(AttitudeActual.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xFC5B8CF4; + protected static final String NAME = "AttitudeActual"; + protected static String DESCRIPTION = "The updated Attitude estimation from @ref AHRSCommsModule."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java new file mode 100644 index 000000000..d28302b6a --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java @@ -0,0 +1,158 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The raw attitude sensor data from @ref AHRSCommsModule. Not always updated. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The raw attitude sensor data from @ref AHRSCommsModule. Not always updated. + +generated from attituderaw.xml + **/ +public class AttitudeRaw extends UAVDataObject { + + public AttitudeRaw() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List magnetometersElemNames = new ArrayList(); + magnetometersElemNames.add("X"); + magnetometersElemNames.add("Y"); + magnetometersElemNames.add("Z"); + fields.add( new UAVObjectField("magnetometers", "mGa", UAVObjectField.FieldType.INT16, magnetometersElemNames, null) ); + + List gyrosElemNames = new ArrayList(); + gyrosElemNames.add("X"); + gyrosElemNames.add("Y"); + gyrosElemNames.add("Z"); + fields.add( new UAVObjectField("gyros", "deg/s", UAVObjectField.FieldType.FLOAT32, gyrosElemNames, null) ); + + List gyrotempElemNames = new ArrayList(); + gyrotempElemNames.add("XY"); + gyrotempElemNames.add("Z"); + fields.add( new UAVObjectField("gyrotemp", "raw", UAVObjectField.FieldType.UINT16, gyrotempElemNames, null) ); + + List accelsElemNames = new ArrayList(); + accelsElemNames.add("X"); + accelsElemNames.add("Y"); + accelsElemNames.add("Z"); + fields.add( new UAVObjectField("accels", "m/s^2", UAVObjectField.FieldType.FLOAT32, accelsElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AttitudeRaw obj = new AttitudeRaw(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AttitudeRaw GetInstance(UAVObjectManager objMngr, int instID) + { + return (AttitudeRaw)(objMngr.getObject(AttitudeRaw.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x37747DE6; + protected static final String NAME = "AttitudeRaw"; + protected static String DESCRIPTION = "The raw attitude sensor data from @ref AHRSCommsModule. Not always updated."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java new file mode 100644 index 000000000..482fc12ce --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java @@ -0,0 +1,159 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref Attitude module used on CopterControl + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref Attitude module used on CopterControl + +generated from attitudesettings.xml + **/ +public class AttitudeSettings extends UAVDataObject { + + public AttitudeSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AccelBiasElemNames = new ArrayList(); + AccelBiasElemNames.add("X"); + AccelBiasElemNames.add("Y"); + AccelBiasElemNames.add("Z"); + fields.add( new UAVObjectField("AccelBias", "lsb", UAVObjectField.FieldType.INT16, AccelBiasElemNames, null) ); + + List GyroGainElemNames = new ArrayList(); + GyroGainElemNames.add("0"); + fields.add( new UAVObjectField("GyroGain", "(rad/s)/lsb", UAVObjectField.FieldType.FLOAT32, GyroGainElemNames, null) ); + + List AccelKpElemNames = new ArrayList(); + AccelKpElemNames.add("0"); + fields.add( new UAVObjectField("AccelKp", "channel", UAVObjectField.FieldType.FLOAT32, AccelKpElemNames, null) ); + + List AccelKiElemNames = new ArrayList(); + AccelKiElemNames.add("0"); + fields.add( new UAVObjectField("AccelKi", "channel", UAVObjectField.FieldType.FLOAT32, AccelKiElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("AccelBias").setValue(0,0); + getField("AccelBias").setValue(0,1); + getField("AccelBias").setValue(0,2); + getField("GyroGain").setValue(0.42); + getField("AccelKp").setValue(0.01); + getField("AccelKi").setValue(0.0001); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AttitudeSettings obj = new AttitudeSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AttitudeSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (AttitudeSettings)(objMngr.getObject(AttitudeSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x327BF29A; + protected static final String NAME = "AttitudeSettings"; + protected static String DESCRIPTION = "Settings for the @ref Attitude module used on CopterControl"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java new file mode 100644 index 000000000..a2c2c7e3d --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java @@ -0,0 +1,147 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The raw data from the barometric sensor with pressure, temperature and altitude estimate. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The raw data from the barometric sensor with pressure, temperature and altitude estimate. + +generated from baroaltitude.xml + **/ +public class BaroAltitude extends UAVDataObject { + + public BaroAltitude() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AltitudeElemNames = new ArrayList(); + AltitudeElemNames.add("0"); + fields.add( new UAVObjectField("Altitude", "m", UAVObjectField.FieldType.FLOAT32, AltitudeElemNames, null) ); + + List TemperatureElemNames = new ArrayList(); + TemperatureElemNames.add("0"); + fields.add( new UAVObjectField("Temperature", "C", UAVObjectField.FieldType.FLOAT32, TemperatureElemNames, null) ); + + List PressureElemNames = new ArrayList(); + PressureElemNames.add("0"); + fields.add( new UAVObjectField("Pressure", "kPa", UAVObjectField.FieldType.FLOAT32, PressureElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + BaroAltitude obj = new BaroAltitude(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public BaroAltitude GetInstance(UAVObjectManager objMngr, int instID) + { + return (BaroAltitude)(objMngr.getObject(BaroAltitude.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xED4424F6; + protected static final String NAME = "BaroAltitude"; + protected static String DESCRIPTION = "The raw data from the barometric sensor with pressure, temperature and altitude estimate."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java new file mode 100644 index 000000000..19e477b62 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java @@ -0,0 +1,163 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Battery configuration information. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Battery configuration information. + +generated from batterysettings.xml + **/ +public class BatterySettings extends UAVDataObject { + + public BatterySettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List BatteryVoltageElemNames = new ArrayList(); + BatteryVoltageElemNames.add("0"); + fields.add( new UAVObjectField("BatteryVoltage", "V", UAVObjectField.FieldType.FLOAT32, BatteryVoltageElemNames, null) ); + + List BatteryCapacityElemNames = new ArrayList(); + BatteryCapacityElemNames.add("0"); + fields.add( new UAVObjectField("BatteryCapacity", "mAh", UAVObjectField.FieldType.UINT32, BatteryCapacityElemNames, null) ); + + List BatteryTypeElemNames = new ArrayList(); + BatteryTypeElemNames.add("0"); + List BatteryTypeEnumOptions = new ArrayList(); + BatteryTypeEnumOptions.add("LiPo"); + BatteryTypeEnumOptions.add("A123"); + BatteryTypeEnumOptions.add("LiCo"); + BatteryTypeEnumOptions.add("LiFeSO4"); + BatteryTypeEnumOptions.add("None"); + fields.add( new UAVObjectField("BatteryType", "", UAVObjectField.FieldType.ENUM, BatteryTypeElemNames, BatteryTypeEnumOptions) ); + + List CalibrationsElemNames = new ArrayList(); + CalibrationsElemNames.add("Voltage"); + CalibrationsElemNames.add("Current"); + fields.add( new UAVObjectField("Calibrations", "", UAVObjectField.FieldType.FLOAT32, CalibrationsElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("BatteryVoltage").setValue(11.1); + getField("BatteryCapacity").setValue(2200); + getField("BatteryType").setValue(0); + getField("Calibrations").setValue(1,0); + getField("Calibrations").setValue(1,1); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + BatterySettings obj = new BatterySettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public BatterySettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (BatterySettings)(objMngr.getObject(BatterySettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xA5FF1D9A; + protected static final String NAME = "BatterySettings"; + protected static String DESCRIPTION = "Battery configuration information."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java new file mode 100644 index 000000000..493d6cd64 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java @@ -0,0 +1,258 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Firmware IAP + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Firmware IAP + +generated from firmwareiapobj.xml + **/ +public class FirmwareIAPObj extends UAVDataObject { + + public FirmwareIAPObj() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List CommandElemNames = new ArrayList(); + CommandElemNames.add("0"); + fields.add( new UAVObjectField("Command", "", UAVObjectField.FieldType.UINT16, CommandElemNames, null) ); + + List DescriptionElemNames = new ArrayList(); + DescriptionElemNames.add("0"); + DescriptionElemNames.add("1"); + DescriptionElemNames.add("2"); + DescriptionElemNames.add("3"); + DescriptionElemNames.add("4"); + DescriptionElemNames.add("5"); + DescriptionElemNames.add("6"); + DescriptionElemNames.add("7"); + DescriptionElemNames.add("8"); + DescriptionElemNames.add("9"); + DescriptionElemNames.add("10"); + DescriptionElemNames.add("11"); + DescriptionElemNames.add("12"); + DescriptionElemNames.add("13"); + DescriptionElemNames.add("14"); + DescriptionElemNames.add("15"); + DescriptionElemNames.add("16"); + DescriptionElemNames.add("17"); + DescriptionElemNames.add("18"); + DescriptionElemNames.add("19"); + DescriptionElemNames.add("20"); + DescriptionElemNames.add("21"); + DescriptionElemNames.add("22"); + DescriptionElemNames.add("23"); + DescriptionElemNames.add("24"); + DescriptionElemNames.add("25"); + DescriptionElemNames.add("26"); + DescriptionElemNames.add("27"); + DescriptionElemNames.add("28"); + DescriptionElemNames.add("29"); + DescriptionElemNames.add("30"); + DescriptionElemNames.add("31"); + DescriptionElemNames.add("32"); + DescriptionElemNames.add("33"); + DescriptionElemNames.add("34"); + DescriptionElemNames.add("35"); + DescriptionElemNames.add("36"); + DescriptionElemNames.add("37"); + DescriptionElemNames.add("38"); + DescriptionElemNames.add("39"); + DescriptionElemNames.add("40"); + DescriptionElemNames.add("41"); + DescriptionElemNames.add("42"); + DescriptionElemNames.add("43"); + DescriptionElemNames.add("44"); + DescriptionElemNames.add("45"); + DescriptionElemNames.add("46"); + DescriptionElemNames.add("47"); + DescriptionElemNames.add("48"); + DescriptionElemNames.add("49"); + DescriptionElemNames.add("50"); + DescriptionElemNames.add("51"); + DescriptionElemNames.add("52"); + DescriptionElemNames.add("53"); + DescriptionElemNames.add("54"); + DescriptionElemNames.add("55"); + DescriptionElemNames.add("56"); + DescriptionElemNames.add("57"); + DescriptionElemNames.add("58"); + DescriptionElemNames.add("59"); + DescriptionElemNames.add("60"); + DescriptionElemNames.add("61"); + DescriptionElemNames.add("62"); + DescriptionElemNames.add("63"); + DescriptionElemNames.add("64"); + DescriptionElemNames.add("65"); + DescriptionElemNames.add("66"); + DescriptionElemNames.add("67"); + DescriptionElemNames.add("68"); + DescriptionElemNames.add("69"); + DescriptionElemNames.add("70"); + DescriptionElemNames.add("71"); + DescriptionElemNames.add("72"); + DescriptionElemNames.add("73"); + DescriptionElemNames.add("74"); + DescriptionElemNames.add("75"); + DescriptionElemNames.add("76"); + DescriptionElemNames.add("77"); + DescriptionElemNames.add("78"); + DescriptionElemNames.add("79"); + DescriptionElemNames.add("80"); + DescriptionElemNames.add("81"); + DescriptionElemNames.add("82"); + DescriptionElemNames.add("83"); + DescriptionElemNames.add("84"); + DescriptionElemNames.add("85"); + DescriptionElemNames.add("86"); + DescriptionElemNames.add("87"); + DescriptionElemNames.add("88"); + DescriptionElemNames.add("89"); + DescriptionElemNames.add("90"); + DescriptionElemNames.add("91"); + DescriptionElemNames.add("92"); + DescriptionElemNames.add("93"); + DescriptionElemNames.add("94"); + DescriptionElemNames.add("95"); + DescriptionElemNames.add("96"); + DescriptionElemNames.add("97"); + DescriptionElemNames.add("98"); + DescriptionElemNames.add("99"); + fields.add( new UAVObjectField("Description", "", UAVObjectField.FieldType.UINT8, DescriptionElemNames, null) ); + + List BoardRevisionElemNames = new ArrayList(); + BoardRevisionElemNames.add("0"); + fields.add( new UAVObjectField("BoardRevision", "", UAVObjectField.FieldType.UINT16, BoardRevisionElemNames, null) ); + + List BoardTypeElemNames = new ArrayList(); + BoardTypeElemNames.add("0"); + fields.add( new UAVObjectField("BoardType", "", UAVObjectField.FieldType.UINT8, BoardTypeElemNames, null) ); + + List ArmResetElemNames = new ArrayList(); + ArmResetElemNames.add("0"); + fields.add( new UAVObjectField("ArmReset", "", UAVObjectField.FieldType.UINT8, ArmResetElemNames, null) ); + + List crcElemNames = new ArrayList(); + crcElemNames.add("0"); + fields.add( new UAVObjectField("crc", "", UAVObjectField.FieldType.UINT32, crcElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FirmwareIAPObj obj = new FirmwareIAPObj(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FirmwareIAPObj GetInstance(UAVObjectManager objMngr, int instID) + { + return (FirmwareIAPObj)(objMngr.getObject(FirmwareIAPObj.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x1A8ECC2; + protected static final String NAME = "FirmwareIAPObj"; + protected static String DESCRIPTION = "Firmware IAP"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java new file mode 100644 index 000000000..d9fba1de5 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java @@ -0,0 +1,165 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Battery status information. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Battery status information. + +generated from flightbatterystate.xml + **/ +public class FlightBatteryState extends UAVDataObject { + + public FlightBatteryState() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List VoltageElemNames = new ArrayList(); + VoltageElemNames.add("0"); + fields.add( new UAVObjectField("Voltage", "V", UAVObjectField.FieldType.FLOAT32, VoltageElemNames, null) ); + + List CurrentElemNames = new ArrayList(); + CurrentElemNames.add("0"); + fields.add( new UAVObjectField("Current", "A", UAVObjectField.FieldType.FLOAT32, CurrentElemNames, null) ); + + List PeakCurrentElemNames = new ArrayList(); + PeakCurrentElemNames.add("0"); + fields.add( new UAVObjectField("PeakCurrent", "A", UAVObjectField.FieldType.FLOAT32, PeakCurrentElemNames, null) ); + + List AvgCurrentElemNames = new ArrayList(); + AvgCurrentElemNames.add("0"); + fields.add( new UAVObjectField("AvgCurrent", "A", UAVObjectField.FieldType.FLOAT32, AvgCurrentElemNames, null) ); + + List ConsumedEnergyElemNames = new ArrayList(); + ConsumedEnergyElemNames.add("0"); + fields.add( new UAVObjectField("ConsumedEnergy", "mAh", UAVObjectField.FieldType.FLOAT32, ConsumedEnergyElemNames, null) ); + + List EstimatedFlightTimeElemNames = new ArrayList(); + EstimatedFlightTimeElemNames.add("0"); + fields.add( new UAVObjectField("EstimatedFlightTime", "sec", UAVObjectField.FieldType.FLOAT32, EstimatedFlightTimeElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READONLY; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Voltage").setValue(0); + getField("Current").setValue(0); + getField("PeakCurrent").setValue(0); + getField("AvgCurrent").setValue(0); + getField("ConsumedEnergy").setValue(0); + getField("EstimatedFlightTime").setValue(0); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FlightBatteryState obj = new FlightBatteryState(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FlightBatteryState GetInstance(UAVObjectManager objMngr, int instID) + { + return (FlightBatteryState)(objMngr.getObject(FlightBatteryState.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x791A50E; + protected static final String NAME = "FlightBatteryState"; + protected static String DESCRIPTION = "Battery status information."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java new file mode 100644 index 000000000..2e453eda5 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java @@ -0,0 +1,144 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Control the flight plan script + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Control the flight plan script + +generated from flightplancontrol.xml + **/ +public class FlightPlanControl extends UAVDataObject { + + public FlightPlanControl() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List CommandElemNames = new ArrayList(); + CommandElemNames.add("0"); + List CommandEnumOptions = new ArrayList(); + CommandEnumOptions.add("Start"); + CommandEnumOptions.add("Stop"); + CommandEnumOptions.add("Kill"); + fields.add( new UAVObjectField("Command", "", UAVObjectField.FieldType.ENUM, CommandElemNames, CommandEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Command").setValue(0); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FlightPlanControl obj = new FlightPlanControl(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FlightPlanControl GetInstance(UAVObjectManager objMngr, int instID) + { + return (FlightPlanControl)(objMngr.getObject(FlightPlanControl.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x6B4FE6DA; + protected static final String NAME = "FlightPlanControl"; + protected static String DESCRIPTION = "Control the flight plan script"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java new file mode 100644 index 000000000..383e4aff0 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java @@ -0,0 +1,140 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the flight plan module, control the execution of the script + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the flight plan module, control the execution of the script + +generated from flightplansettings.xml + **/ +public class FlightPlanSettings extends UAVDataObject { + + public FlightPlanSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List TestElemNames = new ArrayList(); + TestElemNames.add("0"); + fields.add( new UAVObjectField("Test", "", UAVObjectField.FieldType.FLOAT32, TestElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Test").setValue(0); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FlightPlanSettings obj = new FlightPlanSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FlightPlanSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (FlightPlanSettings)(objMngr.getObject(FlightPlanSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x85368422; + protected static final String NAME = "FlightPlanSettings"; + protected static String DESCRIPTION = "Settings for the flight plan module, control the execution of the script"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java new file mode 100644 index 000000000..00920553c --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java @@ -0,0 +1,187 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Status of the flight plan script + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Status of the flight plan script + +generated from flightplanstatus.xml + **/ +public class FlightPlanStatus extends UAVDataObject { + + public FlightPlanStatus() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List StatusElemNames = new ArrayList(); + StatusElemNames.add("0"); + List StatusEnumOptions = new ArrayList(); + StatusEnumOptions.add("Stopped"); + StatusEnumOptions.add("Running"); + StatusEnumOptions.add("Error"); + fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); + + List ErrorTypeElemNames = new ArrayList(); + ErrorTypeElemNames.add("0"); + List ErrorTypeEnumOptions = new ArrayList(); + ErrorTypeEnumOptions.add("None"); + ErrorTypeEnumOptions.add("VMInitError"); + ErrorTypeEnumOptions.add("Exception"); + ErrorTypeEnumOptions.add("IOError"); + ErrorTypeEnumOptions.add("DivByZero"); + ErrorTypeEnumOptions.add("AssertError"); + ErrorTypeEnumOptions.add("AttributeError"); + ErrorTypeEnumOptions.add("ImportError"); + ErrorTypeEnumOptions.add("IndexError"); + ErrorTypeEnumOptions.add("KeyError"); + ErrorTypeEnumOptions.add("MemoryError"); + ErrorTypeEnumOptions.add("NameError"); + ErrorTypeEnumOptions.add("SyntaxError"); + ErrorTypeEnumOptions.add("SystemError"); + ErrorTypeEnumOptions.add("TypeError"); + ErrorTypeEnumOptions.add("ValueError"); + ErrorTypeEnumOptions.add("StopIteration"); + ErrorTypeEnumOptions.add("Warning"); + ErrorTypeEnumOptions.add("UnknownError"); + fields.add( new UAVObjectField("ErrorType", "", UAVObjectField.FieldType.ENUM, ErrorTypeElemNames, ErrorTypeEnumOptions) ); + + List ErrorFileIDElemNames = new ArrayList(); + ErrorFileIDElemNames.add("0"); + fields.add( new UAVObjectField("ErrorFileID", "", UAVObjectField.FieldType.UINT32, ErrorFileIDElemNames, null) ); + + List ErrorLineNumElemNames = new ArrayList(); + ErrorLineNumElemNames.add("0"); + fields.add( new UAVObjectField("ErrorLineNum", "", UAVObjectField.FieldType.UINT32, ErrorLineNumElemNames, null) ); + + List Debug1ElemNames = new ArrayList(); + Debug1ElemNames.add("0"); + fields.add( new UAVObjectField("Debug1", "", UAVObjectField.FieldType.FLOAT32, Debug1ElemNames, null) ); + + List Debug2ElemNames = new ArrayList(); + Debug2ElemNames.add("0"); + fields.add( new UAVObjectField("Debug2", "", UAVObjectField.FieldType.FLOAT32, Debug2ElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 2000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Status").setValue(0); + getField("ErrorType").setValue(0); + getField("Debug1").setValue(0); + getField("Debug2").setValue(0); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FlightPlanStatus obj = new FlightPlanStatus(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FlightPlanStatus GetInstance(UAVObjectManager objMngr, int instID) + { + return (FlightPlanStatus)(objMngr.getObject(FlightPlanStatus.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x9FC14812; + protected static final String NAME = "FlightPlanStatus"; + protected static String DESCRIPTION = "Status of the flight plan script"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java new file mode 100644 index 000000000..b58fe6d46 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java @@ -0,0 +1,164 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Maintains the telemetry statistics from the OpenPilot flight computer. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Maintains the telemetry statistics from the OpenPilot flight computer. + +generated from flighttelemetrystats.xml + **/ +public class FlightTelemetryStats extends UAVDataObject { + + public FlightTelemetryStats() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List StatusElemNames = new ArrayList(); + StatusElemNames.add("0"); + List StatusEnumOptions = new ArrayList(); + StatusEnumOptions.add("Disconnected"); + StatusEnumOptions.add("HandshakeReq"); + StatusEnumOptions.add("HandshakeAck"); + StatusEnumOptions.add("Connected"); + fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); + + List TxDataRateElemNames = new ArrayList(); + TxDataRateElemNames.add("0"); + fields.add( new UAVObjectField("TxDataRate", "bytes/sec", UAVObjectField.FieldType.FLOAT32, TxDataRateElemNames, null) ); + + List RxDataRateElemNames = new ArrayList(); + RxDataRateElemNames.add("0"); + fields.add( new UAVObjectField("RxDataRate", "bytes/sec", UAVObjectField.FieldType.FLOAT32, RxDataRateElemNames, null) ); + + List TxFailuresElemNames = new ArrayList(); + TxFailuresElemNames.add("0"); + fields.add( new UAVObjectField("TxFailures", "count", UAVObjectField.FieldType.UINT32, TxFailuresElemNames, null) ); + + List RxFailuresElemNames = new ArrayList(); + RxFailuresElemNames.add("0"); + fields.add( new UAVObjectField("RxFailures", "count", UAVObjectField.FieldType.UINT32, RxFailuresElemNames, null) ); + + List TxRetriesElemNames = new ArrayList(); + TxRetriesElemNames.add("0"); + fields.add( new UAVObjectField("TxRetries", "count", UAVObjectField.FieldType.UINT32, TxRetriesElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 5000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 5000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FlightTelemetryStats obj = new FlightTelemetryStats(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FlightTelemetryStats GetInstance(UAVObjectManager objMngr, int instID) + { + return (FlightTelemetryStats)(objMngr.getObject(FlightTelemetryStats.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x660C265E; + protected static final String NAME = "FlightTelemetryStats"; + protected static String DESCRIPTION = "Maintains the telemetry statistics from the OpenPilot flight computer."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java new file mode 100644 index 000000000..0f304d45d --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java @@ -0,0 +1,164 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The telemetry statistics from the ground computer + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The telemetry statistics from the ground computer + +generated from gcstelemetrystats.xml + **/ +public class GCSTelemetryStats extends UAVDataObject { + + public GCSTelemetryStats() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List StatusElemNames = new ArrayList(); + StatusElemNames.add("0"); + List StatusEnumOptions = new ArrayList(); + StatusEnumOptions.add("Disconnected"); + StatusEnumOptions.add("HandshakeReq"); + StatusEnumOptions.add("HandshakeAck"); + StatusEnumOptions.add("Connected"); + fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); + + List TxDataRateElemNames = new ArrayList(); + TxDataRateElemNames.add("0"); + fields.add( new UAVObjectField("TxDataRate", "bytes/sec", UAVObjectField.FieldType.FLOAT32, TxDataRateElemNames, null) ); + + List RxDataRateElemNames = new ArrayList(); + RxDataRateElemNames.add("0"); + fields.add( new UAVObjectField("RxDataRate", "bytes/sec", UAVObjectField.FieldType.FLOAT32, RxDataRateElemNames, null) ); + + List TxFailuresElemNames = new ArrayList(); + TxFailuresElemNames.add("0"); + fields.add( new UAVObjectField("TxFailures", "count", UAVObjectField.FieldType.UINT32, TxFailuresElemNames, null) ); + + List RxFailuresElemNames = new ArrayList(); + RxFailuresElemNames.add("0"); + fields.add( new UAVObjectField("RxFailures", "count", UAVObjectField.FieldType.UINT32, RxFailuresElemNames, null) ); + + List TxRetriesElemNames = new ArrayList(); + TxRetriesElemNames.add("0"); + fields.add( new UAVObjectField("TxRetries", "count", UAVObjectField.FieldType.UINT32, TxRetriesElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.gcsTelemetryUpdatePeriod = 5000; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GCSTelemetryStats obj = new GCSTelemetryStats(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GCSTelemetryStats GetInstance(UAVObjectManager objMngr, int instID) + { + return (GCSTelemetryStats)(objMngr.getObject(GCSTelemetryStats.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x771E1046; + protected static final String NAME = "GCSTelemetryStats"; + protected static String DESCRIPTION = "The telemetry statistics from the ground computer"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java new file mode 100644 index 000000000..889091e0e --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java @@ -0,0 +1,184 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Raw GPS data from @ref GPSModule. Should only be used by @ref AHRSCommsModule. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Raw GPS data from @ref GPSModule. Should only be used by @ref AHRSCommsModule. + +generated from gpsposition.xml + **/ +public class GPSPosition extends UAVDataObject { + + public GPSPosition() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List StatusElemNames = new ArrayList(); + StatusElemNames.add("0"); + List StatusEnumOptions = new ArrayList(); + StatusEnumOptions.add("NoGPS"); + StatusEnumOptions.add("NoFix"); + StatusEnumOptions.add("Fix2D"); + StatusEnumOptions.add("Fix3D"); + fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); + + List LatitudeElemNames = new ArrayList(); + LatitudeElemNames.add("0"); + fields.add( new UAVObjectField("Latitude", "degrees x 10^-7", UAVObjectField.FieldType.INT32, LatitudeElemNames, null) ); + + List LongitudeElemNames = new ArrayList(); + LongitudeElemNames.add("0"); + fields.add( new UAVObjectField("Longitude", "degrees x 10^-7", UAVObjectField.FieldType.INT32, LongitudeElemNames, null) ); + + List AltitudeElemNames = new ArrayList(); + AltitudeElemNames.add("0"); + fields.add( new UAVObjectField("Altitude", "meters", UAVObjectField.FieldType.FLOAT32, AltitudeElemNames, null) ); + + List GeoidSeparationElemNames = new ArrayList(); + GeoidSeparationElemNames.add("0"); + fields.add( new UAVObjectField("GeoidSeparation", "meters", UAVObjectField.FieldType.FLOAT32, GeoidSeparationElemNames, null) ); + + List HeadingElemNames = new ArrayList(); + HeadingElemNames.add("0"); + fields.add( new UAVObjectField("Heading", "degrees", UAVObjectField.FieldType.FLOAT32, HeadingElemNames, null) ); + + List GroundspeedElemNames = new ArrayList(); + GroundspeedElemNames.add("0"); + fields.add( new UAVObjectField("Groundspeed", "m/s", UAVObjectField.FieldType.FLOAT32, GroundspeedElemNames, null) ); + + List SatellitesElemNames = new ArrayList(); + SatellitesElemNames.add("0"); + fields.add( new UAVObjectField("Satellites", "", UAVObjectField.FieldType.INT8, SatellitesElemNames, null) ); + + List PDOPElemNames = new ArrayList(); + PDOPElemNames.add("0"); + fields.add( new UAVObjectField("PDOP", "", UAVObjectField.FieldType.FLOAT32, PDOPElemNames, null) ); + + List HDOPElemNames = new ArrayList(); + HDOPElemNames.add("0"); + fields.add( new UAVObjectField("HDOP", "", UAVObjectField.FieldType.FLOAT32, HDOPElemNames, null) ); + + List VDOPElemNames = new ArrayList(); + VDOPElemNames.add("0"); + fields.add( new UAVObjectField("VDOP", "", UAVObjectField.FieldType.FLOAT32, VDOPElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GPSPosition obj = new GPSPosition(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GPSPosition GetInstance(UAVObjectManager objMngr, int instID) + { + return (GPSPosition)(objMngr.getObject(GPSPosition.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xB5495042; + protected static final String NAME = "GPSPosition"; + protected static String DESCRIPTION = "Raw GPS data from @ref GPSModule. Should only be used by @ref AHRSCommsModule."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java new file mode 100644 index 000000000..fa1100207 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java @@ -0,0 +1,215 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Contains information about the GPS satellites in view from @ref GPSModule. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Contains information about the GPS satellites in view from @ref GPSModule. + +generated from gpssatellites.xml + **/ +public class GPSSatellites extends UAVDataObject { + + public GPSSatellites() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List SatsInViewElemNames = new ArrayList(); + SatsInViewElemNames.add("0"); + fields.add( new UAVObjectField("SatsInView", "", UAVObjectField.FieldType.INT8, SatsInViewElemNames, null) ); + + List PRNElemNames = new ArrayList(); + PRNElemNames.add("0"); + PRNElemNames.add("1"); + PRNElemNames.add("2"); + PRNElemNames.add("3"); + PRNElemNames.add("4"); + PRNElemNames.add("5"); + PRNElemNames.add("6"); + PRNElemNames.add("7"); + PRNElemNames.add("8"); + PRNElemNames.add("9"); + PRNElemNames.add("10"); + PRNElemNames.add("11"); + PRNElemNames.add("12"); + PRNElemNames.add("13"); + PRNElemNames.add("14"); + PRNElemNames.add("15"); + fields.add( new UAVObjectField("PRN", "", UAVObjectField.FieldType.INT8, PRNElemNames, null) ); + + List ElevationElemNames = new ArrayList(); + ElevationElemNames.add("0"); + ElevationElemNames.add("1"); + ElevationElemNames.add("2"); + ElevationElemNames.add("3"); + ElevationElemNames.add("4"); + ElevationElemNames.add("5"); + ElevationElemNames.add("6"); + ElevationElemNames.add("7"); + ElevationElemNames.add("8"); + ElevationElemNames.add("9"); + ElevationElemNames.add("10"); + ElevationElemNames.add("11"); + ElevationElemNames.add("12"); + ElevationElemNames.add("13"); + ElevationElemNames.add("14"); + ElevationElemNames.add("15"); + fields.add( new UAVObjectField("Elevation", "degrees", UAVObjectField.FieldType.FLOAT32, ElevationElemNames, null) ); + + List AzimuthElemNames = new ArrayList(); + AzimuthElemNames.add("0"); + AzimuthElemNames.add("1"); + AzimuthElemNames.add("2"); + AzimuthElemNames.add("3"); + AzimuthElemNames.add("4"); + AzimuthElemNames.add("5"); + AzimuthElemNames.add("6"); + AzimuthElemNames.add("7"); + AzimuthElemNames.add("8"); + AzimuthElemNames.add("9"); + AzimuthElemNames.add("10"); + AzimuthElemNames.add("11"); + AzimuthElemNames.add("12"); + AzimuthElemNames.add("13"); + AzimuthElemNames.add("14"); + AzimuthElemNames.add("15"); + fields.add( new UAVObjectField("Azimuth", "degrees", UAVObjectField.FieldType.FLOAT32, AzimuthElemNames, null) ); + + List SNRElemNames = new ArrayList(); + SNRElemNames.add("0"); + SNRElemNames.add("1"); + SNRElemNames.add("2"); + SNRElemNames.add("3"); + SNRElemNames.add("4"); + SNRElemNames.add("5"); + SNRElemNames.add("6"); + SNRElemNames.add("7"); + SNRElemNames.add("8"); + SNRElemNames.add("9"); + SNRElemNames.add("10"); + SNRElemNames.add("11"); + SNRElemNames.add("12"); + SNRElemNames.add("13"); + SNRElemNames.add("14"); + SNRElemNames.add("15"); + fields.add( new UAVObjectField("SNR", "", UAVObjectField.FieldType.INT8, SNRElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 10000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 30000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GPSSatellites obj = new GPSSatellites(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GPSSatellites GetInstance(UAVObjectManager objMngr, int instID) + { + return (GPSSatellites)(objMngr.getObject(GPSSatellites.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xD62FA3AE; + protected static final String NAME = "GPSSatellites"; + protected static String DESCRIPTION = "Contains information about the GPS satellites in view from @ref GPSModule."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java new file mode 100644 index 000000000..5ff55cc2e --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java @@ -0,0 +1,159 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Contains the GPS time from @ref GPSModule. Required to compute the world magnetic model correctly when setting the home location. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Contains the GPS time from @ref GPSModule. Required to compute the world magnetic model correctly when setting the home location. + +generated from gpstime.xml + **/ +public class GPSTime extends UAVDataObject { + + public GPSTime() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List MonthElemNames = new ArrayList(); + MonthElemNames.add("0"); + fields.add( new UAVObjectField("Month", "", UAVObjectField.FieldType.INT8, MonthElemNames, null) ); + + List DayElemNames = new ArrayList(); + DayElemNames.add("0"); + fields.add( new UAVObjectField("Day", "", UAVObjectField.FieldType.INT8, DayElemNames, null) ); + + List YearElemNames = new ArrayList(); + YearElemNames.add("0"); + fields.add( new UAVObjectField("Year", "", UAVObjectField.FieldType.INT16, YearElemNames, null) ); + + List HourElemNames = new ArrayList(); + HourElemNames.add("0"); + fields.add( new UAVObjectField("Hour", "", UAVObjectField.FieldType.INT8, HourElemNames, null) ); + + List MinuteElemNames = new ArrayList(); + MinuteElemNames.add("0"); + fields.add( new UAVObjectField("Minute", "", UAVObjectField.FieldType.INT8, MinuteElemNames, null) ); + + List SecondElemNames = new ArrayList(); + SecondElemNames.add("0"); + fields.add( new UAVObjectField("Second", "", UAVObjectField.FieldType.INT8, SecondElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 10000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 30000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GPSTime obj = new GPSTime(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GPSTime GetInstance(UAVObjectManager objMngr, int instID) + { + return (GPSTime)(objMngr.getObject(GPSTime.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x56FFF0A2; + protected static final String NAME = "GPSTime"; + protected static String DESCRIPTION = "Contains the GPS time from @ref GPSModule. Required to compute the world magnetic model correctly when setting the home location."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java new file mode 100644 index 000000000..2cde12f64 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java @@ -0,0 +1,197 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref GuidanceModule + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref GuidanceModule + +generated from guidancesettings.xml + **/ +public class GuidanceSettings extends UAVDataObject { + + public GuidanceSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List GuidanceModeElemNames = new ArrayList(); + GuidanceModeElemNames.add("0"); + List GuidanceModeEnumOptions = new ArrayList(); + GuidanceModeEnumOptions.add("DUAL_LOOP"); + GuidanceModeEnumOptions.add("VELOCITY_CONTROL"); + fields.add( new UAVObjectField("GuidanceMode", "", UAVObjectField.FieldType.ENUM, GuidanceModeElemNames, GuidanceModeEnumOptions) ); + + List HorizontalPElemNames = new ArrayList(); + HorizontalPElemNames.add("Kp"); + HorizontalPElemNames.add("Max"); + fields.add( new UAVObjectField("HorizontalP", "", UAVObjectField.FieldType.FLOAT32, HorizontalPElemNames, null) ); + + List HorizontalVelPIDElemNames = new ArrayList(); + HorizontalVelPIDElemNames.add("Kp"); + HorizontalVelPIDElemNames.add("Ki"); + HorizontalVelPIDElemNames.add("Kd"); + HorizontalVelPIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("HorizontalVelPID", "", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); + + List VerticalPElemNames = new ArrayList(); + VerticalPElemNames.add("Kp"); + VerticalPElemNames.add("Max"); + fields.add( new UAVObjectField("VerticalP", "", UAVObjectField.FieldType.FLOAT32, VerticalPElemNames, null) ); + + List VerticalVelPIDElemNames = new ArrayList(); + VerticalVelPIDElemNames.add("Kp"); + VerticalVelPIDElemNames.add("Ki"); + VerticalVelPIDElemNames.add("Kd"); + VerticalVelPIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("VerticalVelPID", "", UAVObjectField.FieldType.FLOAT32, VerticalVelPIDElemNames, null) ); + + List ThrottleControlElemNames = new ArrayList(); + ThrottleControlElemNames.add("0"); + List ThrottleControlEnumOptions = new ArrayList(); + ThrottleControlEnumOptions.add("FALSE"); + ThrottleControlEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("ThrottleControl", "", UAVObjectField.FieldType.ENUM, ThrottleControlElemNames, ThrottleControlEnumOptions) ); + + List MaxRollPitchElemNames = new ArrayList(); + MaxRollPitchElemNames.add("0"); + fields.add( new UAVObjectField("MaxRollPitch", "deg", UAVObjectField.FieldType.FLOAT32, MaxRollPitchElemNames, null) ); + + List UpdatePeriodElemNames = new ArrayList(); + UpdatePeriodElemNames.add("0"); + fields.add( new UAVObjectField("UpdatePeriod", "", UAVObjectField.FieldType.INT32, UpdatePeriodElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("GuidanceMode").setValue(0); + getField("HorizontalP").setValue(0.2,0); + getField("HorizontalP").setValue(150,1); + getField("HorizontalVelPID").setValue(0.1,0); + getField("HorizontalVelPID").setValue(0.002,1); + getField("HorizontalVelPID").setValue(0,2); + getField("HorizontalVelPID").setValue(1000,3); + getField("VerticalP").setValue(0.1,0); + getField("VerticalP").setValue(200,1); + getField("VerticalVelPID").setValue(0.1,0); + getField("VerticalVelPID").setValue(0,1); + getField("VerticalVelPID").setValue(0,2); + getField("VerticalVelPID").setValue(0,3); + getField("ThrottleControl").setValue(0); + getField("MaxRollPitch").setValue(10); + getField("UpdatePeriod").setValue(100); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GuidanceSettings obj = new GuidanceSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GuidanceSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (GuidanceSettings)(objMngr.getObject(GuidanceSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x74740AA2; + protected static final String NAME = "GuidanceSettings"; + protected static String DESCRIPTION = "Settings for the @ref GuidanceModule"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java new file mode 100644 index 000000000..2adebce70 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java @@ -0,0 +1,197 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * HomeLocation setting which contains the constants to tranlate from longitutde and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +HomeLocation setting which contains the constants to tranlate from longitutde and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule. + +generated from homelocation.xml + **/ +public class HomeLocation extends UAVDataObject { + + public HomeLocation() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List SetElemNames = new ArrayList(); + SetElemNames.add("0"); + List SetEnumOptions = new ArrayList(); + SetEnumOptions.add("FALSE"); + SetEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("Set", "", UAVObjectField.FieldType.ENUM, SetElemNames, SetEnumOptions) ); + + List LatitudeElemNames = new ArrayList(); + LatitudeElemNames.add("0"); + fields.add( new UAVObjectField("Latitude", "deg * 10e6", UAVObjectField.FieldType.INT32, LatitudeElemNames, null) ); + + List LongitudeElemNames = new ArrayList(); + LongitudeElemNames.add("0"); + fields.add( new UAVObjectField("Longitude", "deg * 10e6", UAVObjectField.FieldType.INT32, LongitudeElemNames, null) ); + + List AltitudeElemNames = new ArrayList(); + AltitudeElemNames.add("0"); + fields.add( new UAVObjectField("Altitude", "m over geoid", UAVObjectField.FieldType.FLOAT32, AltitudeElemNames, null) ); + + List ECEFElemNames = new ArrayList(); + ECEFElemNames.add("0"); + ECEFElemNames.add("1"); + ECEFElemNames.add("2"); + fields.add( new UAVObjectField("ECEF", "cm", UAVObjectField.FieldType.INT32, ECEFElemNames, null) ); + + List RNEElemNames = new ArrayList(); + RNEElemNames.add("0"); + RNEElemNames.add("1"); + RNEElemNames.add("2"); + RNEElemNames.add("3"); + RNEElemNames.add("4"); + RNEElemNames.add("5"); + RNEElemNames.add("6"); + RNEElemNames.add("7"); + RNEElemNames.add("8"); + fields.add( new UAVObjectField("RNE", "", UAVObjectField.FieldType.FLOAT32, RNEElemNames, null) ); + + List BeElemNames = new ArrayList(); + BeElemNames.add("0"); + BeElemNames.add("1"); + BeElemNames.add("2"); + fields.add( new UAVObjectField("Be", "", UAVObjectField.FieldType.FLOAT32, BeElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Set").setValue(0); + getField("Latitude").setValue(0); + getField("Longitude").setValue(0); + getField("Altitude").setValue(0); + getField("ECEF").setValue(0,0); + getField("ECEF").setValue(0,1); + getField("ECEF").setValue(0,2); + getField("RNE").setValue(0,0); + getField("RNE").setValue(0,1); + getField("RNE").setValue(0,2); + getField("RNE").setValue(0,3); + getField("RNE").setValue(0,4); + getField("RNE").setValue(0,5); + getField("RNE").setValue(0,6); + getField("RNE").setValue(0,7); + getField("RNE").setValue(0,8); + getField("Be").setValue(0,0); + getField("Be").setValue(0,1); + getField("Be").setValue(0,2); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + HomeLocation obj = new HomeLocation(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public HomeLocation GetInstance(UAVObjectManager objMngr, int instID) + { + return (HomeLocation)(objMngr.getObject(HomeLocation.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xD6008ED2; + protected static final String NAME = "HomeLocation"; + protected static String DESCRIPTION = "HomeLocation setting which contains the constants to tranlate from longitutde and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java new file mode 100644 index 000000000..fc68e2902 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java @@ -0,0 +1,238 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Tracks statistics on the I2C bus. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Tracks statistics on the I2C bus. + +generated from i2cstats.xml + **/ +public class I2CStats extends UAVDataObject { + + public I2CStats() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List event_errorsElemNames = new ArrayList(); + event_errorsElemNames.add("0"); + fields.add( new UAVObjectField("event_errors", "", UAVObjectField.FieldType.UINT8, event_errorsElemNames, null) ); + + List fsm_errorsElemNames = new ArrayList(); + fsm_errorsElemNames.add("0"); + fields.add( new UAVObjectField("fsm_errors", "", UAVObjectField.FieldType.UINT8, fsm_errorsElemNames, null) ); + + List irq_errorsElemNames = new ArrayList(); + irq_errorsElemNames.add("0"); + fields.add( new UAVObjectField("irq_errors", "", UAVObjectField.FieldType.UINT8, irq_errorsElemNames, null) ); + + List nacksElemNames = new ArrayList(); + nacksElemNames.add("0"); + fields.add( new UAVObjectField("nacks", "", UAVObjectField.FieldType.UINT8, nacksElemNames, null) ); + + List timeoutsElemNames = new ArrayList(); + timeoutsElemNames.add("0"); + fields.add( new UAVObjectField("timeouts", "", UAVObjectField.FieldType.UINT8, timeoutsElemNames, null) ); + + List last_error_typeElemNames = new ArrayList(); + last_error_typeElemNames.add("0"); + List last_error_typeEnumOptions = new ArrayList(); + last_error_typeEnumOptions.add("EVENT"); + last_error_typeEnumOptions.add("FSM"); + last_error_typeEnumOptions.add("INTERRUPT"); + fields.add( new UAVObjectField("last_error_type", "", UAVObjectField.FieldType.ENUM, last_error_typeElemNames, last_error_typeEnumOptions) ); + + List evirq_logElemNames = new ArrayList(); + evirq_logElemNames.add("0"); + evirq_logElemNames.add("1"); + evirq_logElemNames.add("2"); + evirq_logElemNames.add("3"); + evirq_logElemNames.add("4"); + fields.add( new UAVObjectField("evirq_log", "", UAVObjectField.FieldType.UINT32, evirq_logElemNames, null) ); + + List erirq_logElemNames = new ArrayList(); + erirq_logElemNames.add("0"); + erirq_logElemNames.add("1"); + erirq_logElemNames.add("2"); + erirq_logElemNames.add("3"); + erirq_logElemNames.add("4"); + fields.add( new UAVObjectField("erirq_log", "", UAVObjectField.FieldType.UINT32, erirq_logElemNames, null) ); + + List event_logElemNames = new ArrayList(); + event_logElemNames.add("0"); + event_logElemNames.add("1"); + event_logElemNames.add("2"); + event_logElemNames.add("3"); + event_logElemNames.add("4"); + List event_logEnumOptions = new ArrayList(); + event_logEnumOptions.add("I2C_EVENT_BUS_ERROR"); + event_logEnumOptions.add("I2C_EVENT_START"); + event_logEnumOptions.add("I2C_EVENT_STARTED_MORE_TXN_READ"); + event_logEnumOptions.add("I2C_EVENT_STARTED_MORE_TXN_WRITE"); + event_logEnumOptions.add("I2C_EVENT_STARTED_LAST_TXN_READ"); + event_logEnumOptions.add("I2C_EVENT_STARTED_LAST_TXN_WRITE"); + event_logEnumOptions.add("I2C_EVENT_ADDR_SENT_LEN_EQ_0"); + event_logEnumOptions.add("I2C_EVENT_ADDR_SENT_LEN_EQ_1"); + event_logEnumOptions.add("I2C_EVENT_ADDR_SENT_LEN_EQ_2"); + event_logEnumOptions.add("I2C_EVENT_ADDR_SENT_LEN_GT_2"); + event_logEnumOptions.add("I2C_EVENT_TRANSFER_DONE_LEN_EQ_0"); + event_logEnumOptions.add("I2C_EVENT_TRANSFER_DONE_LEN_EQ_1"); + event_logEnumOptions.add("I2C_EVENT_TRANSFER_DONE_LEN_EQ_2"); + event_logEnumOptions.add("I2C_EVENT_TRANSFER_DONE_LEN_GT_2"); + event_logEnumOptions.add("I2C_EVENT_NACK"); + event_logEnumOptions.add("I2C_EVENT_STOPPED"); + event_logEnumOptions.add("I2C_EVENT_AUTO"); + fields.add( new UAVObjectField("event_log", "", UAVObjectField.FieldType.ENUM, event_logElemNames, event_logEnumOptions) ); + + List state_logElemNames = new ArrayList(); + state_logElemNames.add("0"); + state_logElemNames.add("1"); + state_logElemNames.add("2"); + state_logElemNames.add("3"); + state_logElemNames.add("4"); + List state_logEnumOptions = new ArrayList(); + state_logEnumOptions.add("I2C_STATE_FSM_FAULT"); + state_logEnumOptions.add("I2C_STATE_BUS_ERROR"); + state_logEnumOptions.add("I2C_STATE_STOPPED"); + state_logEnumOptions.add("I2C_STATE_STOPPING"); + state_logEnumOptions.add("I2C_STATE_STARTING"); + state_logEnumOptions.add("I2C_STATE_R_MORE_TXN_ADDR"); + state_logEnumOptions.add("I2C_STATE_R_MORE_TXN_PRE_ONE"); + state_logEnumOptions.add("I2C_STATE_R_MORE_TXN_PRE_FIRST"); + state_logEnumOptions.add("I2C_STATE_R_MORE_TXN_PRE_MIDDLE"); + state_logEnumOptions.add("I2C_STATE_R_MORE_TXN_LAST"); + state_logEnumOptions.add("I2C_STATE_R_MORE_TXN_POST_LAST"); + state_logEnumOptions.add("R_LAST_TXN_ADDR"); + state_logEnumOptions.add("I2C_STATE_R_LAST_TXN_PRE_ONE"); + state_logEnumOptions.add("I2C_STATE_R_LAST_TXN_PRE_FIRST"); + state_logEnumOptions.add("I2C_STATE_R_LAST_TXN_PRE_MIDDLE"); + state_logEnumOptions.add("I2C_STATE_R_LAST_TXN_PRE_LAST"); + state_logEnumOptions.add("I2C_STATE_R_LAST_TXN_POST_LAST"); + state_logEnumOptions.add("I2C_STATE_W_MORE_TXN_ADDR"); + state_logEnumOptions.add("I2C_STATE_W_MORE_TXN_MIDDLE"); + state_logEnumOptions.add("I2C_STATE_W_MORE_TXN_LAST"); + state_logEnumOptions.add("I2C_STATE_W_LAST_TXN_ADDR"); + state_logEnumOptions.add("I2C_STATE_W_LAST_TXN_MIDDLE"); + state_logEnumOptions.add("I2C_STATE_W_LAST_TXN_LAST"); + state_logEnumOptions.add("I2C_STATE_NACK"); + fields.add( new UAVObjectField("state_log", "", UAVObjectField.FieldType.ENUM, state_logElemNames, state_logEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 10000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 30000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + I2CStats obj = new I2CStats(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public I2CStats GetInstance(UAVObjectManager objMngr, int instID) + { + return (I2CStats)(objMngr.getObject(I2CStats.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x23CE9E9C; + protected static final String NAME = "I2CStats"; + protected static String DESCRIPTION = "Tracks statistics on the I2C bus."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java new file mode 100644 index 000000000..636f30946 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java @@ -0,0 +1,199 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The output from the @ref ManualControlModule which descodes the receiver inputs. Overriden by GCS for fly-by-wire control. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The output from the @ref ManualControlModule which descodes the receiver inputs. Overriden by GCS for fly-by-wire control. + +generated from manualcontrolcommand.xml + **/ +public class ManualControlCommand extends UAVDataObject { + + public ManualControlCommand() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List ConnectedElemNames = new ArrayList(); + ConnectedElemNames.add("0"); + List ConnectedEnumOptions = new ArrayList(); + ConnectedEnumOptions.add("False"); + ConnectedEnumOptions.add("True"); + fields.add( new UAVObjectField("Connected", "", UAVObjectField.FieldType.ENUM, ConnectedElemNames, ConnectedEnumOptions) ); + + List ArmedElemNames = new ArrayList(); + ArmedElemNames.add("0"); + List ArmedEnumOptions = new ArrayList(); + ArmedEnumOptions.add("False"); + ArmedEnumOptions.add("True"); + fields.add( new UAVObjectField("Armed", "", UAVObjectField.FieldType.ENUM, ArmedElemNames, ArmedEnumOptions) ); + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "%", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "%", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "%", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + List ThrottleElemNames = new ArrayList(); + ThrottleElemNames.add("0"); + fields.add( new UAVObjectField("Throttle", "%", UAVObjectField.FieldType.FLOAT32, ThrottleElemNames, null) ); + + List FlightModeElemNames = new ArrayList(); + FlightModeElemNames.add("0"); + List FlightModeEnumOptions = new ArrayList(); + FlightModeEnumOptions.add("Manual"); + FlightModeEnumOptions.add("Stabilized1"); + FlightModeEnumOptions.add("Stabilized2"); + FlightModeEnumOptions.add("Stabilized3"); + FlightModeEnumOptions.add("VelocityControl"); + FlightModeEnumOptions.add("PositionHold"); + fields.add( new UAVObjectField("FlightMode", "", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); + + List Accessory1ElemNames = new ArrayList(); + Accessory1ElemNames.add("0"); + fields.add( new UAVObjectField("Accessory1", "%", UAVObjectField.FieldType.FLOAT32, Accessory1ElemNames, null) ); + + List Accessory2ElemNames = new ArrayList(); + Accessory2ElemNames.add("0"); + fields.add( new UAVObjectField("Accessory2", "%", UAVObjectField.FieldType.FLOAT32, Accessory2ElemNames, null) ); + + List Accessory3ElemNames = new ArrayList(); + Accessory3ElemNames.add("0"); + fields.add( new UAVObjectField("Accessory3", "%", UAVObjectField.FieldType.FLOAT32, Accessory3ElemNames, null) ); + + List ChannelElemNames = new ArrayList(); + ChannelElemNames.add("0"); + ChannelElemNames.add("1"); + ChannelElemNames.add("2"); + ChannelElemNames.add("3"); + ChannelElemNames.add("4"); + ChannelElemNames.add("5"); + ChannelElemNames.add("6"); + ChannelElemNames.add("7"); + fields.add( new UAVObjectField("Channel", "us", UAVObjectField.FieldType.UINT16, ChannelElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 2000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + ManualControlCommand obj = new ManualControlCommand(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public ManualControlCommand GetInstance(UAVObjectManager objMngr, int instID) + { + return (ManualControlCommand)(objMngr.getObject(ManualControlCommand.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x926794; + protected static final String NAME = "ManualControlCommand"; + protected static String DESCRIPTION = "The output from the @ref ManualControlModule which descodes the receiver inputs. Overriden by GCS for fly-by-wire control."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java new file mode 100644 index 000000000..c14aef758 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java @@ -0,0 +1,395 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings to indicate how to decode receiver input by @ref ManualControlModule. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings to indicate how to decode receiver input by @ref ManualControlModule. + +generated from manualcontrolsettings.xml + **/ +public class ManualControlSettings extends UAVDataObject { + + public ManualControlSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List InputModeElemNames = new ArrayList(); + InputModeElemNames.add("0"); + List InputModeEnumOptions = new ArrayList(); + InputModeEnumOptions.add("PWM"); + InputModeEnumOptions.add("PPM"); + InputModeEnumOptions.add("Spektrum"); + fields.add( new UAVObjectField("InputMode", "", UAVObjectField.FieldType.ENUM, InputModeElemNames, InputModeEnumOptions) ); + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + List RollEnumOptions = new ArrayList(); + RollEnumOptions.add("Channel1"); + RollEnumOptions.add("Channel2"); + RollEnumOptions.add("Channel3"); + RollEnumOptions.add("Channel4"); + RollEnumOptions.add("Channel5"); + RollEnumOptions.add("Channel6"); + RollEnumOptions.add("Channel7"); + RollEnumOptions.add("Channel8"); + RollEnumOptions.add("None"); + fields.add( new UAVObjectField("Roll", "channel", UAVObjectField.FieldType.ENUM, RollElemNames, RollEnumOptions) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + List PitchEnumOptions = new ArrayList(); + PitchEnumOptions.add("Channel1"); + PitchEnumOptions.add("Channel2"); + PitchEnumOptions.add("Channel3"); + PitchEnumOptions.add("Channel4"); + PitchEnumOptions.add("Channel5"); + PitchEnumOptions.add("Channel6"); + PitchEnumOptions.add("Channel7"); + PitchEnumOptions.add("Channel8"); + PitchEnumOptions.add("None"); + fields.add( new UAVObjectField("Pitch", "channel", UAVObjectField.FieldType.ENUM, PitchElemNames, PitchEnumOptions) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + List YawEnumOptions = new ArrayList(); + YawEnumOptions.add("Channel1"); + YawEnumOptions.add("Channel2"); + YawEnumOptions.add("Channel3"); + YawEnumOptions.add("Channel4"); + YawEnumOptions.add("Channel5"); + YawEnumOptions.add("Channel6"); + YawEnumOptions.add("Channel7"); + YawEnumOptions.add("Channel8"); + YawEnumOptions.add("None"); + fields.add( new UAVObjectField("Yaw", "channel", UAVObjectField.FieldType.ENUM, YawElemNames, YawEnumOptions) ); + + List ThrottleElemNames = new ArrayList(); + ThrottleElemNames.add("0"); + List ThrottleEnumOptions = new ArrayList(); + ThrottleEnumOptions.add("Channel1"); + ThrottleEnumOptions.add("Channel2"); + ThrottleEnumOptions.add("Channel3"); + ThrottleEnumOptions.add("Channel4"); + ThrottleEnumOptions.add("Channel5"); + ThrottleEnumOptions.add("Channel6"); + ThrottleEnumOptions.add("Channel7"); + ThrottleEnumOptions.add("Channel8"); + ThrottleEnumOptions.add("None"); + fields.add( new UAVObjectField("Throttle", "channel", UAVObjectField.FieldType.ENUM, ThrottleElemNames, ThrottleEnumOptions) ); + + List FlightModeElemNames = new ArrayList(); + FlightModeElemNames.add("0"); + List FlightModeEnumOptions = new ArrayList(); + FlightModeEnumOptions.add("Channel1"); + FlightModeEnumOptions.add("Channel2"); + FlightModeEnumOptions.add("Channel3"); + FlightModeEnumOptions.add("Channel4"); + FlightModeEnumOptions.add("Channel5"); + FlightModeEnumOptions.add("Channel6"); + FlightModeEnumOptions.add("Channel7"); + FlightModeEnumOptions.add("Channel8"); + FlightModeEnumOptions.add("None"); + fields.add( new UAVObjectField("FlightMode", "channel", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); + + List Accessory1ElemNames = new ArrayList(); + Accessory1ElemNames.add("0"); + List Accessory1EnumOptions = new ArrayList(); + Accessory1EnumOptions.add("Channel1"); + Accessory1EnumOptions.add("Channel2"); + Accessory1EnumOptions.add("Channel3"); + Accessory1EnumOptions.add("Channel4"); + Accessory1EnumOptions.add("Channel5"); + Accessory1EnumOptions.add("Channel6"); + Accessory1EnumOptions.add("Channel7"); + Accessory1EnumOptions.add("Channel8"); + Accessory1EnumOptions.add("None"); + fields.add( new UAVObjectField("Accessory1", "channel", UAVObjectField.FieldType.ENUM, Accessory1ElemNames, Accessory1EnumOptions) ); + + List Accessory2ElemNames = new ArrayList(); + Accessory2ElemNames.add("0"); + List Accessory2EnumOptions = new ArrayList(); + Accessory2EnumOptions.add("Channel1"); + Accessory2EnumOptions.add("Channel2"); + Accessory2EnumOptions.add("Channel3"); + Accessory2EnumOptions.add("Channel4"); + Accessory2EnumOptions.add("Channel5"); + Accessory2EnumOptions.add("Channel6"); + Accessory2EnumOptions.add("Channel7"); + Accessory2EnumOptions.add("Channel8"); + Accessory2EnumOptions.add("None"); + fields.add( new UAVObjectField("Accessory2", "channel", UAVObjectField.FieldType.ENUM, Accessory2ElemNames, Accessory2EnumOptions) ); + + List Accessory3ElemNames = new ArrayList(); + Accessory3ElemNames.add("0"); + List Accessory3EnumOptions = new ArrayList(); + Accessory3EnumOptions.add("Channel1"); + Accessory3EnumOptions.add("Channel2"); + Accessory3EnumOptions.add("Channel3"); + Accessory3EnumOptions.add("Channel4"); + Accessory3EnumOptions.add("Channel5"); + Accessory3EnumOptions.add("Channel6"); + Accessory3EnumOptions.add("Channel7"); + Accessory3EnumOptions.add("Channel8"); + Accessory3EnumOptions.add("None"); + fields.add( new UAVObjectField("Accessory3", "channel", UAVObjectField.FieldType.ENUM, Accessory3ElemNames, Accessory3EnumOptions) ); + + List ArmingElemNames = new ArrayList(); + ArmingElemNames.add("0"); + List ArmingEnumOptions = new ArrayList(); + ArmingEnumOptions.add("Always Disarmed"); + ArmingEnumOptions.add("Always Armed"); + ArmingEnumOptions.add("Roll Left"); + ArmingEnumOptions.add("Roll Right"); + ArmingEnumOptions.add("Pitch Forward"); + ArmingEnumOptions.add("Pitch Aft"); + ArmingEnumOptions.add("Yaw Left"); + ArmingEnumOptions.add("Yaw Right"); + fields.add( new UAVObjectField("Arming", "", UAVObjectField.FieldType.ENUM, ArmingElemNames, ArmingEnumOptions) ); + + List Stabilization1SettingsElemNames = new ArrayList(); + Stabilization1SettingsElemNames.add("Roll"); + Stabilization1SettingsElemNames.add("Pitch"); + Stabilization1SettingsElemNames.add("Yaw"); + List Stabilization1SettingsEnumOptions = new ArrayList(); + Stabilization1SettingsEnumOptions.add("None"); + Stabilization1SettingsEnumOptions.add("Rate"); + Stabilization1SettingsEnumOptions.add("Attitude"); + fields.add( new UAVObjectField("Stabilization1Settings", "", UAVObjectField.FieldType.ENUM, Stabilization1SettingsElemNames, Stabilization1SettingsEnumOptions) ); + + List Stabilization2SettingsElemNames = new ArrayList(); + Stabilization2SettingsElemNames.add("Roll"); + Stabilization2SettingsElemNames.add("Pitch"); + Stabilization2SettingsElemNames.add("Yaw"); + List Stabilization2SettingsEnumOptions = new ArrayList(); + Stabilization2SettingsEnumOptions.add("None"); + Stabilization2SettingsEnumOptions.add("Rate"); + Stabilization2SettingsEnumOptions.add("Attitude"); + fields.add( new UAVObjectField("Stabilization2Settings", "", UAVObjectField.FieldType.ENUM, Stabilization2SettingsElemNames, Stabilization2SettingsEnumOptions) ); + + List Stabilization3SettingsElemNames = new ArrayList(); + Stabilization3SettingsElemNames.add("Roll"); + Stabilization3SettingsElemNames.add("Pitch"); + Stabilization3SettingsElemNames.add("Yaw"); + List Stabilization3SettingsEnumOptions = new ArrayList(); + Stabilization3SettingsEnumOptions.add("None"); + Stabilization3SettingsEnumOptions.add("Rate"); + Stabilization3SettingsEnumOptions.add("Attitude"); + fields.add( new UAVObjectField("Stabilization3Settings", "", UAVObjectField.FieldType.ENUM, Stabilization3SettingsElemNames, Stabilization3SettingsEnumOptions) ); + + List FlightModePositionElemNames = new ArrayList(); + FlightModePositionElemNames.add("0"); + FlightModePositionElemNames.add("1"); + FlightModePositionElemNames.add("2"); + List FlightModePositionEnumOptions = new ArrayList(); + FlightModePositionEnumOptions.add("Manual"); + FlightModePositionEnumOptions.add("Stabilized1"); + FlightModePositionEnumOptions.add("Stabilized2"); + FlightModePositionEnumOptions.add("Stabilized3"); + FlightModePositionEnumOptions.add("VelocityControl"); + FlightModePositionEnumOptions.add("PositionHold"); + fields.add( new UAVObjectField("FlightModePosition", "", UAVObjectField.FieldType.ENUM, FlightModePositionElemNames, FlightModePositionEnumOptions) ); + + List ChannelMaxElemNames = new ArrayList(); + ChannelMaxElemNames.add("0"); + ChannelMaxElemNames.add("1"); + ChannelMaxElemNames.add("2"); + ChannelMaxElemNames.add("3"); + ChannelMaxElemNames.add("4"); + ChannelMaxElemNames.add("5"); + ChannelMaxElemNames.add("6"); + ChannelMaxElemNames.add("7"); + fields.add( new UAVObjectField("ChannelMax", "us", UAVObjectField.FieldType.INT16, ChannelMaxElemNames, null) ); + + List ChannelNeutralElemNames = new ArrayList(); + ChannelNeutralElemNames.add("0"); + ChannelNeutralElemNames.add("1"); + ChannelNeutralElemNames.add("2"); + ChannelNeutralElemNames.add("3"); + ChannelNeutralElemNames.add("4"); + ChannelNeutralElemNames.add("5"); + ChannelNeutralElemNames.add("6"); + ChannelNeutralElemNames.add("7"); + fields.add( new UAVObjectField("ChannelNeutral", "us", UAVObjectField.FieldType.INT16, ChannelNeutralElemNames, null) ); + + List ChannelMinElemNames = new ArrayList(); + ChannelMinElemNames.add("0"); + ChannelMinElemNames.add("1"); + ChannelMinElemNames.add("2"); + ChannelMinElemNames.add("3"); + ChannelMinElemNames.add("4"); + ChannelMinElemNames.add("5"); + ChannelMinElemNames.add("6"); + ChannelMinElemNames.add("7"); + fields.add( new UAVObjectField("ChannelMin", "us", UAVObjectField.FieldType.INT16, ChannelMinElemNames, null) ); + + List ArmedTimeoutElemNames = new ArrayList(); + ArmedTimeoutElemNames.add("0"); + fields.add( new UAVObjectField("ArmedTimeout", "ms", UAVObjectField.FieldType.UINT16, ArmedTimeoutElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("InputMode").setValue(0); + getField("Roll").setValue(0); + getField("Pitch").setValue(1); + getField("Yaw").setValue(2); + getField("Throttle").setValue(3); + getField("FlightMode").setValue(4); + getField("Accessory1").setValue(8); + getField("Accessory2").setValue(8); + getField("Accessory3").setValue(8); + getField("Arming").setValue(0); + getField("Stabilization1Settings").setValue(2,0); + getField("Stabilization1Settings").setValue(2,1); + getField("Stabilization1Settings").setValue(2,2); + getField("Stabilization2Settings").setValue(2,0); + getField("Stabilization2Settings").setValue(2,1); + getField("Stabilization2Settings").setValue(2,2); + getField("Stabilization3Settings").setValue(2,0); + getField("Stabilization3Settings").setValue(2,1); + getField("Stabilization3Settings").setValue(2,2); + getField("FlightModePosition").setValue(0,0); + getField("FlightModePosition").setValue(1,1); + getField("FlightModePosition").setValue(2,2); + getField("ChannelMax").setValue(2000,0); + getField("ChannelMax").setValue(2000,1); + getField("ChannelMax").setValue(2000,2); + getField("ChannelMax").setValue(2000,3); + getField("ChannelMax").setValue(2000,4); + getField("ChannelMax").setValue(2000,5); + getField("ChannelMax").setValue(2000,6); + getField("ChannelMax").setValue(2000,7); + getField("ChannelNeutral").setValue(1500,0); + getField("ChannelNeutral").setValue(1500,1); + getField("ChannelNeutral").setValue(1500,2); + getField("ChannelNeutral").setValue(1500,3); + getField("ChannelNeutral").setValue(1500,4); + getField("ChannelNeutral").setValue(1500,5); + getField("ChannelNeutral").setValue(1500,6); + getField("ChannelNeutral").setValue(1500,7); + getField("ChannelMin").setValue(1000,0); + getField("ChannelMin").setValue(1000,1); + getField("ChannelMin").setValue(1000,2); + getField("ChannelMin").setValue(1000,3); + getField("ChannelMin").setValue(1000,4); + getField("ChannelMin").setValue(1000,5); + getField("ChannelMin").setValue(1000,6); + getField("ChannelMin").setValue(1000,7); + getField("ArmedTimeout").setValue(30000); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + ManualControlSettings obj = new ManualControlSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public ManualControlSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (ManualControlSettings)(objMngr.getObject(ManualControlSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x2B82102; + protected static final String NAME = "ManualControlSettings"; + protected static String DESCRIPTION = "Settings to indicate how to decode receiver input by @ref ManualControlModule."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java new file mode 100644 index 000000000..554e366f3 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java @@ -0,0 +1,357 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType + +generated from mixersettings.xml + **/ +public class MixerSettings extends UAVDataObject { + + public MixerSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List MaxAccelElemNames = new ArrayList(); + MaxAccelElemNames.add("0"); + fields.add( new UAVObjectField("MaxAccel", "units/sec", UAVObjectField.FieldType.FLOAT32, MaxAccelElemNames, null) ); + + List FeedForwardElemNames = new ArrayList(); + FeedForwardElemNames.add("0"); + fields.add( new UAVObjectField("FeedForward", "", UAVObjectField.FieldType.FLOAT32, FeedForwardElemNames, null) ); + + List AccelTimeElemNames = new ArrayList(); + AccelTimeElemNames.add("0"); + fields.add( new UAVObjectField("AccelTime", "ms", UAVObjectField.FieldType.FLOAT32, AccelTimeElemNames, null) ); + + List DecelTimeElemNames = new ArrayList(); + DecelTimeElemNames.add("0"); + fields.add( new UAVObjectField("DecelTime", "ms", UAVObjectField.FieldType.FLOAT32, DecelTimeElemNames, null) ); + + List ThrottleCurve1ElemNames = new ArrayList(); + ThrottleCurve1ElemNames.add("0"); + ThrottleCurve1ElemNames.add("25"); + ThrottleCurve1ElemNames.add("50"); + ThrottleCurve1ElemNames.add("75"); + ThrottleCurve1ElemNames.add("100"); + fields.add( new UAVObjectField("ThrottleCurve1", "percent", UAVObjectField.FieldType.FLOAT32, ThrottleCurve1ElemNames, null) ); + + List ThrottleCurve2ElemNames = new ArrayList(); + ThrottleCurve2ElemNames.add("0"); + ThrottleCurve2ElemNames.add("25"); + ThrottleCurve2ElemNames.add("50"); + ThrottleCurve2ElemNames.add("75"); + ThrottleCurve2ElemNames.add("100"); + fields.add( new UAVObjectField("ThrottleCurve2", "percent", UAVObjectField.FieldType.FLOAT32, ThrottleCurve2ElemNames, null) ); + + List Mixer1TypeElemNames = new ArrayList(); + Mixer1TypeElemNames.add("0"); + List Mixer1TypeEnumOptions = new ArrayList(); + Mixer1TypeEnumOptions.add("Disabled"); + Mixer1TypeEnumOptions.add("Motor"); + Mixer1TypeEnumOptions.add("Servo"); + fields.add( new UAVObjectField("Mixer1Type", "", UAVObjectField.FieldType.ENUM, Mixer1TypeElemNames, Mixer1TypeEnumOptions) ); + + List Mixer1VectorElemNames = new ArrayList(); + Mixer1VectorElemNames.add("ThrottleCurve1"); + Mixer1VectorElemNames.add("ThrottleCurve2"); + Mixer1VectorElemNames.add("Roll"); + Mixer1VectorElemNames.add("Pitch"); + Mixer1VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer1Vector", "", UAVObjectField.FieldType.INT8, Mixer1VectorElemNames, null) ); + + List Mixer2TypeElemNames = new ArrayList(); + Mixer2TypeElemNames.add("0"); + List Mixer2TypeEnumOptions = new ArrayList(); + Mixer2TypeEnumOptions.add("Disabled"); + Mixer2TypeEnumOptions.add("Motor"); + Mixer2TypeEnumOptions.add("Servo"); + fields.add( new UAVObjectField("Mixer2Type", "", UAVObjectField.FieldType.ENUM, Mixer2TypeElemNames, Mixer2TypeEnumOptions) ); + + List Mixer2VectorElemNames = new ArrayList(); + Mixer2VectorElemNames.add("ThrottleCurve1"); + Mixer2VectorElemNames.add("ThrottleCurve2"); + Mixer2VectorElemNames.add("Roll"); + Mixer2VectorElemNames.add("Pitch"); + Mixer2VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer2Vector", "", UAVObjectField.FieldType.INT8, Mixer2VectorElemNames, null) ); + + List Mixer3TypeElemNames = new ArrayList(); + Mixer3TypeElemNames.add("0"); + List Mixer3TypeEnumOptions = new ArrayList(); + Mixer3TypeEnumOptions.add("Disabled"); + Mixer3TypeEnumOptions.add("Motor"); + Mixer3TypeEnumOptions.add("Servo"); + fields.add( new UAVObjectField("Mixer3Type", "", UAVObjectField.FieldType.ENUM, Mixer3TypeElemNames, Mixer3TypeEnumOptions) ); + + List Mixer3VectorElemNames = new ArrayList(); + Mixer3VectorElemNames.add("ThrottleCurve1"); + Mixer3VectorElemNames.add("ThrottleCurve2"); + Mixer3VectorElemNames.add("Roll"); + Mixer3VectorElemNames.add("Pitch"); + Mixer3VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer3Vector", "", UAVObjectField.FieldType.INT8, Mixer3VectorElemNames, null) ); + + List Mixer4TypeElemNames = new ArrayList(); + Mixer4TypeElemNames.add("0"); + List Mixer4TypeEnumOptions = new ArrayList(); + Mixer4TypeEnumOptions.add("Disabled"); + Mixer4TypeEnumOptions.add("Motor"); + Mixer4TypeEnumOptions.add("Servo"); + fields.add( new UAVObjectField("Mixer4Type", "", UAVObjectField.FieldType.ENUM, Mixer4TypeElemNames, Mixer4TypeEnumOptions) ); + + List Mixer4VectorElemNames = new ArrayList(); + Mixer4VectorElemNames.add("ThrottleCurve1"); + Mixer4VectorElemNames.add("ThrottleCurve2"); + Mixer4VectorElemNames.add("Roll"); + Mixer4VectorElemNames.add("Pitch"); + Mixer4VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer4Vector", "", UAVObjectField.FieldType.INT8, Mixer4VectorElemNames, null) ); + + List Mixer5TypeElemNames = new ArrayList(); + Mixer5TypeElemNames.add("0"); + List Mixer5TypeEnumOptions = new ArrayList(); + Mixer5TypeEnumOptions.add("Disabled"); + Mixer5TypeEnumOptions.add("Motor"); + Mixer5TypeEnumOptions.add("Servo"); + fields.add( new UAVObjectField("Mixer5Type", "", UAVObjectField.FieldType.ENUM, Mixer5TypeElemNames, Mixer5TypeEnumOptions) ); + + List Mixer5VectorElemNames = new ArrayList(); + Mixer5VectorElemNames.add("ThrottleCurve1"); + Mixer5VectorElemNames.add("ThrottleCurve2"); + Mixer5VectorElemNames.add("Roll"); + Mixer5VectorElemNames.add("Pitch"); + Mixer5VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer5Vector", "", UAVObjectField.FieldType.INT8, Mixer5VectorElemNames, null) ); + + List Mixer6TypeElemNames = new ArrayList(); + Mixer6TypeElemNames.add("0"); + List Mixer6TypeEnumOptions = new ArrayList(); + Mixer6TypeEnumOptions.add("Disabled"); + Mixer6TypeEnumOptions.add("Motor"); + Mixer6TypeEnumOptions.add("Servo"); + fields.add( new UAVObjectField("Mixer6Type", "", UAVObjectField.FieldType.ENUM, Mixer6TypeElemNames, Mixer6TypeEnumOptions) ); + + List Mixer6VectorElemNames = new ArrayList(); + Mixer6VectorElemNames.add("ThrottleCurve1"); + Mixer6VectorElemNames.add("ThrottleCurve2"); + Mixer6VectorElemNames.add("Roll"); + Mixer6VectorElemNames.add("Pitch"); + Mixer6VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer6Vector", "", UAVObjectField.FieldType.INT8, Mixer6VectorElemNames, null) ); + + List Mixer7TypeElemNames = new ArrayList(); + Mixer7TypeElemNames.add("0"); + List Mixer7TypeEnumOptions = new ArrayList(); + Mixer7TypeEnumOptions.add("Disabled"); + Mixer7TypeEnumOptions.add("Motor"); + Mixer7TypeEnumOptions.add("Servo"); + fields.add( new UAVObjectField("Mixer7Type", "", UAVObjectField.FieldType.ENUM, Mixer7TypeElemNames, Mixer7TypeEnumOptions) ); + + List Mixer7VectorElemNames = new ArrayList(); + Mixer7VectorElemNames.add("ThrottleCurve1"); + Mixer7VectorElemNames.add("ThrottleCurve2"); + Mixer7VectorElemNames.add("Roll"); + Mixer7VectorElemNames.add("Pitch"); + Mixer7VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer7Vector", "", UAVObjectField.FieldType.INT8, Mixer7VectorElemNames, null) ); + + List Mixer8TypeElemNames = new ArrayList(); + Mixer8TypeElemNames.add("0"); + List Mixer8TypeEnumOptions = new ArrayList(); + Mixer8TypeEnumOptions.add("Disabled"); + Mixer8TypeEnumOptions.add("Motor"); + Mixer8TypeEnumOptions.add("Servo"); + fields.add( new UAVObjectField("Mixer8Type", "", UAVObjectField.FieldType.ENUM, Mixer8TypeElemNames, Mixer8TypeEnumOptions) ); + + List Mixer8VectorElemNames = new ArrayList(); + Mixer8VectorElemNames.add("ThrottleCurve1"); + Mixer8VectorElemNames.add("ThrottleCurve2"); + Mixer8VectorElemNames.add("Roll"); + Mixer8VectorElemNames.add("Pitch"); + Mixer8VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer8Vector", "", UAVObjectField.FieldType.INT8, Mixer8VectorElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("MaxAccel").setValue(1000); + getField("FeedForward").setValue(0); + getField("AccelTime").setValue(0); + getField("DecelTime").setValue(0); + getField("ThrottleCurve1").setValue(0,0); + getField("ThrottleCurve1").setValue(0.25,1); + getField("ThrottleCurve1").setValue(0.5,2); + getField("ThrottleCurve1").setValue(0.75,3); + getField("ThrottleCurve1").setValue(1,4); + getField("ThrottleCurve2").setValue(0,0); + getField("ThrottleCurve2").setValue(0.25,1); + getField("ThrottleCurve2").setValue(0.5,2); + getField("ThrottleCurve2").setValue(0.75,3); + getField("ThrottleCurve2").setValue(1,4); + getField("Mixer1Type").setValue(0); + getField("Mixer1Vector").setValue(0,0); + getField("Mixer1Vector").setValue(0,1); + getField("Mixer1Vector").setValue(0,2); + getField("Mixer1Vector").setValue(0,3); + getField("Mixer1Vector").setValue(0,4); + getField("Mixer2Type").setValue(0); + getField("Mixer2Vector").setValue(0,0); + getField("Mixer2Vector").setValue(0,1); + getField("Mixer2Vector").setValue(0,2); + getField("Mixer2Vector").setValue(0,3); + getField("Mixer2Vector").setValue(0,4); + getField("Mixer3Type").setValue(0); + getField("Mixer3Vector").setValue(0,0); + getField("Mixer3Vector").setValue(0,1); + getField("Mixer3Vector").setValue(0,2); + getField("Mixer3Vector").setValue(0,3); + getField("Mixer3Vector").setValue(0,4); + getField("Mixer4Type").setValue(0); + getField("Mixer4Vector").setValue(0,0); + getField("Mixer4Vector").setValue(0,1); + getField("Mixer4Vector").setValue(0,2); + getField("Mixer4Vector").setValue(0,3); + getField("Mixer4Vector").setValue(0,4); + getField("Mixer5Type").setValue(0); + getField("Mixer5Vector").setValue(0,0); + getField("Mixer5Vector").setValue(0,1); + getField("Mixer5Vector").setValue(0,2); + getField("Mixer5Vector").setValue(0,3); + getField("Mixer5Vector").setValue(0,4); + getField("Mixer6Type").setValue(0); + getField("Mixer6Vector").setValue(0,0); + getField("Mixer6Vector").setValue(0,1); + getField("Mixer6Vector").setValue(0,2); + getField("Mixer6Vector").setValue(0,3); + getField("Mixer6Vector").setValue(0,4); + getField("Mixer7Type").setValue(0); + getField("Mixer7Vector").setValue(0,0); + getField("Mixer7Vector").setValue(0,1); + getField("Mixer7Vector").setValue(0,2); + getField("Mixer7Vector").setValue(0,3); + getField("Mixer7Vector").setValue(0,4); + getField("Mixer8Type").setValue(0); + getField("Mixer8Vector").setValue(0,0); + getField("Mixer8Vector").setValue(0,1); + getField("Mixer8Vector").setValue(0,2); + getField("Mixer8Vector").setValue(0,3); + getField("Mixer8Vector").setValue(0,4); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + MixerSettings obj = new MixerSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public MixerSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (MixerSettings)(objMngr.getObject(MixerSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x4FAE374E; + protected static final String NAME = "MixerSettings"; + protected static String DESCRIPTION = "Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java new file mode 100644 index 000000000..fbd405b40 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java @@ -0,0 +1,167 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Status for the matrix mixer showing the output of each mixer after all scaling + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Status for the matrix mixer showing the output of each mixer after all scaling + +generated from mixerstatus.xml + **/ +public class MixerStatus extends UAVDataObject { + + public MixerStatus() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List Mixer1ElemNames = new ArrayList(); + Mixer1ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer1", "", UAVObjectField.FieldType.FLOAT32, Mixer1ElemNames, null) ); + + List Mixer2ElemNames = new ArrayList(); + Mixer2ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer2", "", UAVObjectField.FieldType.FLOAT32, Mixer2ElemNames, null) ); + + List Mixer3ElemNames = new ArrayList(); + Mixer3ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer3", "", UAVObjectField.FieldType.FLOAT32, Mixer3ElemNames, null) ); + + List Mixer4ElemNames = new ArrayList(); + Mixer4ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer4", "", UAVObjectField.FieldType.FLOAT32, Mixer4ElemNames, null) ); + + List Mixer5ElemNames = new ArrayList(); + Mixer5ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer5", "", UAVObjectField.FieldType.FLOAT32, Mixer5ElemNames, null) ); + + List Mixer6ElemNames = new ArrayList(); + Mixer6ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer6", "", UAVObjectField.FieldType.FLOAT32, Mixer6ElemNames, null) ); + + List Mixer7ElemNames = new ArrayList(); + Mixer7ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer7", "", UAVObjectField.FieldType.FLOAT32, Mixer7ElemNames, null) ); + + List Mixer8ElemNames = new ArrayList(); + Mixer8ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer8", "", UAVObjectField.FieldType.FLOAT32, Mixer8ElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + MixerStatus obj = new MixerStatus(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public MixerStatus GetInstance(UAVObjectManager objMngr, int instID) + { + return (MixerStatus)(objMngr.getObject(MixerStatus.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xF6A33F10; + protected static final String NAME = "MixerStatus"; + protected static String DESCRIPTION = "Status for the matrix mixer showing the output of each mixer after all scaling"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java new file mode 100644 index 000000000..f16ddd199 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java @@ -0,0 +1,147 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The projection of acceleration in the NED reference frame used by @ref Guidance. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The projection of acceleration in the NED reference frame used by @ref Guidance. + +generated from nedaccel.xml + **/ +public class NedAccel extends UAVDataObject { + + public NedAccel() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List NorthElemNames = new ArrayList(); + NorthElemNames.add("0"); + fields.add( new UAVObjectField("North", "cm/s^2", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); + + List EastElemNames = new ArrayList(); + EastElemNames.add("0"); + fields.add( new UAVObjectField("East", "cm/s^2", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); + + List DownElemNames = new ArrayList(); + DownElemNames.add("0"); + fields.add( new UAVObjectField("Down", "cm/s^2", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 10001; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + NedAccel obj = new NedAccel(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public NedAccel GetInstance(UAVObjectManager objMngr, int instID) + { + return (NedAccel)(objMngr.getObject(NedAccel.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x8E852CE8; + protected static final String NAME = "NedAccel"; + protected static String DESCRIPTION = "The projection of acceleration in the NED reference frame used by @ref Guidance."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java new file mode 100644 index 000000000..2a09c2b40 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java @@ -0,0 +1,160 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Someone who knows please enter this + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Someone who knows please enter this + +generated from objectpersistence.xml + **/ +public class ObjectPersistence extends UAVDataObject { + + public ObjectPersistence() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List OperationElemNames = new ArrayList(); + OperationElemNames.add("0"); + List OperationEnumOptions = new ArrayList(); + OperationEnumOptions.add("Load"); + OperationEnumOptions.add("Save"); + OperationEnumOptions.add("Delete"); + fields.add( new UAVObjectField("Operation", "", UAVObjectField.FieldType.ENUM, OperationElemNames, OperationEnumOptions) ); + + List SelectionElemNames = new ArrayList(); + SelectionElemNames.add("0"); + List SelectionEnumOptions = new ArrayList(); + SelectionEnumOptions.add("SingleObject"); + SelectionEnumOptions.add("AllSettings"); + SelectionEnumOptions.add("AllMetaObjects"); + SelectionEnumOptions.add("AllObjects"); + fields.add( new UAVObjectField("Selection", "", UAVObjectField.FieldType.ENUM, SelectionElemNames, SelectionEnumOptions) ); + + List ObjectIDElemNames = new ArrayList(); + ObjectIDElemNames.add("0"); + fields.add( new UAVObjectField("ObjectID", "", UAVObjectField.FieldType.UINT32, ObjectIDElemNames, null) ); + + List InstanceIDElemNames = new ArrayList(); + InstanceIDElemNames.add("0"); + fields.add( new UAVObjectField("InstanceID", "", UAVObjectField.FieldType.UINT32, InstanceIDElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + ObjectPersistence obj = new ObjectPersistence(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public ObjectPersistence GetInstance(UAVObjectManager objMngr, int instID) + { + return (ObjectPersistence)(objMngr.getObject(ObjectPersistence.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x22216832; + protected static final String NAME = "ObjectPersistence"; + protected static String DESCRIPTION = "Someone who knows please enter this"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java new file mode 100644 index 000000000..444009f90 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java @@ -0,0 +1,147 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Contains the current position relative to @ref HomeLocation + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Contains the current position relative to @ref HomeLocation + +generated from positionactual.xml + **/ +public class PositionActual extends UAVDataObject { + + public PositionActual() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List NorthElemNames = new ArrayList(); + NorthElemNames.add("0"); + fields.add( new UAVObjectField("North", "cm", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + + List EastElemNames = new ArrayList(); + EastElemNames.add("0"); + fields.add( new UAVObjectField("East", "cm", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + + List DownElemNames = new ArrayList(); + DownElemNames.add("0"); + fields.add( new UAVObjectField("Down", "cm", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + PositionActual obj = new PositionActual(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public PositionActual GetInstance(UAVObjectManager objMngr, int instID) + { + return (PositionActual)(objMngr.getObject(PositionActual.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xE0739636; + protected static final String NAME = "PositionActual"; + protected static String DESCRIPTION = "Contains the current position relative to @ref HomeLocation"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java new file mode 100644 index 000000000..5cf51df71 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java @@ -0,0 +1,147 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner + +generated from positiondesired.xml + **/ +public class PositionDesired extends UAVDataObject { + + public PositionDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List NorthElemNames = new ArrayList(); + NorthElemNames.add("0"); + fields.add( new UAVObjectField("North", "cm", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + + List EastElemNames = new ArrayList(); + EastElemNames.add("0"); + fields.add( new UAVObjectField("East", "cm", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + + List DownElemNames = new ArrayList(); + DownElemNames.add("0"); + fields.add( new UAVObjectField("Down", "cm", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + PositionDesired obj = new PositionDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public PositionDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (PositionDesired)(objMngr.getObject(PositionDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x2FC4E5BA; + protected static final String NAME = "PositionDesired"; + protected static String DESCRIPTION = "The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner "; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java new file mode 100644 index 000000000..7164c0957 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java @@ -0,0 +1,147 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Status for the matrix mixer showing the output of each mixer after all scaling + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Status for the matrix mixer showing the output of each mixer after all scaling + +generated from ratedesired.xml + **/ +public class RateDesired extends UAVDataObject { + + public RateDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "deg/s", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "deg/s", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "deg/s", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + RateDesired obj = new RateDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public RateDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (RateDesired)(objMngr.getObject(RateDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xBA41B51C; + protected static final String NAME = "RateDesired"; + protected static String DESCRIPTION = "Status for the matrix mixer showing the output of each mixer after all scaling"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java new file mode 100644 index 000000000..4e9f0b8b8 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java @@ -0,0 +1,139 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The raw data from the ultrasound sonar sensor with altitude estimate. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The raw data from the ultrasound sonar sensor with altitude estimate. + +generated from sonaraltitude.xml + **/ +public class SonarAltitude extends UAVDataObject { + + public SonarAltitude() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AltitudeElemNames = new ArrayList(); + AltitudeElemNames.add("0"); + fields.add( new UAVObjectField("Altitude", "m", UAVObjectField.FieldType.FLOAT32, AltitudeElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + SonarAltitude obj = new SonarAltitude(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public SonarAltitude GetInstance(UAVObjectManager objMngr, int instID) + { + return (SonarAltitude)(objMngr.getObject(SonarAltitude.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x1FDD844C; + protected static final String NAME = "SonarAltitude"; + protected static String DESCRIPTION = "The raw data from the ultrasound sonar sensor with altitude estimate."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java new file mode 100644 index 000000000..8cba8a54c --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java @@ -0,0 +1,161 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The desired attitude that @ref StabilizationModule will try and achieve if FlightMode is Stabilized. Comes from @ref ManaulControlModule. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The desired attitude that @ref StabilizationModule will try and achieve if FlightMode is Stabilized. Comes from @ref ManaulControlModule. + +generated from stabilizationdesired.xml + **/ +public class StabilizationDesired extends UAVDataObject { + + public StabilizationDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "degrees", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "degrees", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "degrees", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + List ThrottleElemNames = new ArrayList(); + ThrottleElemNames.add("0"); + fields.add( new UAVObjectField("Throttle", "%", UAVObjectField.FieldType.FLOAT32, ThrottleElemNames, null) ); + + List StabilizationModeElemNames = new ArrayList(); + StabilizationModeElemNames.add("Roll"); + StabilizationModeElemNames.add("Pitch"); + StabilizationModeElemNames.add("Yaw"); + List StabilizationModeEnumOptions = new ArrayList(); + StabilizationModeEnumOptions.add("None"); + StabilizationModeEnumOptions.add("Rate"); + StabilizationModeEnumOptions.add("Attitude"); + fields.add( new UAVObjectField("StabilizationMode", "", UAVObjectField.FieldType.ENUM, StabilizationModeElemNames, StabilizationModeEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + StabilizationDesired obj = new StabilizationDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public StabilizationDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (StabilizationDesired)(objMngr.getObject(StabilizationDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x41AA9DC2; + protected static final String NAME = "StabilizationDesired"; + protected static String DESCRIPTION = "The desired attitude that @ref StabilizationModule will try and achieve if FlightMode is Stabilized. Comes from @ref ManaulControlModule."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java new file mode 100644 index 000000000..74c480e1c --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java @@ -0,0 +1,222 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * PID settings used by the Stabilization module to combine the @ref AttitudeActual and @ref AttitudeDesired to compute @ref ActuatorDesired + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +PID settings used by the Stabilization module to combine the @ref AttitudeActual and @ref AttitudeDesired to compute @ref ActuatorDesired + +generated from stabilizationsettings.xml + **/ +public class StabilizationSettings extends UAVDataObject { + + public StabilizationSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List RollMaxElemNames = new ArrayList(); + RollMaxElemNames.add("0"); + fields.add( new UAVObjectField("RollMax", "degrees", UAVObjectField.FieldType.UINT8, RollMaxElemNames, null) ); + + List PitchMaxElemNames = new ArrayList(); + PitchMaxElemNames.add("0"); + fields.add( new UAVObjectField("PitchMax", "degrees", UAVObjectField.FieldType.UINT8, PitchMaxElemNames, null) ); + + List YawMaxElemNames = new ArrayList(); + YawMaxElemNames.add("0"); + fields.add( new UAVObjectField("YawMax", "degrees", UAVObjectField.FieldType.UINT8, YawMaxElemNames, null) ); + + List ManualRateElemNames = new ArrayList(); + ManualRateElemNames.add("Roll"); + ManualRateElemNames.add("Pitch"); + ManualRateElemNames.add("Yaw"); + fields.add( new UAVObjectField("ManualRate", "degrees/sec", UAVObjectField.FieldType.FLOAT32, ManualRateElemNames, null) ); + + List MaximumRateElemNames = new ArrayList(); + MaximumRateElemNames.add("Roll"); + MaximumRateElemNames.add("Pitch"); + MaximumRateElemNames.add("Yaw"); + fields.add( new UAVObjectField("MaximumRate", "degrees/sec", UAVObjectField.FieldType.FLOAT32, MaximumRateElemNames, null) ); + + List RollRatePIElemNames = new ArrayList(); + RollRatePIElemNames.add("Kp"); + RollRatePIElemNames.add("Ki"); + RollRatePIElemNames.add("ILimit"); + fields.add( new UAVObjectField("RollRatePI", "", UAVObjectField.FieldType.FLOAT32, RollRatePIElemNames, null) ); + + List PitchRatePIElemNames = new ArrayList(); + PitchRatePIElemNames.add("Kp"); + PitchRatePIElemNames.add("Ki"); + PitchRatePIElemNames.add("ILimit"); + fields.add( new UAVObjectField("PitchRatePI", "", UAVObjectField.FieldType.FLOAT32, PitchRatePIElemNames, null) ); + + List YawRatePIElemNames = new ArrayList(); + YawRatePIElemNames.add("Kp"); + YawRatePIElemNames.add("Ki"); + YawRatePIElemNames.add("ILimit"); + fields.add( new UAVObjectField("YawRatePI", "", UAVObjectField.FieldType.FLOAT32, YawRatePIElemNames, null) ); + + List RollPIElemNames = new ArrayList(); + RollPIElemNames.add("Kp"); + RollPIElemNames.add("Ki"); + RollPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("RollPI", "", UAVObjectField.FieldType.FLOAT32, RollPIElemNames, null) ); + + List PitchPIElemNames = new ArrayList(); + PitchPIElemNames.add("Kp"); + PitchPIElemNames.add("Ki"); + PitchPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("PitchPI", "", UAVObjectField.FieldType.FLOAT32, PitchPIElemNames, null) ); + + List YawPIElemNames = new ArrayList(); + YawPIElemNames.add("Kp"); + YawPIElemNames.add("Ki"); + YawPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("YawPI", "", UAVObjectField.FieldType.FLOAT32, YawPIElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("RollMax").setValue(35); + getField("PitchMax").setValue(35); + getField("YawMax").setValue(35); + getField("ManualRate").setValue(150,0); + getField("ManualRate").setValue(150,1); + getField("ManualRate").setValue(150,2); + getField("MaximumRate").setValue(300,0); + getField("MaximumRate").setValue(300,1); + getField("MaximumRate").setValue(300,2); + getField("RollRatePI").setValue(0.0015,0); + getField("RollRatePI").setValue(0,1); + getField("RollRatePI").setValue(0.3,2); + getField("PitchRatePI").setValue(0.0015,0); + getField("PitchRatePI").setValue(0,1); + getField("PitchRatePI").setValue(0.3,2); + getField("YawRatePI").setValue(0.003,0); + getField("YawRatePI").setValue(0,1); + getField("YawRatePI").setValue(0.3,2); + getField("RollPI").setValue(2,0); + getField("RollPI").setValue(0,1); + getField("RollPI").setValue(50,2); + getField("PitchPI").setValue(2,0); + getField("PitchPI").setValue(0,1); + getField("PitchPI").setValue(50,2); + getField("YawPI").setValue(2,0); + getField("YawPI").setValue(0,1); + getField("YawPI").setValue(50,2); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + StabilizationSettings obj = new StabilizationSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public StabilizationSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (StabilizationSettings)(objMngr.getObject(StabilizationSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xE2147404; + protected static final String NAME = "StabilizationSettings"; + protected static String DESCRIPTION = "PID settings used by the Stabilization module to combine the @ref AttitudeActual and @ref AttitudeDesired to compute @ref ActuatorDesired"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java new file mode 100644 index 000000000..9136627f4 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java @@ -0,0 +1,176 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Alarms from OpenPilot to indicate failure conditions or warnings. Set by various modules. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Alarms from OpenPilot to indicate failure conditions or warnings. Set by various modules. + +generated from systemalarms.xml + **/ +public class SystemAlarms extends UAVDataObject { + + public SystemAlarms() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AlarmElemNames = new ArrayList(); + AlarmElemNames.add("OutOfMemory"); + AlarmElemNames.add("StackOverflow"); + AlarmElemNames.add("CPUOverload"); + AlarmElemNames.add("EventSystem"); + AlarmElemNames.add("SDCard"); + AlarmElemNames.add("Telemetry"); + AlarmElemNames.add("ManualControl"); + AlarmElemNames.add("Actuator"); + AlarmElemNames.add("Attitude"); + AlarmElemNames.add("Stabilization"); + AlarmElemNames.add("Guidance"); + AlarmElemNames.add("AHRSComms"); + AlarmElemNames.add("Battery"); + AlarmElemNames.add("FlightTime"); + AlarmElemNames.add("I2C"); + AlarmElemNames.add("GPS"); + List AlarmEnumOptions = new ArrayList(); + AlarmEnumOptions.add("Uninitialised"); + AlarmEnumOptions.add("OK"); + AlarmEnumOptions.add("Warning"); + AlarmEnumOptions.add("Error"); + AlarmEnumOptions.add("Critical"); + fields.add( new UAVObjectField("Alarm", "", UAVObjectField.FieldType.ENUM, AlarmElemNames, AlarmEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 4000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Alarm").setValue(0,0); + getField("Alarm").setValue(0,1); + getField("Alarm").setValue(0,2); + getField("Alarm").setValue(0,3); + getField("Alarm").setValue(0,4); + getField("Alarm").setValue(0,5); + getField("Alarm").setValue(0,6); + getField("Alarm").setValue(0,7); + getField("Alarm").setValue(0,8); + getField("Alarm").setValue(0,9); + getField("Alarm").setValue(0,10); + getField("Alarm").setValue(0,11); + getField("Alarm").setValue(0,12); + getField("Alarm").setValue(0,13); + getField("Alarm").setValue(0,14); + getField("Alarm").setValue(0,15); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + SystemAlarms obj = new SystemAlarms(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public SystemAlarms GetInstance(UAVObjectManager objMngr, int instID) + { + return (SystemAlarms)(objMngr.getObject(SystemAlarms.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x89C3DCB2; + protected static final String NAME = "SystemAlarms"; + protected static String DESCRIPTION = "Alarms from OpenPilot to indicate failure conditions or warnings. Set by various modules."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java new file mode 100644 index 000000000..d01b55b24 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java @@ -0,0 +1,157 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand + +generated from systemsettings.xml + **/ +public class SystemSettings extends UAVDataObject { + + public SystemSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AirframeTypeElemNames = new ArrayList(); + AirframeTypeElemNames.add("0"); + List AirframeTypeEnumOptions = new ArrayList(); + AirframeTypeEnumOptions.add("FixedWing"); + AirframeTypeEnumOptions.add("FixedWingElevon"); + AirframeTypeEnumOptions.add("FixedWingVtail"); + AirframeTypeEnumOptions.add("VTOL"); + AirframeTypeEnumOptions.add("HeliCP"); + AirframeTypeEnumOptions.add("QuadX"); + AirframeTypeEnumOptions.add("QuadP"); + AirframeTypeEnumOptions.add("Hexa"); + AirframeTypeEnumOptions.add("Octo"); + AirframeTypeEnumOptions.add("Custom"); + AirframeTypeEnumOptions.add("HexaX"); + AirframeTypeEnumOptions.add("OctoV"); + AirframeTypeEnumOptions.add("OctoCoaxP"); + AirframeTypeEnumOptions.add("OctoCoaxX"); + AirframeTypeEnumOptions.add("HexaCoax"); + AirframeTypeEnumOptions.add("Tri"); + fields.add( new UAVObjectField("AirframeType", "", UAVObjectField.FieldType.ENUM, AirframeTypeElemNames, AirframeTypeEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("AirframeType").setValue(0); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + SystemSettings obj = new SystemSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public SystemSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (SystemSettings)(objMngr.getObject(SystemSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x3875CEE; + protected static final String NAME = "SystemSettings"; + protected static String DESCRIPTION = "Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java new file mode 100644 index 000000000..7c34360e9 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java @@ -0,0 +1,151 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * CPU and memory usage from OpenPilot computer. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +CPU and memory usage from OpenPilot computer. + +generated from systemstats.xml + **/ +public class SystemStats extends UAVDataObject { + + public SystemStats() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List FlightTimeElemNames = new ArrayList(); + FlightTimeElemNames.add("0"); + fields.add( new UAVObjectField("FlightTime", "ms", UAVObjectField.FieldType.UINT32, FlightTimeElemNames, null) ); + + List HeapRemainingElemNames = new ArrayList(); + HeapRemainingElemNames.add("0"); + fields.add( new UAVObjectField("HeapRemaining", "bytes", UAVObjectField.FieldType.UINT16, HeapRemainingElemNames, null) ); + + List CPULoadElemNames = new ArrayList(); + CPULoadElemNames.add("0"); + fields.add( new UAVObjectField("CPULoad", "%", UAVObjectField.FieldType.UINT8, CPULoadElemNames, null) ); + + List CPUTempElemNames = new ArrayList(); + CPUTempElemNames.add("0"); + fields.add( new UAVObjectField("CPUTemp", "C", UAVObjectField.FieldType.INT8, CPUTempElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + SystemStats obj = new SystemStats(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public SystemStats GetInstance(UAVObjectManager objMngr, int instID) + { + return (SystemStats)(objMngr.getObject(SystemStats.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xAA26FFFA; + protected static final String NAME = "SystemStats"; + protected static String DESCRIPTION = "CPU and memory usage from OpenPilot computer. "; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java new file mode 100644 index 000000000..3ad065b5c --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java @@ -0,0 +1,170 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Task information + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Task information + +generated from taskinfo.xml + **/ +public class TaskInfo extends UAVDataObject { + + public TaskInfo() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List StackRemainingElemNames = new ArrayList(); + StackRemainingElemNames.add("System"); + StackRemainingElemNames.add("Actuator"); + StackRemainingElemNames.add("Attitude"); + StackRemainingElemNames.add("TelemetryTx"); + StackRemainingElemNames.add("TelemetryTxPri"); + StackRemainingElemNames.add("TelemetryRx"); + StackRemainingElemNames.add("GPS"); + StackRemainingElemNames.add("ManualControl"); + StackRemainingElemNames.add("Altitude"); + StackRemainingElemNames.add("AHRSComms"); + StackRemainingElemNames.add("Stabilization"); + StackRemainingElemNames.add("Guidance"); + StackRemainingElemNames.add("FlightPlan"); + fields.add( new UAVObjectField("StackRemaining", "bytes", UAVObjectField.FieldType.UINT16, StackRemainingElemNames, null) ); + + List RunningElemNames = new ArrayList(); + RunningElemNames.add("System"); + RunningElemNames.add("Actuator"); + RunningElemNames.add("Attitude"); + RunningElemNames.add("TelemetryTx"); + RunningElemNames.add("TelemetryTxPri"); + RunningElemNames.add("TelemetryRx"); + RunningElemNames.add("GPS"); + RunningElemNames.add("ManualControl"); + RunningElemNames.add("Altitude"); + RunningElemNames.add("AHRSComms"); + RunningElemNames.add("Stabilization"); + RunningElemNames.add("Guidance"); + RunningElemNames.add("FlightPlan"); + List RunningEnumOptions = new ArrayList(); + RunningEnumOptions.add("False"); + RunningEnumOptions.add("True"); + fields.add( new UAVObjectField("Running", "bool", UAVObjectField.FieldType.ENUM, RunningElemNames, RunningEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 10000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + TaskInfo obj = new TaskInfo(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public TaskInfo GetInstance(UAVObjectManager objMngr, int instID) + { + return (TaskInfo)(objMngr.getObject(TaskInfo.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x50F599F0; + protected static final String NAME = "TaskInfo"; + protected static String DESCRIPTION = "Task information"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java new file mode 100644 index 000000000..6995a02b0 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java @@ -0,0 +1,148 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Select baud rate of telemetry. Warning - this must match your modem. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Select baud rate of telemetry. Warning - this must match your modem. + +generated from telemetrysettings.xml + **/ +public class TelemetrySettings extends UAVDataObject { + + public TelemetrySettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List SpeedElemNames = new ArrayList(); + SpeedElemNames.add("0"); + List SpeedEnumOptions = new ArrayList(); + SpeedEnumOptions.add("2400"); + SpeedEnumOptions.add("4800"); + SpeedEnumOptions.add("9600"); + SpeedEnumOptions.add("19200"); + SpeedEnumOptions.add("38400"); + SpeedEnumOptions.add("57600"); + SpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("Speed", "", UAVObjectField.FieldType.ENUM, SpeedElemNames, SpeedEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Speed").setValue(5); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + TelemetrySettings obj = new TelemetrySettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public TelemetrySettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (TelemetrySettings)(objMngr.getObject(TelemetrySettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xA608C526; + protected static final String NAME = "TelemetrySettings"; + protected static String DESCRIPTION = "Select baud rate of telemetry. Warning - this must match your modem."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java new file mode 100644 index 000000000..4eca6ea82 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java @@ -0,0 +1,87 @@ +/** + ****************************************************************************** + * + * + * @file uavobjectsinittemplate.java + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief the template for the uavobjects init part + * $(GENERATEDWARNING) + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import org.openpilot.uavtalk.uavobjects.*; +import org.openpilot.uavtalk.UAVObjectManager; + +public class UAVObjectsInitialize { + + public static void register(UAVObjectManager objMngr) { + try { + objMngr.registerObject( new ActuatorCommand() ); + objMngr.registerObject( new ActuatorDesired() ); + objMngr.registerObject( new ActuatorSettings() ); + objMngr.registerObject( new AHRSCalibration() ); + objMngr.registerObject( new AHRSSettings() ); + objMngr.registerObject( new AhrsStatus() ); + objMngr.registerObject( new AttitudeActual() ); + objMngr.registerObject( new AttitudeRaw() ); + objMngr.registerObject( new AttitudeSettings() ); + objMngr.registerObject( new BaroAltitude() ); + objMngr.registerObject( new BatterySettings() ); + objMngr.registerObject( new FirmwareIAPObj() ); + objMngr.registerObject( new FlightBatteryState() ); + objMngr.registerObject( new FlightPlanControl() ); + objMngr.registerObject( new FlightPlanSettings() ); + objMngr.registerObject( new FlightPlanStatus() ); + objMngr.registerObject( new FlightTelemetryStats() ); + objMngr.registerObject( new GCSTelemetryStats() ); + objMngr.registerObject( new GPSPosition() ); + objMngr.registerObject( new GPSSatellites() ); + objMngr.registerObject( new GPSTime() ); + objMngr.registerObject( new GuidanceSettings() ); + objMngr.registerObject( new HomeLocation() ); + objMngr.registerObject( new I2CStats() ); + objMngr.registerObject( new ManualControlCommand() ); + objMngr.registerObject( new ManualControlSettings() ); + objMngr.registerObject( new MixerSettings() ); + objMngr.registerObject( new MixerStatus() ); + objMngr.registerObject( new NedAccel() ); + objMngr.registerObject( new ObjectPersistence() ); + objMngr.registerObject( new PositionActual() ); + objMngr.registerObject( new PositionDesired() ); + objMngr.registerObject( new RateDesired() ); + objMngr.registerObject( new SonarAltitude() ); + objMngr.registerObject( new StabilizationDesired() ); + objMngr.registerObject( new StabilizationSettings() ); + objMngr.registerObject( new SystemAlarms() ); + objMngr.registerObject( new SystemSettings() ); + objMngr.registerObject( new SystemStats() ); + objMngr.registerObject( new TaskInfo() ); + objMngr.registerObject( new TelemetrySettings() ); + objMngr.registerObject( new VelocityActual() ); + objMngr.registerObject( new VelocityDesired() ); + objMngr.registerObject( new WatchdogStatus() ); + + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java new file mode 100644 index 000000000..649e6c122 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java @@ -0,0 +1,147 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Updated by @ref AHRSCommsModule and used within @ref GuidanceModule for velocity control + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Updated by @ref AHRSCommsModule and used within @ref GuidanceModule for velocity control + +generated from velocityactual.xml + **/ +public class VelocityActual extends UAVDataObject { + + public VelocityActual() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List NorthElemNames = new ArrayList(); + NorthElemNames.add("0"); + fields.add( new UAVObjectField("North", "cm/s", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + + List EastElemNames = new ArrayList(); + EastElemNames.add("0"); + fields.add( new UAVObjectField("East", "cm/s", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + + List DownElemNames = new ArrayList(); + DownElemNames.add("0"); + fields.add( new UAVObjectField("Down", "cm/s", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + VelocityActual obj = new VelocityActual(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public VelocityActual GetInstance(UAVObjectManager objMngr, int instID) + { + return (VelocityActual)(objMngr.getObject(VelocityActual.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x48009C88; + protected static final String NAME = "VelocityActual"; + protected static String DESCRIPTION = "Updated by @ref AHRSCommsModule and used within @ref GuidanceModule for velocity control"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java new file mode 100644 index 000000000..27f290898 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java @@ -0,0 +1,147 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Used within @ref GuidanceModule to communicate between the task computing the desired velocity and the PID loop to achieve it (running at different rates). + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Used within @ref GuidanceModule to communicate between the task computing the desired velocity and the PID loop to achieve it (running at different rates). + +generated from velocitydesired.xml + **/ +public class VelocityDesired extends UAVDataObject { + + public VelocityDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List NorthElemNames = new ArrayList(); + NorthElemNames.add("0"); + fields.add( new UAVObjectField("North", "cm/s", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + + List EastElemNames = new ArrayList(); + EastElemNames.add("0"); + fields.add( new UAVObjectField("East", "cm/s", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + + List DownElemNames = new ArrayList(); + DownElemNames.add("0"); + fields.add( new UAVObjectField("Down", "cm/s", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 1000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + VelocityDesired obj = new VelocityDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public VelocityDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (VelocityDesired)(objMngr.getObject(VelocityDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x122F5E3A; + protected static final String NAME = "VelocityDesired"; + protected static String DESCRIPTION = "Used within @ref GuidanceModule to communicate between the task computing the desired velocity and the PID loop to achieve it (running at different rates)."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java new file mode 100644 index 000000000..3adcad96b --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java @@ -0,0 +1,143 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * For monitoring the flags in the watchdog and especially the bootup flags + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +For monitoring the flags in the watchdog and especially the bootup flags + +generated from watchdogstatus.xml + **/ +public class WatchdogStatus extends UAVDataObject { + + public WatchdogStatus() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List BootupFlagsElemNames = new ArrayList(); + BootupFlagsElemNames.add("0"); + fields.add( new UAVObjectField("BootupFlags", "", UAVObjectField.FieldType.UINT16, BootupFlagsElemNames, null) ); + + List ActiveFlagsElemNames = new ArrayList(); + ActiveFlagsElemNames.add("0"); + fields.add( new UAVObjectField("ActiveFlags", "", UAVObjectField.FieldType.UINT16, ActiveFlagsElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 5000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.loggingUpdatePeriod = 5000; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + WatchdogStatus obj = new WatchdogStatus(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public WatchdogStatus GetInstance(UAVObjectManager objMngr, int instID) + { + return (WatchdogStatus)(objMngr.getObject(WatchdogStatus.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xD646E910; + protected static final String NAME = "WatchdogStatus"; + protected static String DESCRIPTION = "For monitoring the flags in the watchdog and especially the bootup flags"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file From 72de0c622aa4116a3067cc6fa97e7638063221fb Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 13:12:32 -0600 Subject: [PATCH 014/284] Removed various debugging outputs and exceptions for now (will add back in a more principled manner later). Also updated the auto generated code. --- androidgcs/.classpath | 1 + .../org/openpilot/uavtalk/UAVDataObject.java | 2 +- .../src/org/openpilot/uavtalk/UAVObject.java | 5 +- .../org/openpilot/uavtalk/UAVObjectField.java | 30 +++++++---- .../templates/uavobjectsinittemplate.java | 52 ++++--------------- .../templates/uavobjecttemplate.java | 6 +-- .../java/uavobjectgeneratorjava.cpp | 4 +- 7 files changed, 37 insertions(+), 63 deletions(-) diff --git a/androidgcs/.classpath b/androidgcs/.classpath index b24a2abf5..6f3f456df 100644 --- a/androidgcs/.classpath +++ b/androidgcs/.classpath @@ -1,6 +1,7 @@ + diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java index f0a2248f5..de04f81c5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java @@ -9,7 +9,7 @@ public abstract class UAVDataObject extends UAVObject { * @param isSet * @param name */ - public UAVDataObject(int objID, Boolean isSingleInst, Boolean isSet, String name) throws Exception { + public UAVDataObject(int objID, Boolean isSingleInst, Boolean isSet, String name) { super(objID, isSingleInst, name); mobj = null; this.isSet = isSet; diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index bf2c87d7e..cc6718ebd 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -105,10 +105,9 @@ public abstract class UAVObject { * When unable to unpack a field */ public void initializeFields(List fields, ByteBuffer data, - int numBytes) throws Exception { + int numBytes) { // TODO: QMutexLocker locker(mutex); this.numBytes = numBytes; -// this.data = data; this.fields = fields; // Initialize fields for (int n = 0; n < fields.size(); ++n) { @@ -288,7 +287,7 @@ public abstract class UAVObject { * @throws Exception * @returns The number of bytes copied */ - public int unpack(ByteBuffer dataIn) throws Exception { + public int unpack(ByteBuffer dataIn) { if( dataIn == null ) return 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 78ebd7b52..a5fc6b7da 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -90,8 +90,8 @@ public class UAVObjectField { * to the arm/uavtalk standard (little endian) * @param dataOut * @return the number of bytes added - * @throws Exception */ - public int pack(ByteBuffer dataOut) throws Exception { + **/ + public int pack(ByteBuffer dataOut) { //QMutexLocker locker(obj->getMutex()); // Pack each element in output buffer dataOut.order(ByteOrder.LITTLE_ENDIAN); @@ -147,7 +147,7 @@ public class UAVObjectField { break; case STRING: // TODO: Implement strings - throw new Exception("Strings not yet implemented"); + throw new Error("Strings not yet implemented"); } // Done return getNumBytes(); @@ -358,13 +358,13 @@ public class UAVObjectField { } } - public double getDouble() throws Exception { return getDouble(0); }; - public double getDouble(int index) throws Exception { + public double getDouble() { return getDouble(0); }; + public double getDouble(int index) { return Double.valueOf((Double) getValue(index)); } - public void setDouble(double value) throws Exception { setDouble(value, 0); }; - public void setDouble(double value, int index) throws Exception { + public void setDouble(double value) { setDouble(value, 0); }; + public void setDouble(double value, int index) { setValue(value, index); } @@ -436,9 +436,7 @@ public class UAVObjectField { String sout = new String(); sout += name + ": [ "; for (int n = 0; n < numElements; ++n) - { sout += String.valueOf(n) + "(" + getValue(n) + ") "; - } sout += "] " + units + "\n"; return sout; @@ -488,6 +486,18 @@ public class UAVObjectField { ((ArrayList) data).add((long) 0); } break; + case FLOAT32: + ((ArrayList) data).clear(); + for(int index = 0; index < numElements; ++index) { + ((ArrayList) data).add((float) 0); + } + break; + case ENUM: + ((ArrayList) data).clear(); + for(int index = 0; index < numElements; ++index) { + ((ArrayList) data).add((byte) 0); + } + break; } } @@ -546,8 +556,6 @@ public class UAVObjectField { numBytesPerElement = 0; } clear(); - - System.out.println(this); } /** diff --git a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjectsinittemplate.java b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjectsinittemplate.java index 5185ab237..7f9edb791 100644 --- a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjectsinittemplate.java +++ b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjectsinittemplate.java @@ -26,50 +26,18 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -package org.openpilot.uavtalk; +package org.openpilot.uavtalk.uavobjects; import org.openpilot.uavtalk.uavobjects.*; -import org.openpilot.uavtalk.UAVObject; -import java.util.HashMap; +import org.openpilot.uavtalk.UAVObjectManager; -public class UAVObjects { - - private static UAVObject[] uavobjects=null; - private static HashMap id2obj; - - public static void init() { - if (uavobjects==null) { - uavobjects=new UAVObject[] { -$(OBJINIT) - }; - id2obj=new HashMap(); - for (int i=0;i< uavobjects.length;i++) - id2obj.put(uavobjects[i].getObjID(),i); +public class UAVObjectsInitialize { + + public static void register(UAVObjectManager objMngr) { + try { +$(OBJINIT) + } catch (Exception e) { + e.printStackTrace(); + } } - } - - public static UAVObject[] getUAVObjectArray() { - return uavobjects; - } - - public static boolean hasObjectWithID(int id) { - return id2obj.containsKey(id); - } - - public static UAVObject getObjectByID(int id) { - if (!hasObjectWithID(id)) - return null; - return uavobjects[(Integer)id2obj.get(id)]; - } - - public static UAVObject getObjectByName(String name) { - return uavobjects[0]; - } - - public static void printAll() { - for (UAVObject obj : uavobjects) - System.out.println(obj.getObjName()); - } - -$(OBJGETTER) } \ No newline at end of file diff --git a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java index af8f48fce..64e2461f5 100644 --- a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java +++ b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java @@ -36,7 +36,6 @@ import java.util.ListIterator; import org.openpilot.uavtalk.UAVObjectManager; import org.openpilot.uavtalk.UAVObject; import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVMetaObject; import org.openpilot.uavtalk.UAVObjectField; /** @@ -46,7 +45,7 @@ generated from $(XMLFILE) **/ public class $(NAME) extends UAVDataObject { - public $(NAME)() throws Exception { + public $(NAME)() { super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); List fields = new ArrayList(); @@ -57,10 +56,9 @@ $(FIELDSINIT) int numBytes = 0; ListIterator li = fields.listIterator(); while(li.hasNext()) { - numBytes += li.next().getNumBytesElement(); + numBytes += li.next().getNumBytes(); } NUMBYTES = numBytes; - // Initialize object initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); diff --git a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp index 7319b7767..b8d4b33d5 100644 --- a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp +++ b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp @@ -54,14 +54,14 @@ bool UAVObjectGeneratorJava::generate(UAVObjectParser* parser,QString templatepa ObjectInfo* info=parser->getObjectByIndex(objidx); process_object(info); - javaObjInit.append(" objMngr->registerObject( new " + info->name + "() );\n"); + javaObjInit.append("\t\t\tobjMngr.registerObject( new " + info->name + "() );\n"); objInc.append("#include \"" + info->namelc + ".h\"\n"); } // Write the gcs object inialization files javaInitTemplate.replace( QString("$(OBJINC)"), objInc); javaInitTemplate.replace( QString("$(OBJINIT)"), javaObjInit); - bool res = writeFileIfDiffrent( javaOutputPath.absolutePath() + "/uavobjectsinit.java", javaInitTemplate ); + bool res = writeFileIfDiffrent( javaOutputPath.absolutePath() + "/UAVObjectsInitialize.java", javaInitTemplate ); if (!res) { cout << "Error: Could not write output files" << endl; return false; From 6758d5c5982c480c4301eee0e97b91477aecb30f Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 13:33:56 -0600 Subject: [PATCH 015/284] Make the initial values for enums be the string. Make setValue accept numerical or string constants for enums. Only returns a string though. --- .../src/org/openpilot/uavtalk/UAVObjectField.java | 10 ++++++++-- .../generators/java/uavobjectgeneratorjava.cpp | 8 ++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index a5fc6b7da..bb525a5e0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -343,8 +343,14 @@ public class UAVObjectField { break; } case ENUM: - { - byte val = (byte) options.indexOf((String) data); + { + byte val; + try { + // Test if numeric constant passed in + val = ((Number) data).byteValue(); + } catch (Exception e) { + val = (byte) options.indexOf((String) data); + } //if(val < 0) throw new Exception("Enumerated value not found"); List l = (List) this.data; l.set(index, val); diff --git a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp index b8d4b33d5..e942b238f 100644 --- a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp +++ b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp @@ -210,9 +210,9 @@ bool UAVObjectGeneratorJava::process_object(ObjectInfo* info) { if ( info->fields[n]->type == FIELDTYPE_ENUM ) { - initfields.append( QString("\t\tgetField(\"%1\").setValue(%2);\n") + initfields.append( QString("\t\tgetField(\"%1\").setValue(\"%2\");\n") .arg( info->fields[n]->name ) - .arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[0] ) ) ); + .arg( info->fields[n]->defaultValues[0] ) ); } else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 ) { @@ -233,10 +233,10 @@ bool UAVObjectGeneratorJava::process_object(ObjectInfo* info) for (int idx = 0; idx < info->fields[n]->numElements; ++idx) { if ( info->fields[n]->type == FIELDTYPE_ENUM ) { - initfields.append( QString("\t\tgetField(\"%1\").setValue(%3,%2);\n") + initfields.append( QString("\t\tgetField(\"%1\").setValue(\"%3\",%2);\n") .arg( info->fields[n]->name ) .arg( idx ) - .arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[idx] ) ) ); + .arg( info->fields[n]->defaultValues[idx] ) ); } else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 ) { initfields.append( QString("\t\tgetField(\"%1\").setValue(%3,%2);\n") From 3a71d26604dea12f4d6d5c9d3c00dcb3e7bd0416 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 13:36:49 -0600 Subject: [PATCH 016/284] Some cosmetic changes, also initialize the Metadata properly --- .../src/org/openpilot/uavtalk/UAVMetaObject.java | 13 ++++++++++++- androidgcs/src/org/openpilot/uavtalk/UAVObject.java | 2 +- .../src/org/openpilot/uavtalk/UAVObjectField.java | 6 +----- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java index 70e661d46..98e4bd626 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java @@ -3,12 +3,15 @@ package org.openpilot.uavtalk; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; +import java.util.ListIterator; public class UAVMetaObject extends UAVObject { public UAVMetaObject(int objID, String name, UAVDataObject parent) throws Exception { super(objID, true, name); this.parent = parent; + + ownMetadata = new Metadata(); ownMetadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; ownMetadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; @@ -48,9 +51,17 @@ public class UAVMetaObject extends UAVObject { fields.add( new UAVObjectField("Logging Update Mode", "", UAVObjectField.FieldType.ENUM, 1, updateModeEnum) ); fields.add( new UAVObjectField("Logging Update Period", "", UAVObjectField.FieldType.UINT32, 1, null ) ); + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + + // Initialize object + // Initialize parent super.initialize(0); - super.initializeFields(fields, ByteBuffer.allocate(10), 10); + initializeFields(fields, ByteBuffer.allocate(numBytes), numBytes); // Setup metadata of parent parentMetadata = parent.getDefaultMetadata(); diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index cc6718ebd..a990def2c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -461,7 +461,7 @@ public abstract class UAVObject { * Return a string with the object information (only the header) */ public String toStringBrief() { - return getName() + " ( " + Integer.toHexString(getObjID()) + " " + Integer.toHexString(getInstID()) + " " + getNumBytes() + ")\n"; + return getName() + " (" + Integer.toHexString(getObjID()) + " " + Integer.toHexString(getInstID()) + " " + getNumBytes() + ")\n"; } /** diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index bb525a5e0..0b72c33c8 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -440,11 +440,7 @@ public class UAVObjectField { public String toString() { String sout = new String(); - sout += name + ": [ "; - for (int n = 0; n < numElements; ++n) - sout += String.valueOf(n) + "(" + getValue(n) + ") "; - - sout += "] " + units + "\n"; + sout += name + ": " + ((List) data).toString() + " (" + units + ")\n"; return sout; } From 6158e19df15160ddffbfa61ef75172f4bbe2608a Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 18:22:11 -0600 Subject: [PATCH 017/284] Initial implementation of UAVTalk protocol and a test platform for it and the UAVObjectManager --- .../openpilot/uavtalk/UAVObjectManager.java | 22 + .../src/org/openpilot/uavtalk/UAVTalk.java | 808 ++++++++++++++++++ .../org/openpilot/uavtalk/ObjMngrTest.java | 22 + .../tests/org/openpilot/uavtalk/TalkTest.java | 74 ++ 4 files changed, 926 insertions(+) create mode 100644 androidgcs/src/org/openpilot/uavtalk/UAVTalk.java create mode 100644 androidgcs/tests/org/openpilot/uavtalk/ObjMngrTest.java create mode 100644 androidgcs/tests/org/openpilot/uavtalk/TalkTest.java diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java index d75b14b85..2e531fc85 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java @@ -118,6 +118,7 @@ public class UAVObjectManager { // Create metaobject String mname = obj.getName(); mname += "Meta"; + UAVMetaObject mobj = new UAVMetaObject(obj.getObjID()+1, mname, obj); // Initialize object obj.initialize(0, mobj); @@ -224,6 +225,17 @@ public class UAVObjectManager { */ } + + /** + * Returns a specific object by name only, returns instance ID zero + * @param name The object name + * @return The object or null if not found + */ + public UAVObject getObject(String name) + { + return getObject(name, 0, 0); + } + /** * Get a specific object given its name and instance ID * @returns The object is found or NULL if not @@ -233,6 +245,16 @@ public class UAVObjectManager { return getObject(name, 0, instId); } + /** + * Get a specific object with given object ID and instance ID zero + * @param objId the object id + * @returns The object is found or NULL if not + */ + public UAVObject getObject(int objId) + { + return getObject(null, objId, 0); + } + /** * Get a specific object given its object and instance ID * @returns The object is found or NULL if not diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java new file mode 100644 index 000000000..07b061bc9 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -0,0 +1,808 @@ +package org.openpilot.uavtalk; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class UAVTalk { + + /** + * Constants + */ + private static final int SYNC_VAL = 0x3C; + + private static final short crc_table[] = { + 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, + 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, + 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, + 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, + 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, + 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, + 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, + 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, + 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, + 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, + 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, + 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, + 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, + 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, + 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, + 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 + }; + + enum RxStateType {STATE_SYNC, STATE_TYPE, STATE_SIZE, STATE_OBJID, STATE_INSTID, STATE_DATA, STATE_CS}; + + static final int TYPE_MASK = 0xFC; + static final int TYPE_VER = 0x20; + static final int TYPE_OBJ = (TYPE_VER | 0x00); + static final int TYPE_OBJ_REQ = (TYPE_VER | 0x01); + static final int TYPE_OBJ_ACK = (TYPE_VER | 0x02); + static final int TYPE_ACK = (TYPE_VER | 0x03); + + static final int MIN_HEADER_LENGTH = 8; // sync(1), type (1), size(2), object ID(4) + static final int MAX_HEADER_LENGTH = 10; // sync(1), type (1), size(2), object ID (4), instance ID(2, not used in single objects) + + static final int CHECKSUM_LENGTH = 1; + + static final int MAX_PAYLOAD_LENGTH = 256; + + static final int MAX_PACKET_LENGTH = (MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + CHECKSUM_LENGTH); + + static final int ALL_INSTANCES = 0xFFFF; + static final int TX_BUFFER_SIZE = 2*1024; + + /** + * Private data + */ + InputStream inStream; + OutputStream outStream; + UAVObjectManager objMngr; + + UAVObject respObj; + boolean respAllInstances; + // Variables used by the receive state machine + ByteBuffer rxTmpBuffer /* 4 */; + ByteBuffer rxBuffer; + int rxType; + int rxObjId; + int rxInstId; + int rxLength; + int rxPacketLength; + + int rxCSPacket, rxCS; + int rxCount; + int packetSize; + RxStateType rxState; + ComStats stats = new ComStats(); + + /** + * Comm stats + */ + public class ComStats { + public int txBytes = 0; + public int rxBytes = 0; + public int txObjectBytes = 0; + public int rxObjectBytes = 0; + public int rxObjects = 0; + public int txObjects = 0; + public int txErrors = 0; + public int rxErrors = 0; + } + + /** + * Constructor + */ + public UAVTalk(InputStream inStream, OutputStream outStream, UAVObjectManager objMngr) + { + this.objMngr = objMngr; + this.inStream = inStream; + this.outStream = outStream; + + rxState = RxStateType.STATE_SYNC; + rxPacketLength = 0; + + //mutex = new QMutex(QMutex::Recursive); + + respObj = null; + resetStats(); + rxTmpBuffer = ByteBuffer.allocate(4); + rxTmpBuffer.order(ByteOrder.LITTLE_ENDIAN); + rxBuffer = ByteBuffer.allocate(MAX_PAYLOAD_LENGTH); + rxBuffer.order(ByteOrder.LITTLE_ENDIAN); + + // TOOD: Callback connect(io, SIGNAL(readyRead()), this, SLOT(processInputStream())); + } + + /** + * Reset the statistics counters + */ + public void resetStats() + { + //QMutexLocker locker(mutex); + stats = new ComStats(); + } + + /** + * Get the statistics counters + */ + public ComStats getStats() + { + //QMutexLocker locker(mutex); + return stats; + } + + /** + * Called each time there are data in the input buffer + */ + public void processInputStream() + { + int val; + + while (true) + { + try { + //inStream.wait(); + val = inStream.read(); + } /*catch (InterruptedException e) { + // TODO Auto-generated catch block + System.out.println("Connection was aborted\n"); + e.printStackTrace(); + break; + }*/ catch (IOException e) { + // TODO Auto-generated catch block + System.out.println("Error reading from stream\n"); + e.printStackTrace(); + break; + } + //System.out.println("Received byte " + val + " in state + " + rxState); + processInputByte(val); + } + } + + /** + * Request an update for the specified object, on success the object data would have been + * updated by the GCS. + * \param[in] obj Object to update + * \param[in] allInstances If set true then all instances will be updated + * \return Success (true), Failure (false) + */ + public boolean sendObjectRequest(UAVObject obj, boolean allInstances) + { + //QMutexLocker locker(mutex); + return objectTransaction(obj, TYPE_OBJ_REQ, allInstances); + } + + /** + * Send the specified object through the telemetry link. + * \param[in] obj Object to send + * \param[in] acked Selects if an ack is required + * \param[in] allInstances If set true then all instances will be updated + * \return Success (true), Failure (false) + */ + public boolean sendObject(UAVObject obj, boolean acked, boolean allInstances) + { + //QMutexLocker locker(mutex); + if (acked) + { + return objectTransaction(obj, TYPE_OBJ_ACK, allInstances); + } + else + { + return objectTransaction(obj, TYPE_OBJ, allInstances); + } + } + + /** + * Cancel a pending transaction + */ + public void cancelTransaction() + { + //QMutexLocker locker(mutex); + respObj = null; + } + + /** + * Execute the requested transaction on an object. + * \param[in] obj Object + * \param[in] type Transaction type + * TYPE_OBJ: send object, + * TYPE_OBJ_REQ: request object update + * TYPE_OBJ_ACK: send object with an ack + * \param[in] allInstances If set true then all instances will be updated + * \return Success (true), Failure (false) + */ + public boolean objectTransaction(UAVObject obj, int type, boolean allInstances) + { + // Send object depending on if a response is needed + if (type == TYPE_OBJ_ACK || type == TYPE_OBJ_REQ) + { + if ( transmitObject(obj, type, allInstances) ) + { + respObj = obj; + respAllInstances = allInstances; + return true; + } + else + { + return false; + } + } + else if (type == TYPE_OBJ) + { + return transmitObject(obj, TYPE_OBJ, allInstances); + } + else + { + return false; + } + } + + /** + * Process an byte from the telemetry stream. + * \param[in] rxbyte Received byte + * \return Success (true), Failure (false) + */ + public boolean processInputByte(int rxbyte) + { + assert(objMngr != null); + + // Update stats + stats.rxBytes++; + + rxPacketLength++; // update packet byte count + + // Receive state machine + switch (rxState) + { + case STATE_SYNC: + + if (rxbyte != SYNC_VAL) + break; + + // Initialize and update CRC + rxCS = updateCRC(0, rxbyte); + + rxPacketLength = 1; + + rxState = RxStateType.STATE_TYPE; + break; + + case STATE_TYPE: + + // Update CRC + rxCS = updateCRC(rxCS, rxbyte); + + if ((rxbyte & TYPE_MASK) != TYPE_VER) + { + rxState = RxStateType.STATE_SYNC; + break; + } + + rxType = rxbyte; + + packetSize = 0; + + rxState = RxStateType.STATE_SIZE; + rxCount = 0; + break; + + case STATE_SIZE: + + // Update CRC + rxCS = updateCRC(rxCS, rxbyte); + + if (rxCount == 0) + { + packetSize += rxbyte; + rxCount++; + break; + } + + packetSize += (rxbyte << 8) & 0xff00; + + if (packetSize < MIN_HEADER_LENGTH || packetSize > MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH) + { // incorrect packet size + rxState = RxStateType.STATE_SYNC; + break; + } + + rxCount = 0; + rxState = RxStateType.STATE_OBJID; + rxTmpBuffer.position(0); + break; + + case STATE_OBJID: + + // Update CRC + rxCS = updateCRC(rxCS, rxbyte); + + rxTmpBuffer.put(rxCount++, (byte) (rxbyte & 0xff)); + if (rxCount < 4) + break; + + // Search for object, if not found reset state machine + rxObjId = rxTmpBuffer.getInt(0); + { + UAVObject rxObj = objMngr.getObject(rxObjId); + if (rxObj == null) + { + stats.rxErrors++; + rxState = RxStateType.STATE_SYNC; + break; + } + + // Determine data length + if (rxType == TYPE_OBJ_REQ || rxType == TYPE_ACK) + rxLength = 0; + else + rxLength = rxObj.getNumBytes(); + + // Check length and determine next state + if (rxLength >= MAX_PAYLOAD_LENGTH) + { + stats.rxErrors++; + rxState = RxStateType.STATE_SYNC; + break; + } + + // Check the lengths match + if ((rxPacketLength + rxLength) != packetSize) + { // packet error - mismatched packet size + stats.rxErrors++; + rxState = RxStateType.STATE_SYNC; + break; + } + + // Check if this is a single instance object (i.e. if the instance ID field is coming next) + if (rxObj.isSingleInstance()) + { + // If there is a payload get it, otherwise receive checksum + if (rxLength > 0) + rxState = RxStateType.STATE_DATA; + else + rxState = RxStateType.STATE_CS; + rxInstId = 0; + rxCount = 0; + } + else + { + rxState = RxStateType.STATE_INSTID; + rxCount = 0; + } + } + + break; + + case STATE_INSTID: + + // Update CRC + rxCS = updateCRC(rxCS, rxbyte); + + rxTmpBuffer.put(rxCount++, (byte) (rxbyte & 0xff)); + if (rxCount < 2) + break; + + rxInstId = rxTmpBuffer.getShort(0); + + rxCount = 0; + + // If there is a payload get it, otherwise receive checksum + if (rxLength > 0) + rxState = RxStateType.STATE_DATA; + else + rxState = RxStateType.STATE_CS; + + break; + + case STATE_DATA: + + // Update CRC + rxCS = updateCRC(rxCS, rxbyte); + + //System.out.println(rxCount + "/" + rxLength); + rxBuffer.put(rxCount++, (byte) (rxbyte & 0xff)); + if (rxCount < rxLength) + break; + + rxState = RxStateType.STATE_CS; + rxCount = 0; + break; + + case STATE_CS: + + // The CRC byte + rxCSPacket = rxbyte; + + if (rxCS != rxCSPacket) + { // packet error - faulty CRC + stats.rxErrors++; + rxState = RxStateType.STATE_SYNC; + break; + } + + if (rxPacketLength != (packetSize + 1)) + { // packet error - mismatched packet size + stats.rxErrors++; + rxState = RxStateType.STATE_SYNC; + break; + } + + //mutex->lock(); + rxBuffer.position(0); + receiveObject(rxType, rxObjId, rxInstId, rxBuffer); + stats.rxObjectBytes += rxLength; + stats.rxObjects++; + //mutex->unlock(); + + rxState = RxStateType.STATE_SYNC; + break; + + default: + rxState = RxStateType.STATE_SYNC; + stats.rxErrors++; + } + + // Done + return true; + } + + /** + * Receive an object. This function process objects received through the telemetry stream. + * \param[in] type Type of received message (TYPE_OBJ, TYPE_OBJ_REQ, TYPE_OBJ_ACK, TYPE_ACK) + * \param[in] obj Handle of the received object + * \param[in] instId The instance ID of UAVOBJ_ALL_INSTANCES for all instances. + * \param[in] data Data buffer + * \param[in] length Buffer length + * \return Success (true), Failure (false) + */ + public boolean receiveObject(int type, int objId, int instId, ByteBuffer data) + { + assert(objMngr != null); + + UAVObject obj = null; + boolean error = false; + boolean allInstances = (instId == ALL_INSTANCES? true : false); + + System.out.println("Received object: " + objId + " " + objMngr.getObject(objId).getName()); + // Process message type + switch (type) { + case TYPE_OBJ: + // All instances, not allowed for OBJ messages + if (!allInstances) + { + // Get object and update its data + obj = updateObject(objId, instId, data); + // Check if an ack is pending + if ( obj != null ) + { + updateAck(obj); + } + else + { + error = true; + } + } + else + { + error = true; + } + break; + case TYPE_OBJ_ACK: + // All instances, not allowed for OBJ_ACK messages + if (!allInstances) + { + // Get object and update its data + obj = updateObject(objId, instId, data); + // Transmit ACK + if ( obj != null ) + { + transmitObject(obj, TYPE_ACK, false); + } + else + { + error = true; + } + } + else + { + error = true; + } + break; + case TYPE_OBJ_REQ: + // Get object, if all instances are requested get instance 0 of the object + if (allInstances) + { + obj = objMngr.getObject(objId); + } + else + { + obj = objMngr.getObject(objId, instId); + } + // If object was found transmit it + if (obj != null) + { + transmitObject(obj, TYPE_OBJ, allInstances); + } + else + { + error = true; + } + break; + case TYPE_ACK: + // All instances, not allowed for ACK messages + if (!allInstances) + { + // Get object + obj = objMngr.getObject(objId, instId); + // Check if an ack is pending + if (obj != null) + { + updateAck(obj); + } + else + { + error = true; + } + } + break; + default: + error = true; + } + // Done + return !error; + } + + /** + * Update the data of an object from a byte array (unpack). + * If the object instance could not be found in the list, then a + * new one is created. + */ + public UAVObject updateObject(int objId, int instId, ByteBuffer data) + { + assert(objMngr != null); + + // Get object + UAVObject obj = objMngr.getObject(objId, instId); + // If the instance does not exist create it + if (obj == null) + { + // Get the object type + UAVObject tobj = objMngr.getObject(objId); + if (tobj == null) + { + return null; + } + // Make sure this is a data object + UAVDataObject dobj = null; + try { + dobj = (UAVDataObject) tobj; + } catch (Exception e) { + // Failed to cast to a data object + return null; + } + + // Create a new instance, unpack and register + UAVDataObject instobj = dobj.clone(instId); + try { + if ( !objMngr.registerObject(instobj) ) + { + return null; + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + instobj.unpack(data); + return instobj; + } + else + { + // Unpack data into object instance + // System.out.println("Unpacking: " + data.position() + " / " + data.capacity() ); + obj.unpack(data); + return obj; + } + } + + /** + * Check if a transaction is pending and if yes complete it. + */ + public void updateAck(UAVObject obj) + { + if (respObj != null && respObj.getObjID() == obj.getObjID() && (respObj.getInstID() == obj.getInstID() || respAllInstances)) + { + respObj = null; + // TODO: Signals +// emit transactionCompleted(obj); + } + } + + /** + * Send an object through the telemetry link. + * \param[in] obj Object to send + * \param[in] type Transaction type + * \param[in] allInstances True is all instances of the object are to be sent + * \return Success (true), Failure (false) + */ + public boolean transmitObject(UAVObject obj, int type, boolean allInstances) + { + // If all instances are requested on a single instance object it is an error + if (allInstances && obj.isSingleInstance()) + { + allInstances = false; + } + + // Process message type + if ( type == TYPE_OBJ || type == TYPE_OBJ_ACK ) + { + if (allInstances) + { + // Get number of instances + int numInst = objMngr.getNumInstances(obj.getObjID()); + // Send all instances + for (int instId = 0; instId < numInst; ++instId) + { + UAVObject inst = objMngr.getObject(obj.getObjID(), instId); + transmitSingleObject(inst, type, false); + } + return true; + } + else + { + return transmitSingleObject(obj, type, false); + } + } + else if (type == TYPE_OBJ_REQ) + { + return transmitSingleObject(obj, TYPE_OBJ_REQ, allInstances); + } + else if (type == TYPE_ACK) + { + if (!allInstances) + { + return transmitSingleObject(obj, TYPE_ACK, false); + } + else + { + return false; + } + } + else + { + return false; + } + } + + + /** + * Send an object through the telemetry link. + * \param[in] obj Object handle to send + * \param[in] type Transaction type + * \return Success (true), Failure (false) + */ + public boolean transmitSingleObject(UAVObject obj, int type, boolean allInstances) + { + int length; + int dataOffset; + int objId; + int instId; + int allInstId = ALL_INSTANCES; + + assert(objMngr != null && outStream != null); + + ByteBuffer bbuf = ByteBuffer.allocate(MAX_PACKET_LENGTH); + bbuf.order(ByteOrder.LITTLE_ENDIAN); + + // Determine data length + if (type == TYPE_OBJ_REQ || type == TYPE_ACK) + { + length = 0; + } + else + { + length = obj.getNumBytes(); + } + + // Setup type and object id fields + bbuf.put((byte) (SYNC_VAL & 0xff)); + bbuf.put((byte) (type & 0xff)); + bbuf.putShort((short) (length + + 2 /* SYNC, Type */ + + 2 /* Size */ + + 4 /* ObjID */ + + (obj.isSingleInstance() ? 0 : 2) )); + bbuf.putInt(obj.getObjID()); + + // Setup instance ID if one is required + if ( !obj.isSingleInstance() ) + { + // Check if all instances are requested + if (allInstances) + bbuf.putShort((short) (allInstId & 0xffff)); + else + bbuf.putShort((short) (obj.getInstID() & 0xffff)); + } + + // Check length + if (length >= MAX_PAYLOAD_LENGTH) + return false; + + // Copy data (if any) + if (length > 0) + try { + if ( obj.pack(bbuf) == 0) + return false; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + + // Calculate checksum + bbuf.put((byte) (updateCRC(0, bbuf.array()) & 0xff)); + + try { + outStream.write(bbuf.array()); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + +// //TODO: Need to use a different outStream type and check that the backlog isn't more than TX_BUFFER_SIZE +// // Send buffer, check that the transmit backlog does not grow above limit +// if ( io->bytesToWrite() < TX_BUFFER_SIZE ) +// { +// io->write((const char*)txBuffer, dataOffset+length+CHECKSUM_LENGTH); +// } +// else +// { +// ++stats.txErrors; +// return false; +// } + + // Update stats + ++stats.txObjects; + stats.txBytes += bbuf.position(); + stats.txObjectBytes += length; + + // Done + return true; + } + + /** + * Update the crc value with new data. + * + * Generated by pycrc v0.7.5, http://www.tty1.net/pycrc/ + * using the configuration: + * Width = 8 + * Poly = 0x07 + * XorIn = 0x00 + * ReflectIn = False + * XorOut = 0x00 + * ReflectOut = False + * Algorithm = table-driven + * + * \param crc The current crc value. + * \param data Pointer to a buffer of \a data_len bytes. + * \param length Number of bytes in the \a data buffer. + * \return The updated crc value. + */ + int updateCRC(int crc, int data) + { + return crc_table[crc ^ (data & 0xff)]; + } + int updateCRC(int crc, byte [] data) + { + for (int i = 0; i < data.length; i++) + crc = updateCRC(crc, (int) data[i]); + return crc; + } + + + +} diff --git a/androidgcs/tests/org/openpilot/uavtalk/ObjMngrTest.java b/androidgcs/tests/org/openpilot/uavtalk/ObjMngrTest.java new file mode 100644 index 000000000..0131d1246 --- /dev/null +++ b/androidgcs/tests/org/openpilot/uavtalk/ObjMngrTest.java @@ -0,0 +1,22 @@ +package org.openpilot.uavtalk; + +import static org.junit.Assert.*; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; + +public class ObjMngrTest { + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @Test + public void testGetObjects() { + UAVObjectManager objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); +// System.out.println(objMngr.getObject("ActuatorSettings", 0)); + } + +} diff --git a/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java b/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java new file mode 100644 index 000000000..6dc23530e --- /dev/null +++ b/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java @@ -0,0 +1,74 @@ +package org.openpilot.uavtalk; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.Socket; +import java.nio.ByteBuffer; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; +import org.openpilot.uavtalk.UAVTalk; + + +public class TalkTest { + + static UAVObjectManager objMngr; + static final String IP_ADDRDESS = new String("127.0.0.1"); + static final int PORT_NUM = 8000; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + } + + @Test + public void testProcessInputStream() { + Socket connection = null; + UAVTalk talk = null; + try{ + InetAddress ip = InetAddress.getByName(IP_ADDRDESS); + connection = new Socket(ip, PORT_NUM); + } catch (Exception e) { + e.printStackTrace(); + fail("Couldn't connect to test platform"); + } + + try { + talk = new UAVTalk(connection.getInputStream(), connection.getOutputStream(), objMngr); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Couldn't construct UAVTalk object"); + } + + talk.processInputStream(); + } + + @Test + public void testSendObjectRequest() { + fail("Not yet implemented"); + } + + @Test + public void testSendObject() { + fail("Not yet implemented"); + } + + @Test + public void testReceiveObject() { + fail("Not yet implemented"); + } + + @Test + public void testUpdateObject() { + fail("Not yet implemented"); + } + +} From c7f57dffe3b147698a2057401a2de166bfca8bbf Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 6 Mar 2011 18:22:39 -0600 Subject: [PATCH 018/284] Updates to various objects --- .../uavtalk/uavobjects/AHRSCalibration.java | 2 +- .../uavtalk/uavobjects/AHRSSettings.java | 4 +- .../uavtalk/uavobjects/ActuatorSettings.java | 44 +++++++++---------- .../uavtalk/uavobjects/BatterySettings.java | 2 +- .../uavtalk/uavobjects/FlightPlanControl.java | 2 +- .../uavtalk/uavobjects/FlightPlanStatus.java | 4 +- .../uavtalk/uavobjects/GuidanceSettings.java | 4 +- .../uavtalk/uavobjects/HomeLocation.java | 2 +- .../uavobjects/ManualControlSettings.java | 44 +++++++++---------- .../uavtalk/uavobjects/MixerSettings.java | 16 +++---- .../uavtalk/uavobjects/SystemAlarms.java | 32 +++++++------- .../uavtalk/uavobjects/SystemSettings.java | 2 +- .../uavtalk/uavobjects/TelemetrySettings.java | 2 +- 13 files changed, 80 insertions(+), 80 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java index a3096ad39..922582398 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java @@ -171,7 +171,7 @@ public class AHRSCalibration extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("measure_var").setValue(0); + getField("measure_var").setValue("SET"); getField("accel_bias").setValue(-73.5,0); getField("accel_bias").setValue(-73.5,1); getField("accel_bias").setValue(73.5,2); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java index a38915c28..c49c04778 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java @@ -132,10 +132,10 @@ public class AHRSSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("Algorithm").setValue(1); + getField("Algorithm").setValue("INSGPS_INDOOR_NOMAG"); getField("Downsampling").setValue(20); getField("UpdatePeriod").setValue(1); - getField("BiasCorrectedRaw").setValue(0); + getField("BiasCorrectedRaw").setValue("TRUE"); getField("YawBias").setValue(0); getField("PitchBias").setValue(0); getField("RollBias").setValue(0); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java index ebbfaeb17..542b433d1 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java @@ -358,20 +358,20 @@ public class ActuatorSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("FixedWingRoll1").setValue(8); - getField("FixedWingRoll2").setValue(8); - getField("FixedWingPitch1").setValue(8); - getField("FixedWingPitch2").setValue(8); - getField("FixedWingYaw").setValue(8); - getField("FixedWingThrottle").setValue(8); - getField("VTOLMotorN").setValue(8); - getField("VTOLMotorNE").setValue(8); - getField("VTOLMotorE").setValue(8); - getField("VTOLMotorSE").setValue(8); - getField("VTOLMotorS").setValue(8); - getField("VTOLMotorSW").setValue(8); - getField("VTOLMotorW").setValue(8); - getField("VTOLMotorNW").setValue(8); + getField("FixedWingRoll1").setValue("None"); + getField("FixedWingRoll2").setValue("None"); + getField("FixedWingPitch1").setValue("None"); + getField("FixedWingPitch2").setValue("None"); + getField("FixedWingYaw").setValue("None"); + getField("FixedWingThrottle").setValue("None"); + getField("VTOLMotorN").setValue("None"); + getField("VTOLMotorNE").setValue("None"); + getField("VTOLMotorE").setValue("None"); + getField("VTOLMotorSE").setValue("None"); + getField("VTOLMotorS").setValue("None"); + getField("VTOLMotorSW").setValue("None"); + getField("VTOLMotorW").setValue("None"); + getField("VTOLMotorNW").setValue("None"); getField("ChannelUpdateFreq").setValue(50,0); getField("ChannelUpdateFreq").setValue(50,1); getField("ChannelUpdateFreq").setValue(50,2); @@ -400,14 +400,14 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelMin").setValue(1000,5); getField("ChannelMin").setValue(1000,6); getField("ChannelMin").setValue(1000,7); - getField("ChannelType").setValue(0,0); - getField("ChannelType").setValue(0,1); - getField("ChannelType").setValue(0,2); - getField("ChannelType").setValue(0,3); - getField("ChannelType").setValue(0,4); - getField("ChannelType").setValue(0,5); - getField("ChannelType").setValue(0,6); - getField("ChannelType").setValue(0,7); + getField("ChannelType").setValue("PWM",0); + getField("ChannelType").setValue("PWM",1); + getField("ChannelType").setValue("PWM",2); + getField("ChannelType").setValue("PWM",3); + getField("ChannelType").setValue("PWM",4); + getField("ChannelType").setValue("PWM",5); + getField("ChannelType").setValue("PWM",6); + getField("ChannelType").setValue("PWM",7); getField("ChannelAddr").setValue(0,0); getField("ChannelAddr").setValue(1,1); getField("ChannelAddr").setValue(2,2); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java index 19e477b62..6af673930 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java @@ -121,7 +121,7 @@ public class BatterySettings extends UAVDataObject { { getField("BatteryVoltage").setValue(11.1); getField("BatteryCapacity").setValue(2200); - getField("BatteryType").setValue(0); + getField("BatteryType").setValue("LiPo"); getField("Calibrations").setValue(1,0); getField("Calibrations").setValue(1,1); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java index 2e453eda5..fdc5bfcb0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java @@ -104,7 +104,7 @@ public class FlightPlanControl extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("Command").setValue(0); + getField("Command").setValue("Start"); } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java index 00920553c..2303514c0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java @@ -144,8 +144,8 @@ public class FlightPlanStatus extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("Status").setValue(0); - getField("ErrorType").setValue(0); + getField("Status").setValue("Stopped"); + getField("ErrorType").setValue("None"); getField("Debug1").setValue(0); getField("Debug2").setValue(0); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java index 2cde12f64..2fe8bb437 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java @@ -142,7 +142,7 @@ public class GuidanceSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("GuidanceMode").setValue(0); + getField("GuidanceMode").setValue("DUAL_LOOP"); getField("HorizontalP").setValue(0.2,0); getField("HorizontalP").setValue(150,1); getField("HorizontalVelPID").setValue(0.1,0); @@ -155,7 +155,7 @@ public class GuidanceSettings extends UAVDataObject { getField("VerticalVelPID").setValue(0,1); getField("VerticalVelPID").setValue(0,2); getField("VerticalVelPID").setValue(0,3); - getField("ThrottleControl").setValue(0); + getField("ThrottleControl").setValue("FALSE"); getField("MaxRollPitch").setValue(10); getField("UpdatePeriod").setValue(100); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java index 2adebce70..5941c069c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java @@ -139,7 +139,7 @@ public class HomeLocation extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("Set").setValue(0); + getField("Set").setValue("FALSE"); getField("Latitude").setValue(0); getField("Longitude").setValue(0); getField("Altitude").setValue(0); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java index c14aef758..83697999a 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java @@ -309,28 +309,28 @@ public class ManualControlSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("InputMode").setValue(0); - getField("Roll").setValue(0); - getField("Pitch").setValue(1); - getField("Yaw").setValue(2); - getField("Throttle").setValue(3); - getField("FlightMode").setValue(4); - getField("Accessory1").setValue(8); - getField("Accessory2").setValue(8); - getField("Accessory3").setValue(8); - getField("Arming").setValue(0); - getField("Stabilization1Settings").setValue(2,0); - getField("Stabilization1Settings").setValue(2,1); - getField("Stabilization1Settings").setValue(2,2); - getField("Stabilization2Settings").setValue(2,0); - getField("Stabilization2Settings").setValue(2,1); - getField("Stabilization2Settings").setValue(2,2); - getField("Stabilization3Settings").setValue(2,0); - getField("Stabilization3Settings").setValue(2,1); - getField("Stabilization3Settings").setValue(2,2); - getField("FlightModePosition").setValue(0,0); - getField("FlightModePosition").setValue(1,1); - getField("FlightModePosition").setValue(2,2); + getField("InputMode").setValue("PWM"); + getField("Roll").setValue("Channel1"); + getField("Pitch").setValue("Channel2"); + getField("Yaw").setValue("Channel3"); + getField("Throttle").setValue("Channel4"); + getField("FlightMode").setValue("Channel5"); + getField("Accessory1").setValue("None"); + getField("Accessory2").setValue("None"); + getField("Accessory3").setValue("None"); + getField("Arming").setValue("Always Disarmed"); + getField("Stabilization1Settings").setValue("Attitude",0); + getField("Stabilization1Settings").setValue("Attitude",1); + getField("Stabilization1Settings").setValue("Attitude",2); + getField("Stabilization2Settings").setValue("Attitude",0); + getField("Stabilization2Settings").setValue("Attitude",1); + getField("Stabilization2Settings").setValue("Attitude",2); + getField("Stabilization3Settings").setValue("Attitude",0); + getField("Stabilization3Settings").setValue("Attitude",1); + getField("Stabilization3Settings").setValue("Attitude",2); + getField("FlightModePosition").setValue("Manual",0); + getField("FlightModePosition").setValue("Manual",1); + getField("FlightModePosition").setValue("Manual",2); getField("ChannelMax").setValue(2000,0); getField("ChannelMax").setValue(2000,1); getField("ChannelMax").setValue(2000,2); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java index 554e366f3..9aa87d49e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java @@ -270,49 +270,49 @@ public class MixerSettings extends UAVDataObject { getField("ThrottleCurve2").setValue(0.5,2); getField("ThrottleCurve2").setValue(0.75,3); getField("ThrottleCurve2").setValue(1,4); - getField("Mixer1Type").setValue(0); + getField("Mixer1Type").setValue("Disabled"); getField("Mixer1Vector").setValue(0,0); getField("Mixer1Vector").setValue(0,1); getField("Mixer1Vector").setValue(0,2); getField("Mixer1Vector").setValue(0,3); getField("Mixer1Vector").setValue(0,4); - getField("Mixer2Type").setValue(0); + getField("Mixer2Type").setValue("Disabled"); getField("Mixer2Vector").setValue(0,0); getField("Mixer2Vector").setValue(0,1); getField("Mixer2Vector").setValue(0,2); getField("Mixer2Vector").setValue(0,3); getField("Mixer2Vector").setValue(0,4); - getField("Mixer3Type").setValue(0); + getField("Mixer3Type").setValue("Disabled"); getField("Mixer3Vector").setValue(0,0); getField("Mixer3Vector").setValue(0,1); getField("Mixer3Vector").setValue(0,2); getField("Mixer3Vector").setValue(0,3); getField("Mixer3Vector").setValue(0,4); - getField("Mixer4Type").setValue(0); + getField("Mixer4Type").setValue("Disabled"); getField("Mixer4Vector").setValue(0,0); getField("Mixer4Vector").setValue(0,1); getField("Mixer4Vector").setValue(0,2); getField("Mixer4Vector").setValue(0,3); getField("Mixer4Vector").setValue(0,4); - getField("Mixer5Type").setValue(0); + getField("Mixer5Type").setValue("Disabled"); getField("Mixer5Vector").setValue(0,0); getField("Mixer5Vector").setValue(0,1); getField("Mixer5Vector").setValue(0,2); getField("Mixer5Vector").setValue(0,3); getField("Mixer5Vector").setValue(0,4); - getField("Mixer6Type").setValue(0); + getField("Mixer6Type").setValue("Disabled"); getField("Mixer6Vector").setValue(0,0); getField("Mixer6Vector").setValue(0,1); getField("Mixer6Vector").setValue(0,2); getField("Mixer6Vector").setValue(0,3); getField("Mixer6Vector").setValue(0,4); - getField("Mixer7Type").setValue(0); + getField("Mixer7Type").setValue("Disabled"); getField("Mixer7Vector").setValue(0,0); getField("Mixer7Vector").setValue(0,1); getField("Mixer7Vector").setValue(0,2); getField("Mixer7Vector").setValue(0,3); getField("Mixer7Vector").setValue(0,4); - getField("Mixer8Type").setValue(0); + getField("Mixer8Type").setValue("Disabled"); getField("Mixer8Vector").setValue(0,0); getField("Mixer8Vector").setValue(0,1); getField("Mixer8Vector").setValue(0,2); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java index 9136627f4..e9313472c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java @@ -121,22 +121,22 @@ public class SystemAlarms extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("Alarm").setValue(0,0); - getField("Alarm").setValue(0,1); - getField("Alarm").setValue(0,2); - getField("Alarm").setValue(0,3); - getField("Alarm").setValue(0,4); - getField("Alarm").setValue(0,5); - getField("Alarm").setValue(0,6); - getField("Alarm").setValue(0,7); - getField("Alarm").setValue(0,8); - getField("Alarm").setValue(0,9); - getField("Alarm").setValue(0,10); - getField("Alarm").setValue(0,11); - getField("Alarm").setValue(0,12); - getField("Alarm").setValue(0,13); - getField("Alarm").setValue(0,14); - getField("Alarm").setValue(0,15); + getField("Alarm").setValue("Uninitialised",0); + getField("Alarm").setValue("Uninitialised",1); + getField("Alarm").setValue("Uninitialised",2); + getField("Alarm").setValue("Uninitialised",3); + getField("Alarm").setValue("Uninitialised",4); + getField("Alarm").setValue("Uninitialised",5); + getField("Alarm").setValue("Uninitialised",6); + getField("Alarm").setValue("Uninitialised",7); + getField("Alarm").setValue("Uninitialised",8); + getField("Alarm").setValue("Uninitialised",9); + getField("Alarm").setValue("Uninitialised",10); + getField("Alarm").setValue("Uninitialised",11); + getField("Alarm").setValue("Uninitialised",12); + getField("Alarm").setValue("Uninitialised",13); + getField("Alarm").setValue("Uninitialised",14); + getField("Alarm").setValue("Uninitialised",15); } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java index d01b55b24..99bceb6ba 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java @@ -117,7 +117,7 @@ public class SystemSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("AirframeType").setValue(0); + getField("AirframeType").setValue("FixedWing"); } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java index 6995a02b0..675f9b592 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java @@ -108,7 +108,7 @@ public class TelemetrySettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("Speed").setValue(5); + getField("Speed").setValue("57600"); } From 97b5f758a01e1e5e925abbaad1ba8b6b710ad146 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Mon, 7 Mar 2011 04:54:43 -0600 Subject: [PATCH 019/284] Made a lot of critical functions synchronized to block race conditions (essentialy implements a mutex locker for that object). Also added callbacks to UAVObjects for unpacked and updated. More to come. Finally test case that checks that we get FlightStatus through UAVTalk (i.e. that the aircraft is talking). --- .../src/org/openpilot/uavtalk/UAVObject.java | 49 +++++++++++++++++-- .../org/openpilot/uavtalk/UAVObjectField.java | 18 +++---- .../openpilot/uavtalk/UAVObjectManager.java | 14 +++--- .../src/org/openpilot/uavtalk/UAVTalk.java | 18 ++++++- .../tests/org/openpilot/uavtalk/TalkTest.java | 33 +++++++++++-- 5 files changed, 107 insertions(+), 25 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index a990def2c..6ede86094 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -3,9 +3,50 @@ package org.openpilot.uavtalk; import java.nio.ByteBuffer; import java.util.List; import java.util.ListIterator; +import java.util.Observer; +import java.util.Observable; public abstract class UAVObject { + public class CallbackListener extends Observable { + private UAVObject parent; + + public CallbackListener(UAVObject parent) { + this.parent = parent; + } + + public void event () { + setChanged(); + notifyObservers(parent); + } + } + + private CallbackListener updatedListeners = new CallbackListener(this); + public void addUpdatedObserver(Observer o) { + synchronized(updatedListeners) { + updatedListeners.addObserver(o); + } + } + void updated() { + synchronized(updatedListeners) { + updatedListeners.event(); + } + } + + private CallbackListener unpackedListeners = new CallbackListener(this); + public void addUnpackedObserver(Observer o) { + synchronized(unpackedListeners) { + unpackedListeners.addObserver(o); + } + } + void unpacked() { + synchronized(unpackedListeners) { + System.out.println("Unpacked!: " + unpackedListeners.countObservers() + " " + getName()); + unpackedListeners.event(); + } + } + + /** * Object update mode */ @@ -298,10 +339,12 @@ public abstract class UAVObject { UAVObjectField field = li.next(); numBytes += field.unpack(dataIn); } + + // Trigger all the listeners for the unpack event + unpacked(); + updated(); + return numBytes; - // TODO: Callbacks - // emit objectUnpacked(this); // trigger object updated event - // emit objectUpdated(this); } // /** diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 0b72c33c8..21444a04b 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -91,8 +91,7 @@ public class UAVObjectField { * @param dataOut * @return the number of bytes added **/ - public int pack(ByteBuffer dataOut) { - //QMutexLocker locker(obj->getMutex()); + public synchronized int pack(ByteBuffer dataOut) { // Pack each element in output buffer dataOut.order(ByteOrder.LITTLE_ENDIAN); switch (type) @@ -153,7 +152,7 @@ public class UAVObjectField { return getNumBytes(); } - public int unpack(ByteBuffer dataIn) { + public synchronized int unpack(ByteBuffer dataIn) { // Unpack each element from input buffer dataIn.order(ByteOrder.LITTLE_ENDIAN); switch (type) @@ -240,10 +239,9 @@ public class UAVObjectField { return getNumBytes(); } - Object getValue() { return getValue(0); }; + public Object getValue() { return getValue(0); }; @SuppressWarnings("unchecked") - Object getValue(int index) { -// QMutexLocker locker(obj->getMutex()); + public synchronized Object getValue(int index) { // Check that index is not out of bounds if ( index >= numElements ) { @@ -287,8 +285,7 @@ public class UAVObjectField { public void setValue(Object data) { setValue(data,0); } @SuppressWarnings("unchecked") - public void setValue(Object data, int index) { - // QMutexLocker locker(obj->getMutex()); + public synchronized void setValue(Object data, int index) { // Check that index is not out of bounds //if ( index >= numElements ); //throw new Exception("Index out of bounds"); @@ -361,6 +358,7 @@ public class UAVObjectField { //throw new Exception("Sorry I haven't implemented strings yet"); } } + obj.updated(); } } @@ -449,7 +447,7 @@ public class UAVObjectField { } @SuppressWarnings("unchecked") - public void clear() { + public synchronized void clear() { switch (type) { case INT8: @@ -503,7 +501,7 @@ public class UAVObjectField { } } - public void constructorInitialize(String name, String units, FieldType type, List elementNames, List options) { + public synchronized void constructorInitialize(String name, String units, FieldType type, List elementNames, List options) { // Copy params this.name = name; this.units = units; diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java index 2e531fc85..74ddb95fb 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java @@ -23,7 +23,7 @@ public class UAVObjectManager { * updates. * @throws Exception */ - public boolean registerObject(UAVDataObject obj) throws Exception + public synchronized boolean registerObject(UAVDataObject obj) throws Exception { // QMutexLocker locker(mutex); @@ -128,7 +128,7 @@ public class UAVObjectManager { return true; } - public void addObject(UAVObject obj) + public synchronized void addObject(UAVObject obj) { // Add to list List ls = new ArrayList(); @@ -143,15 +143,15 @@ public class UAVObjectManager { */ public List> getObjects() { - //QMutexLocker locker(mutex); return objects; } /** * Same as getObjects() but will only return DataObjects. */ - public List< List > getDataObjects() + public List< List > getDataObjects() { + assert(false); // TOOD This return new ArrayList>(); /* QMutexLocker locker(mutex); @@ -190,6 +190,7 @@ public class UAVObjectManager { */ public List > getMetaObjects() { + assert(false); // TODO return new ArrayList< List >(); /* QMutexLocker locker(mutex); @@ -267,7 +268,7 @@ public class UAVObjectManager { /** * Helper function for the public getObject() functions. */ - public UAVObject getObject(String name, int objId, int instId) + public synchronized UAVObject getObject(String name, int objId, int instId) { //QMutexLocker locker(mutex); // Check if this object type is already in the list @@ -310,9 +311,8 @@ public class UAVObjectManager { /** * Helper function for the public getObjectInstances() */ - public List getObjectInstances(String name, int objId) + public synchronized List getObjectInstances(String name, int objId) { - //QMutexLocker locker(mutex); // Check if this object type is already in the list ListIterator> objIter = objects.listIterator(); while(objIter.hasNext()) { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 07b061bc9..7ea9c7c60 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -10,6 +10,22 @@ import java.nio.ByteOrder; public class UAVTalk { + private Thread inputProcessingThread = null; + /** + * A reference to the thread for processing the incoming stream + * @return + */ + public Thread getInputProcessThread() { + if(inputProcessingThread == null) + + inputProcessingThread = new Thread() { + public void run() { + processInputStream(); + } + }; + return inputProcessingThread; + } + /** * Constants */ @@ -684,7 +700,7 @@ public class UAVTalk { * \param[in] type Transaction type * \return Success (true), Failure (false) */ - public boolean transmitSingleObject(UAVObject obj, int type, boolean allInstances) + public synchronized boolean transmitSingleObject(UAVObject obj, int type, boolean allInstances) { int length; int dataOffset; diff --git a/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java b/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java index 6dc23530e..252927122 100644 --- a/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java +++ b/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java @@ -9,6 +9,8 @@ import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; import java.nio.ByteBuffer; +import java.util.Observable; +import java.util.Observer; import org.junit.BeforeClass; import org.junit.Test; @@ -20,8 +22,9 @@ public class TalkTest { static UAVObjectManager objMngr; static final String IP_ADDRDESS = new String("127.0.0.1"); - static final int PORT_NUM = 8000; - + static final int PORT_NUM = 7777; + boolean succeed = false; + @BeforeClass public static void setUpBeforeClass() throws Exception { objMngr = new UAVObjectManager(); @@ -29,7 +32,7 @@ public class TalkTest { } @Test - public void testProcessInputStream() { + public void testGetFlightStatus() { Socket connection = null; UAVTalk talk = null; try{ @@ -48,7 +51,29 @@ public class TalkTest { fail("Couldn't construct UAVTalk object"); } - talk.processInputStream(); + Thread inputStream = talk.getInputProcessThread(); + inputStream.start(); + + succeed = false; + + UAVObject obj = objMngr.getObject("FlightTelemetryStats"); + + obj.addUpdatedObserver( new Observer() { + public void update(Observable observable, Object data) { + // TODO Auto-generated method stub + System.out.println("Updated: " + data.toString()); + succeed = true; + } + }); + + try { + Thread.sleep(1000); + } catch (InterruptedException e1) { + } + + if(!succeed) + fail("Never received a FlightTelemetryStats update"); + } @Test From 1ffe0691f55820490c5178424b602eb7b017bf0f Mon Sep 17 00:00:00 2001 From: James Cotton Date: Mon, 7 Mar 2011 04:56:14 -0600 Subject: [PATCH 020/284] Test case for the callbacks --- .../org/openpilot/uavtalk/DataObjectTest.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 androidgcs/tests/org/openpilot/uavtalk/DataObjectTest.java diff --git a/androidgcs/tests/org/openpilot/uavtalk/DataObjectTest.java b/androidgcs/tests/org/openpilot/uavtalk/DataObjectTest.java new file mode 100644 index 000000000..0f8106cc5 --- /dev/null +++ b/androidgcs/tests/org/openpilot/uavtalk/DataObjectTest.java @@ -0,0 +1,95 @@ +package org.openpilot.uavtalk; + +import static org.junit.Assert.*; + +import java.nio.ByteBuffer; +import java.util.Observer; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openpilot.uavtalk.uavobjects.ActuatorCommand; +import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; + +import android.database.Observable; + +public class DataObjectTest { + + boolean succeed = false; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @Test + public void testUpdatedObserver() { + + succeed = false; + + UAVObject obj = new ActuatorCommand(); + obj.addUpdatedObserver( new Observer() { + + public void update(java.util.Observable observable, Object data) { + System.out.println("Updated: " + data.toString()); + succeed = true; + } + }); + obj.updated(); + + if(!succeed) + fail("No callback"); + + System.out.println("Done"); + + } + + @Test + public void testUpdatedViaObjMngr() { + succeed = false; + + UAVObjectManager objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + + UAVObject obj = objMngr.getObject("FlightTelemetryStats"); + obj.addUpdatedObserver( new Observer() { + + public void update(java.util.Observable observable, Object data) { + System.out.println("Updated: " + data.toString()); + succeed = true; + } + }); + objMngr.getObject("FlightTelemetryStats").updated(); + + if(!succeed) + fail("No callback"); + System.out.println("Done"); + + } + + @Test + public void testUnpackedViaObjMngr() { + succeed = false; + + UAVObjectManager objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + + UAVObject obj = objMngr.getObject("FlightTelemetryStats"); + obj.addUnpackedObserver( new Observer() { + + public void update(java.util.Observable observable, Object data) { + System.out.println("Updated: " + data.toString()); + succeed = true; + } + }); + + ByteBuffer bbuf = ByteBuffer.allocate(obj.getNumBytes()); + objMngr.getObject("FlightTelemetryStats").unpack(bbuf); + + if(!succeed) + fail("No callback"); + + System.out.println("Done"); + + } + + +} From 01e9d1a47231f7323250e25cb6edbe242c9dc5e0 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Mon, 7 Mar 2011 11:26:50 -0600 Subject: [PATCH 021/284] Add isMetadata() instead of testing whether dynamic cast fails --- androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java | 1 + androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java | 5 +++++ androidgcs/src/org/openpilot/uavtalk/UAVObject.java | 1 + 3 files changed, 7 insertions(+) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java index de04f81c5..5694cc9d8 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java @@ -24,6 +24,7 @@ public abstract class UAVDataObject extends UAVObject { super.initialize(instID); } + public boolean isMetadata() { return true; }; /** * Assign a metaobject */ diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java index 98e4bd626..7aab176ef 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java @@ -66,6 +66,11 @@ public class UAVMetaObject extends UAVObject { // Setup metadata of parent parentMetadata = parent.getDefaultMetadata(); } + + @Override + public boolean isMetadata() { + return true; + }; /** * Get the parent object diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 6ede86094..6d35df822 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -46,6 +46,7 @@ public abstract class UAVObject { } } + public abstract boolean isMetadata(); /** * Object update mode From b0f826758809c8d526d5a8f2f8ab7c8e4a05ef54 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Mon, 7 Mar 2011 11:27:21 -0600 Subject: [PATCH 022/284] Initial start of the telemetry system which interfaces between UAVTalk and the ObjectManager/Objects --- .../src/org/openpilot/uavtalk/Telemetry.java | 25 ++ .../openpilot/uavtalk/TelemetryManager.java | 5 + .../openpilot/uavtalk/TelemetryMonitor.java | 263 ++++++++++++++++++ 3 files changed, 293 insertions(+) create mode 100644 androidgcs/src/org/openpilot/uavtalk/Telemetry.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/TelemetryManager.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java new file mode 100644 index 000000000..88bc33de5 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -0,0 +1,25 @@ +package org.openpilot.uavtalk; + +public class Telemetry { + + private TelemetryStats stats; + public class TelemetryStats { + public int txBytes; + public int rxBytes; + public int txObjectBytes; + public int rxObjectBytes; + public int rxObjects; + public int txObjects; + public int txErrors; + public int rxErrors; + public int txRetries; + } ; + + public TelemetryStats getStats() { + return stats; + } + + public void resetStats() { + stats = new TelemetryStats(); + } +} diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryManager.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryManager.java new file mode 100644 index 000000000..7540a1423 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryManager.java @@ -0,0 +1,5 @@ +package org.openpilot.uavtalk; + +public class TelemetryManager { + +} diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java new file mode 100644 index 000000000..40fc220cc --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -0,0 +1,263 @@ +package org.openpilot.uavtalk; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import java.util.Observable; +import java.util.Observer; +import java.util.Timer; +import java.util.TimerTask; + +import org.openpilot.uavtalk.uavobjects.FlightTelemetryStats; +import org.openpilot.uavtalk.uavobjects.GCSTelemetryStats; + +import android.util.Log; + +public class TelemetryMonitor { + + private static final String TAG = "TelemetryMonitor"; + + static final int STATS_UPDATE_PERIOD_MS = 4000; + static final int STATS_CONNECT_PERIOD_MS = 1000; + static final int CONNECTION_TIMEOUT_MS = 8000; + + private UAVObjectManager objMngr; + private Telemetry tel; + private UAVObject objPending; + private UAVObject gcsStatsObj; + private UAVObject flightStatsObj; + private Timer periodicTask; + private int currentPeriod; + private List queue; + + public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel) + { + this.objMngr = objMngr; + this.tel = tel; + this.objPending = null; + queue = new ArrayList(); + + // Get stats objects + gcsStatsObj = objMngr.getObject("GCSTelemetryStats"); + flightStatsObj = objMngr.getObject("FlightTelemetryStats"); + + flightStatsObj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + flightStatsUpdated((UAVObject) data); + } + }); + + // Start update timer + setPeriod(STATS_CONNECT_PERIOD_MS); + } + + /** + * Initiate object retrieval, initialize queue with objects to be retrieved. + */ + public void startRetrievingObjects() + { + // Clear object queue + queue.clear(); + // Get all objects, add metaobjects, settings and data objects with OnChange update mode to the queue + List< List > objs = objMngr.getObjects(); + + ListIterator> objListIterator = objs.listIterator(); + while( objListIterator.hasNext() ) + { + List instList = objListIterator.next(); + UAVObject obj = instList.get(0); + UAVObject.Metadata mdata = obj.getMetadata(); + if ( mdata.gcsTelemetryUpdateMode != UAVObject.UpdateMode.UPDATEMODE_NEVER ) + { + if ( obj.isMetadata() ) + { + queue.add(obj); + } + else /* Data object */ + { + UAVDataObject dobj = (UAVDataObject) obj; + if ( dobj.isSettings() ) + { + queue.add(obj); + } + else + { + if ( mdata.flightTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE ) + { + queue.add(obj); + } + } + } + } + } + // Start retrieving + Log.d(TAG,"Starting to retrieve meta and settings objects from the autopilot (%1 objects)" + queue.size()) ; + retrieveNextObject(); + } + + /** + * Cancel the object retrieval + */ + public void stopRetrievingObjects() + { + //qxtLog->debug("Object retrieval has been cancelled"); + queue.clear(); + } + + /** + * Retrieve the next object in the queue + */ + public void retrieveNextObject() + { + // If queue is empty return + if ( queue.isEmpty() ) + { + //qxtLog->debug("Object retrieval completed"); + //emit connected(); + return; + } + // Get next object from the queue + UAVObject obj = queue.remove(0); + + Log.d(TAG, "Retrieving object: " + obj.getName()) ; + // Connect to object + //connect(obj, SIGNAL(transactionCompleted(UAVObject*,bool)), this, SLOT(transactionCompleted(UAVObject*,bool))); + // Request update + obj.requestUpdate(); + objPending = obj; + } + + /** + * Called by the retrieved object when a transaction is completed. + */ + public void transactionCompleted(UAVObject obj, boolean success) + { + //QMutexLocker locker(mutex); + // Disconnect from sending object + //obj->disconnect(this); + objPending = null; + + // Process next object if telemetry is still available + if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 ) + { + retrieveNextObject(); + } + else + { + stopRetrievingObjects(); + } + } + + /** + * Called each time the flight stats object is updated by the autopilot + */ + public synchronized void flightStatsUpdated(UAVObject obj) + { + // Force update if not yet connected + if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") != 0 || + ((String) flightStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 ) + { + processStatsUpdates(); + } + } + + /** + * Called periodically to update the statistics and connection status. + */ + public synchronized void processStatsUpdates() + { + // Get telemetry stats + Telemetry.TelemetryStats telStats = tel.getStats(); + tel.resetStats(); + + // Update stats object + gcsStatsObj.getField("RxDataRate").setDouble( (float)telStats.rxBytes / ((float)currentPeriod/1000.0) ); + gcsStatsObj.getField("TxDataRate").setDouble( (float)telStats.txBytes / ((float)currentPeriod/1000.0) ); + UAVObjectField field = gcsStatsObj.getField("RxFailures"); + field.setDouble(field.getDouble() + telStats.rxErrors); + field = gcsStatsObj.getField("TxFailures"); + field.setDouble(field.getDouble() + telStats.txErrors); + field = gcsStatsObj.getField("TxRetries"); + field.setDouble(field.getDouble() + telStats.txRetries); + + // Check for a connection timeout + boolean connectionTimeout; + if ( telStats.rxObjects > 0 ) + { + //connectionTimer.start(); + } + if ( connectionTimer.elapsed() > CONNECTION_TIMEOUT_MS ) + { + connectionTimeout = true; + } + else + { + connectionTimeout = false; + } + + // Update connection state + int oldStatus = gcsStats.Status; + if ( gcsStats.Status == GCSTelemetryStats::STATUS_DISCONNECTED ) + { + // Request connection + gcsStats.Status = GCSTelemetryStats::STATUS_HANDSHAKEREQ; + } + else if ( gcsStats.Status == GCSTelemetryStats::STATUS_HANDSHAKEREQ ) + { + // Check for connection acknowledge + if ( flightStats.Status == FlightTelemetryStats::STATUS_HANDSHAKEACK ) + { + gcsStats.Status = GCSTelemetryStats::STATUS_CONNECTED; + } + } + else if ( gcsStats.Status == GCSTelemetryStats::STATUS_CONNECTED ) + { + // Check if the connection is still active and the the autopilot is still connected + if (flightStats.Status == FlightTelemetryStats::STATUS_DISCONNECTED || connectionTimeout) + { + gcsStats.Status = GCSTelemetryStats::STATUS_DISCONNECTED; + } + } + + // Set data + gcsStatsObj->setData(gcsStats); + + // Force telemetry update if not yet connected + if ( gcsStats.Status != GCSTelemetryStats::STATUS_CONNECTED || + flightStats.Status != FlightTelemetryStats::STATUS_CONNECTED ) + { + gcsStatsObj->updated(); + } + + // Act on new connections or disconnections + if (gcsStats.Status == GCSTelemetryStats::STATUS_CONNECTED && gcsStats.Status != oldStatus) + { + setPeriod(STATS_UPDATE_PERIOD_MS); + statsTimer->setInterval(STATS_UPDATE_PERIOD_MS); + Log.d(TAG,"Connection with the autopilot established"); + startRetrievingObjects(); + } + if (gcsStats.Status == GCSTelemetryStats::STATUS_DISCONNECTED && gcsStats.Status != oldStatus) + { + setPeriod(STATS_CONNECT_PERIOD_MS); + Log.d(TAG,"Connection with the autopilot lost"); + Log.d(TAG,"Trying to connect to the autopilot"); + emit disconnected(); + } + } + + private void setPeriod(int ms) { + if(periodicTask == null) + periodicTask = new Timer(); + + periodicTask.cancel(); + currentPeriod = ms; + periodicTask.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + processStatsUpdates(); + } + }, currentPeriod, currentPeriod); + } + +} From 3d7f4e227304c1012a3e94305780f3cf00340a30 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Wed, 9 Mar 2011 02:44:25 -0600 Subject: [PATCH 023/284] A few more synchronized statements and deep cloning of objects --- .../src/org/openpilot/uavtalk/UAVObject.java | 30 ++-- .../org/openpilot/uavtalk/UAVObjectField.java | 13 +- .../openpilot/uavtalk/UAVObjectManager.java | 130 +++++++++--------- 3 files changed, 97 insertions(+), 76 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 6d35df822..adfece03e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -1,6 +1,7 @@ package org.openpilot.uavtalk; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import java.util.Observer; @@ -128,8 +129,7 @@ public abstract class UAVObject { // this.mutex = new QMutex(QMutex::Recursive); }; - public void initialize(int instID) { - // QMutexLocker locker(mutex); + public synchronized void initialize(int instID) { this.instID = instID; } @@ -146,9 +146,8 @@ public abstract class UAVObject { * @throws Exception * When unable to unpack a field */ - public void initializeFields(List fields, ByteBuffer data, + public synchronized void initializeFields(List fields, ByteBuffer data, int numBytes) { - // TODO: QMutexLocker locker(mutex); this.numBytes = numBytes; this.fields = fields; // Initialize fields @@ -267,15 +266,13 @@ public abstract class UAVObject { * Get the number of fields held by this object */ public int getNumFields() { - // QMutexLocker locker(mutex); return fields.size(); } /** * Get the object's fields */ - public List getFields() { - // QMutexLocker locker(mutex); + public synchronized List getFields() { return fields; } @@ -286,7 +283,6 @@ public abstract class UAVObject { * @returns The field or NULL if not found */ public UAVObjectField getField(String name) { - // QMutexLocker locker(mutex); // Look for field ListIterator li = fields.listIterator(); while (li.hasNext()) { @@ -307,8 +303,7 @@ public abstract class UAVObject { * @returns The number of bytes copied * @note The array must already have enough space allocated for the object */ - public int pack(ByteBuffer dataOut) throws Exception { - // QMutexLocker locker(mutex); + public synchronized int pack(ByteBuffer dataOut) throws Exception { if (dataOut.remaining() < getNumBytes()) throw new Exception("Not enough bytes in ByteBuffer to pack object"); int numBytes = 0; @@ -329,7 +324,7 @@ public abstract class UAVObject { * @throws Exception * @returns The number of bytes copied */ - public int unpack(ByteBuffer dataIn) { + public synchronized int unpack(ByteBuffer dataIn) { if( dataIn == null ) return 0; @@ -532,8 +527,17 @@ public abstract class UAVObject { /** * Java specific functions */ - public UAVObject clone() { - return (UAVObject) clone(); + public synchronized UAVObject clone() { + UAVObject newObj = clone(); + List newFields = new ArrayList(); + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + UAVObjectField nf = li.next().clone(); + nf.initialize(newObj); + newFields.add(nf); + } + newObj.initializeFields(newFields, ByteBuffer.allocate(numBytes), numBytes); + return newObj; } /** diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 21444a04b..2fd7f7846 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -617,6 +617,17 @@ public class UAVObjectField { return num; } + + @Override + public UAVObjectField clone() + { + UAVObjectField newField = new UAVObjectField(new String(name), new String(units), type, + new ArrayList(elementNames), + new ArrayList(options)); + newField.initialize(obj); + newField.data = data; + return newField; + } private String name; private String units; @@ -626,7 +637,7 @@ public class UAVObjectField { private int numElements; private int numBytesPerElement; private int offset; - private Object data; private UAVObject obj; + protected Object data; } diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java index 74ddb95fb..63f535eac 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java @@ -3,9 +3,29 @@ package org.openpilot.uavtalk; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; +import java.util.Observable; +import java.util.Observer; public class UAVObjectManager { + public class CallbackListener extends Observable { + public void event (UAVObject obj) { + setChanged(); + notifyObservers(obj); + } + } + private CallbackListener newInstance = new CallbackListener(); + public void addNewInstanceObserver(Observer o) { + synchronized(newInstance) { + newInstance.addObserver(o); + } + } + private CallbackListener newObject = new CallbackListener(); + public void addNewObjectObserver(Observer o) { + synchronized(newObject) { + newObject.addObserver(o); + } + } private final int MAX_INSTANCES = 10; // Use array list to store objects since rarely added or deleted @@ -79,11 +99,12 @@ public class UAVObjectManager { UAVDataObject newObj = obj.clone(instID); newObj.initialize(mobj); instList.add(newObj); - // emit new instance signal + newInstance.event(newObj); } obj.initialize(mobj); //emit new instance signal instList.add(obj); + newInstance.event(obj); instIter = instList.listIterator(); while(instIter.hasNext()) { @@ -101,13 +122,13 @@ public class UAVObjectManager { UAVDataObject cobj = obj.clone(instId); cobj.initialize(mobj); instList.add(cobj); - // emit newInstance(cobj); + newInstance.event(cobj); } // Finally, initialize the actual object instance obj.initialize(mobj); // Add the actual object instance in the list instList.add(obj); - //emit newInstance(obj); + newInstance.event(obj); return true; } @@ -149,81 +170,67 @@ public class UAVObjectManager { /** * Same as getObjects() but will only return DataObjects. */ - public List< List > getDataObjects() + public synchronized List< List > getDataObjects() { - assert(false); // TOOD This - return new ArrayList>(); - - /* QMutexLocker locker(mutex); - QList< QList > dObjects; + List< List > dObjects = new ArrayList< List > (); // Go through objects and copy to new list when types match - for (int objidx = 0; objidx < objects.length(); ++objidx) - { - if (objects[objidx].length() > 0) - { - // Check type - UAVDataObject* obj = dynamic_cast(objects[objidx][0]); - if (obj != NULL) - { - // Create instance list - QList list; - // Go through instances and cast them to UAVDataObject, then add to list - for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) - { - obj = dynamic_cast(objects[objidx][instidx]); - if (obj != NULL) - { - list.append(obj); - } - } - // Append to object list - dObjects.append(list); - } + ListIterator> objIt = objects.listIterator(0); + + // Check if this object type is already in the list + while(objIt.hasNext()) { + List instList = objIt.next(); + + // If no instances skip + if(instList.size() == 0) + continue; + + // If meta data skip + if(instList.get(0).isMetadata()) + continue; + + List newInstList = new ArrayList(); + ListIterator instIt = instList.listIterator(); + while(instIt.hasNext()) { + newInstList.add((UAVDataObject) instIt.next()); } - }*/ + dObjects.add(newInstList); + } // Done + return dObjects; } /** * Same as getObjects() but will only return MetaObjects. */ - public List > getMetaObjects() + public synchronized List > getMetaObjects() { - assert(false); // TODO - return new ArrayList< List >(); - /* - QMutexLocker locker(mutex); - QList< QList > mObjects; + List< List > mObjects = new ArrayList< List > (); // Go through objects and copy to new list when types match - for (int objidx = 0; objidx < objects.length(); ++objidx) - { - if (objects[objidx].length() > 0) - { - // Check type - UAVMetaObject* obj = dynamic_cast(objects[objidx][0]); - if (obj != NULL) - { - // Create instance list - QList list; - // Go through instances and cast them to UAVMetaObject, then add to list - for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) - { - obj = dynamic_cast(objects[objidx][instidx]); - if (obj != NULL) - { - list.append(obj); - } - } - // Append to object list - mObjects.append(list); - } + ListIterator> objIt = objects.listIterator(0); + + // Check if this object type is already in the list + while(objIt.hasNext()) { + List instList = objIt.next(); + + // If no instances skip + if(instList.size() == 0) + continue; + + // If meta data skip + if(!instList.get(0).isMetadata()) + continue; + + List newInstList = new ArrayList(); + ListIterator instIt = instList.listIterator(); + while(instIt.hasNext()) { + newInstList.add((UAVMetaObject) instIt.next()); } + mObjects.add(newInstList); } // Done return mObjects; - */ } @@ -270,7 +277,6 @@ public class UAVObjectManager { */ public synchronized UAVObject getObject(String name, int objId, int instId) { - //QMutexLocker locker(mutex); // Check if this object type is already in the list ListIterator> objIter = objects.listIterator(); while(objIter.hasNext()) { From cb5e690de058f077c997432446d299a0d012cd4b Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 Mar 2011 02:05:36 -0600 Subject: [PATCH 024/284] Most of the work on Telemetry.java as well as lots of signals for various object events --- .../src/org/openpilot/uavtalk/Telemetry.java | 623 +++++++++++++++++- .../openpilot/uavtalk/TelemetryMonitor.java | 2 +- .../src/org/openpilot/uavtalk/UAVObject.java | 51 +- .../openpilot/uavtalk/UAVObjectManager.java | 3 +- .../src/org/openpilot/uavtalk/UAVTalk.java | 7 +- 5 files changed, 673 insertions(+), 13 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 88bc33de5..79e821fe3 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -1,8 +1,18 @@ package org.openpilot.uavtalk; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Observable; +import java.util.Observer; +import java.util.Queue; +import java.util.Timer; +import java.util.TimerTask; + +import org.openpilot.uavtalk.UAVObject.Acked; + public class Telemetry { - private TelemetryStats stats; public class TelemetryStats { public int txBytes; public int rxBytes; @@ -15,11 +25,612 @@ public class Telemetry { public int txRetries; } ; - public TelemetryStats getStats() { - return stats; - } + class ObjectTimeInfo { + UAVObject obj; + int updatePeriodMs; /** Update period in ms or 0 if no periodic updates are needed */ + int timeToNextUpdateMs; /** Time delay to the next update */ + }; + + class ObjectQueueInfo { + UAVObject obj; + int event; + boolean allInstances; + }; + + class ObjectTransactionInfo { + UAVObject obj; + boolean allInstances; + boolean objRequest; + int retriesRemaining; + Acked acked; + } ; - public void resetStats() { - stats = new TelemetryStats(); + /** + * Events generated by objects. Not enum because used in mask. + */ + private static final int EV_UNPACKED = 0x01; /** Object data updated by unpacking */ + private static final int EV_UPDATED = 0x02; /** Object data updated by changing the data structure */ + private static final int EV_UPDATED_MANUAL = 0x04; /** Object update event manually generated */ + private static final int EV_UPDATE_REQ = 0x08; /** Request to update object data */ + + /** + * Constructor + */ + public Telemetry(UAVTalk utalk, UAVObjectManager objMngr) + { + this.utalk = utalk; + this.objMngr = objMngr; + + // Process all objects in the list + List< List > objs = objMngr.getObjects(); + ListIterator> li = objs.listIterator(); + while(li.hasNext()) + registerObject(li.next().get(0)); // we only need to register one instance per object type + + // Listen to new object creations + objMngr.addNewInstanceObserver(new Observer() { + public void update(Observable observable, Object data) { + newInstance((UAVObject) data); + } + }); + objMngr.addNewObjectObserver(new Observer() { + public void update(Observable observable, Object data) { + newObject((UAVObject) data); + } + }); + + // Listen to transaction completions + utalk.addObserver(new Observer() { + public void update(Observable observable, Object data) { + transactionCompleted((UAVObject) data); + } + }); + + // Get GCS stats object + gcsStatsObj = objMngr.getObject("GCSTelemetryStats"); + + // Setup transaction timer + transPending = false; + transTimer = new Timer(); + transTimerTask = new TimerTask() { + @Override + public void run() { + transactionTimeout(); + } + }; + // Setup and start the periodic timer + timeToNextUpdateMs = 0; + + updateTimer = new Timer(); + updateTimerTask = new TimerTask() { + @Override + public void run() { + processPeriodicUpdates(); + } + }; + updateTimer.scheduleAtFixedRate(updateTimerTask, 1000, 1000); + // Setup and start the stats timer + txErrors = 0; + txRetries = 0; } + + /** + * Register a new object for periodic updates (if enabled) + */ + private void registerObject(UAVObject obj) + { + // Setup object for periodic updates + addObject(obj); + + // Setup object for telemetry updates + updateObject(obj); + } + + /** + * Add an object in the list used for periodic updates + */ + private void addObject(UAVObject obj) + { + // Check if object type is already in the list + ListIterator li = objList.listIterator(); + while(li.hasNext()) { + ObjectTimeInfo n = li.next(); + if( n.obj.getObjID() == obj.getObjID() ) + { + // Object type (not instance!) is already in the list, do nothing + return; + } + } + + // If this point is reached, then the object type is new, let's add it + ObjectTimeInfo timeInfo = new ObjectTimeInfo(); + timeInfo.obj = obj; + timeInfo.timeToNextUpdateMs = 0; + timeInfo.updatePeriodMs = 0; + objList.add(timeInfo); + } + + /** + * Update the object's timers + */ + private void setUpdatePeriod(UAVObject obj, int periodMs) + { + // Find object type (not instance!) and update its period + ListIterator li = objList.listIterator(); + while(li.hasNext()) { + ObjectTimeInfo n = li.next(); + if ( n.obj.getObjID() == obj.getObjID() ) + { + n.updatePeriodMs = periodMs; + n.timeToNextUpdateMs = (int) (periodMs * (new java.util.Random()).nextDouble()); // avoid bunching of updates + } + } + } + + /** + * Connect to all instances of an object depending on the event mask specified + */ + private void connectToObjectInstances(UAVObject obj, int eventMask) + { + List objs = objMngr.getObjectInstances(obj.getObjID()); + ListIterator li = objs.listIterator(); + while(li.hasNext()) + { + obj = li.next(); + //TODO: Disconnect all + // obj.disconnect(this); + + // Connect only the selected events + if ( (eventMask&EV_UNPACKED) != 0) + { + obj.addUnpackedObserver(new Observer() { + public void update(Observable observable, Object data) { + objectUnpacked( (UAVObject) data); + } + }); + } + if ( (eventMask&EV_UPDATED) != 0) + { + obj.addUpdatedAutoObserver(new Observer() { + public void update(Observable observable, Object data) { + objectUpdatedAuto( (UAVObject) data); + } + }); + } + if ( (eventMask&EV_UPDATED_MANUAL) != 0) + { + obj.addUpdatedManualObserver(new Observer() { + public void update(Observable observable, Object data) { + objectUpdatedManual( (UAVObject) data); + } + }); + } + if ( (eventMask&EV_UPDATE_REQ) != 0) + { + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + updateRequested( (UAVObject) data); + } + }); + } + } + } + + /** + * Update an object based on its metadata properties + */ + private void updateObject(UAVObject obj) + { + // Get metadata + UAVObject.Metadata metadata = obj.getMetadata(); + + // Setup object depending on update mode + int eventMask; + if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_PERIODIC ) + { + // Set update period + setUpdatePeriod(obj, metadata.gcsTelemetryUpdatePeriod); + // Connect signals for all instances + eventMask = EV_UPDATED_MANUAL | EV_UPDATE_REQ; + if(obj.isMetadata()) + eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events) + + connectToObjectInstances(obj, eventMask); + } + else if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE ) + { + // Set update period + setUpdatePeriod(obj, 0); + // Connect signals for all instances + eventMask = EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ; + if(obj.isMetadata()) + eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events) + + connectToObjectInstances(obj, eventMask); + } + else if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_MANUAL ) + { + // Set update period + setUpdatePeriod(obj, 0); + // Connect signals for all instances + eventMask = EV_UPDATED_MANUAL | EV_UPDATE_REQ; + if(obj.isMetadata()) + eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events) + + connectToObjectInstances(obj, eventMask); + } + else if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_NEVER ) + { + // Set update period + setUpdatePeriod(obj, 0); + // Disconnect from object + connectToObjectInstances(obj, 0); + } + } + + /** + * Called when a transaction is successfully completed (uavtalk event) + */ + private void transactionCompleted(UAVObject obj) + { + // Check if there is a pending transaction and the objects match + if ( transPending && transInfo.obj.getObjID() == obj.getObjID() ) + { + // qDebug() << QString("Telemetry: transaction completed for %1").arg(obj->getName()); + // Complete transaction + transTimer.cancel(); + transPending = false; + // Send signal + obj.transactionCompleted(true); + // Process new object updates from queue + processObjectQueue(); + } else + { + // qDebug() << "Error: received a transaction completed when did not expect it."; + } + } + + /** + * Called when a transaction is not completed within the timeout period (timer event) + */ + private void transactionTimeout() + { +// qDebug() << "Telemetry: transaction timeout."; + transTimer.cancel(); + // Proceed only if there is a pending transaction + if ( transPending ) + { + // Check if more retries are pending + if (transInfo.retriesRemaining > 0) + { + --transInfo.retriesRemaining; + processObjectTransaction(); + ++txRetries; + } + else + { + // Terminate transaction + utalk.cancelTransaction(); + transPending = false; + // Send signal + transInfo.obj.transactionCompleted(false); + // Process new object updates from queue + processObjectQueue(); + ++txErrors; + } + } + } + + /** + * Start an object transaction with UAVTalk, all information is stored in transInfo + */ + private void processObjectTransaction() + { + if (transPending) + { + // qDebug() << tr("Process Object transaction for %1").arg(transInfo.obj->getName()); + // Initiate transaction + if (transInfo.objRequest) + { + utalk.sendObjectRequest(transInfo.obj, transInfo.allInstances); + } + else + { + utalk.sendObject(transInfo.obj, transInfo.acked == Acked.TRUE, transInfo.allInstances); + } + // Start timer if a response is expected + if ( transInfo.objRequest || transInfo.acked == Acked.TRUE ) + { + transTimer.scheduleAtFixedRate(transTimerTask, REQ_TIMEOUT_MS, REQ_TIMEOUT_MS); + } + else + { + transTimer.cancel(); + transPending = false; + } + } else + { + // qDebug() << "Error: inside of processObjectTransaction with no transPending"; + } + } + + /** + * Process the event received from an object + */ + private void processObjectUpdates(UAVObject obj, int event, boolean allInstances, boolean priority) + { + // Push event into queue +// qDebug() << "Push event into queue for obj " << QString("%1 event %2").arg(obj->getName()).arg(event); + ObjectQueueInfo objInfo = new ObjectQueueInfo(); + objInfo.obj = obj; + objInfo.event = event; + objInfo.allInstances = allInstances; + if (priority) + { + if ( objPriorityQueue.size() < MAX_QUEUE_SIZE ) + { + objPriorityQueue.add(objInfo); + } + else + { + ++txErrors; + obj.transactionCompleted(false); + //qxtLog->warning(tr("Telemetry: priority event queue is full, event lost (%1)").arg(obj->getName())); + } + } + else + { + if ( objQueue.size() < MAX_QUEUE_SIZE ) + { + objQueue.add(objInfo); + } + else + { + ++txErrors; + obj.transactionCompleted(false); + } + } + + // If there is no transaction in progress then process event + if (!transPending) + { + // qDebug() << "No transaction pending, process object queue..."; + processObjectQueue(); + } else + { + // qDebug() << "Transaction pending, DO NOT process object queue..."; + } + } + + /** + * Process events from the object queue + */ + private void processObjectQueue() + { + // qDebug() << "Process object queue " << tr("- Depth (%1 %2)").arg(objQueue.length()).arg(objPriorityQueue.length()); + + // Don nothing if a transaction is already in progress (should not happen) + if (transPending) + { +// qxtLog->error("Telemetry: Dequeue while a transaction pending!"); + return; + } + + // Get object information from queue (first the priority and then the regular queue) + ObjectQueueInfo objInfo; + if ( !objPriorityQueue.isEmpty() ) + { + objInfo = objPriorityQueue.remove(); + } + else if ( !objQueue.isEmpty() ) + { + objInfo = objQueue.remove(); + } + else + { + return; + } + + // Check if a connection has been established, only process GCSTelemetryStats updates + // (used to establish the connection) + if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") != 0 ) + { + objQueue.clear(); + if ( objInfo.obj.getObjID() != objMngr.getObject("GCSTelemetryStats").getObjID() ) + { + objInfo.obj.transactionCompleted(false); + return; + } + } + + // Setup transaction (skip if unpack event) + if ( objInfo.event != EV_UNPACKED ) + { + UAVObject.Metadata metadata = objInfo.obj.getMetadata(); + transInfo.obj = objInfo.obj; + transInfo.allInstances = objInfo.allInstances; + transInfo.retriesRemaining = MAX_RETRIES; + transInfo.acked = metadata.gcsTelemetryAcked; + if ( objInfo.event == EV_UPDATED || objInfo.event == EV_UPDATED_MANUAL ) + { + transInfo.objRequest = false; + } + else if ( objInfo.event == EV_UPDATE_REQ ) + { + transInfo.objRequest = true; + } + // Start transaction + transPending = true; + processObjectTransaction(); + } else + { +// qDebug() << QString("Process object queue: this is an unpack event for %1").arg(objInfo.obj->getName()); + } + + // If this is a metaobject then make necessary telemetry updates + if (objInfo.obj.isMetadata()) + { + UAVMetaObject metaobj = (UAVMetaObject) objInfo.obj; + updateObject( metaobj.getParentObject() ); + } + + // The fact we received an unpacked event does not mean that + // we do not have additional objects still in the queue, + // so we have to reschedule queue processing to make sure they are not + // stuck: + if ( objInfo.event == EV_UNPACKED ) + processObjectQueue(); + + } + + /** + * Check is any objects are pending for periodic updates + * TODO: Clean-up + */ + private synchronized void processPeriodicUpdates() + { + // Stop timer + updateTimer.cancel(); + + // Iterate through each object and update its timer, if zero then transmit object. + // Also calculate smallest delay to next update (will be used for setting timeToNextUpdateMs) + int minDelay = MAX_UPDATE_PERIOD_MS; + ObjectTimeInfo objinfo; + int elapsedMs = 0; + long startTime; + int offset; + ListIterator li = objList.listIterator(); + while(li.hasNext()) + { + objinfo = li.next(); + // If object is configured for periodic updates + if (objinfo.updatePeriodMs > 0) + { + objinfo.timeToNextUpdateMs -= timeToNextUpdateMs; + // Check if time for the next update + if (objinfo.timeToNextUpdateMs <= 0) + { + // Reset timer + offset = (-objinfo.timeToNextUpdateMs) % objinfo.updatePeriodMs; + objinfo.timeToNextUpdateMs = objinfo.updatePeriodMs - offset; + // Send object + startTime = System.currentTimeMillis(); + processObjectUpdates(objinfo.obj, EV_UPDATED_MANUAL, true, false); + elapsedMs = (int) (System.currentTimeMillis() - startTime); + // Update timeToNextUpdateMs with the elapsed delay of sending the object; + timeToNextUpdateMs += elapsedMs; + } + // Update minimum delay + if (objinfo.timeToNextUpdateMs < minDelay) + { + minDelay = objinfo.timeToNextUpdateMs; + } + } + } + + // Check if delay for the next update is too short + if (minDelay < MIN_UPDATE_PERIOD_MS) + { + minDelay = MIN_UPDATE_PERIOD_MS; + } + + // Done + timeToNextUpdateMs = minDelay; + + // Restart timer + //updateTimer->start(timeToNextUpdateMs); + updateTimer.scheduleAtFixedRate(updateTimerTask, timeToNextUpdateMs, timeToNextUpdateMs); + } + + public TelemetryStats getStats() + { + // Get UAVTalk stats + UAVTalk.ComStats utalkStats = utalk.getStats(); + + // Update stats + TelemetryStats stats = new TelemetryStats(); + stats.txBytes = utalkStats.txBytes; + stats.rxBytes = utalkStats.rxBytes; + stats.txObjectBytes = utalkStats.txObjectBytes; + stats.rxObjectBytes = utalkStats.rxObjectBytes; + stats.rxObjects = utalkStats.rxObjects; + stats.txObjects = utalkStats.txObjects; + stats.txErrors = utalkStats.txErrors + txErrors; + stats.rxErrors = utalkStats.rxErrors; + stats.txRetries = txRetries; + + // Done + return stats; + } + + public synchronized void resetStats() + { + utalk.resetStats(); + txErrors = 0; + txRetries = 0; + } + + private synchronized void objectUpdatedAuto(UAVObject obj) + { + processObjectUpdates(obj, EV_UPDATED, false, true); + } + + private synchronized void objectUpdatedManual(UAVObject obj) + { + processObjectUpdates(obj, EV_UPDATED_MANUAL, false, true); + } + + private synchronized void objectUnpacked(UAVObject obj) + { + processObjectUpdates(obj, EV_UNPACKED, false, true); + } + + private synchronized void updateRequested(UAVObject obj) + { + processObjectUpdates(obj, EV_UPDATE_REQ, false, true); + } + + private void newObject(UAVObject obj) + { + registerObject(obj); + } + + private synchronized void newInstance(UAVObject obj) + { + registerObject(obj); + } + + /** + * Private variables + */ + private TelemetryStats stats; + private UAVObjectManager objMngr; + private UAVTalk utalk; + private UAVObject gcsStatsObj; + private List objList; + private Queue objQueue = new LinkedList(); + private Queue objPriorityQueue = new LinkedList(); + private ObjectTransactionInfo transInfo; + private boolean transPending; + + private Timer updateTimer; + private TimerTask updateTimerTask; + private Timer transTimer; + private TimerTask transTimerTask; + + private int timeToNextUpdateMs; + private int txErrors; + private int txRetries; + + /** + * Private constants + */ + private static final int REQ_TIMEOUT_MS = 250; + private static final int MAX_RETRIES = 2; + private static final int MAX_UPDATE_PERIOD_MS = 1000; + private static final int MIN_UPDATE_PERIOD_MS = 1; + private static final int MAX_QUEUE_SIZE = 20; + + + } diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index 40fc220cc..39d332457 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -123,7 +123,7 @@ public class TelemetryMonitor { // Connect to object //connect(obj, SIGNAL(transactionCompleted(UAVObject*,bool)), this, SLOT(transactionCompleted(UAVObject*,bool))); // Request update - obj.requestUpdate(); + tel.requestUpdate(obj); objPending = obj; } diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index adfece03e..9e4f69a39 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -8,7 +8,7 @@ import java.util.Observer; import java.util.Observable; public abstract class UAVObject { - + public class CallbackListener extends Observable { private UAVObject parent; @@ -20,6 +20,31 @@ public abstract class UAVObject { setChanged(); notifyObservers(parent); } + public void event (Object data) { + setChanged(); + notifyObservers(data); + } + } + + public class TransactionResult { + public UAVObject obj; + public boolean success; + public TransactionResult(UAVObject obj, boolean success) { + this.obj = obj; + this.success = success; + } + } + + private CallbackListener transactionCompletedListeners = new CallbackListener(this); + public void addTransactionCompleted(Observer o) { + synchronized(transactionCompletedListeners) { + transactionCompletedListeners.addObserver(o); + } + } + void transactionCompleted(boolean status) { + synchronized(transactionCompletedListeners) { + transactionCompletedListeners.event(new TransactionResult(this,status)); + } } private CallbackListener updatedListeners = new CallbackListener(this); @@ -47,6 +72,30 @@ public abstract class UAVObject { } } + private CallbackListener updatedAutoListeners = new CallbackListener(this); + public void addUpdatedAutoObserver(Observer o) { + synchronized(updatedAutoListeners) { + updatedAutoListeners.addObserver(o); + } + } + void updatedAuto() { + synchronized(updatedAutoListeners) { + updatedAutoListeners.event(); + } + } + + private CallbackListener updatedManualListeners = new CallbackListener(this); + public void addUpdatedManualObserver(Observer o) { + synchronized(updatedManualListeners) { + updatedManualListeners.addObserver(o); + } + } + void updatedManual() { + synchronized(updatedManualListeners) { + updatedManualListeners.event(); + } + } + public abstract boolean isMetadata(); /** diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java index 63f535eac..3ec588879 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java @@ -102,7 +102,6 @@ public class UAVObjectManager { newInstance.event(newObj); } obj.initialize(mobj); - //emit new instance signal instList.add(obj); newInstance.event(obj); @@ -155,7 +154,7 @@ public class UAVObjectManager { List ls = new ArrayList(); ls.add(obj); objects.add(ls); - //emit newObject(obj); + newObject.event(obj); } /** diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 7ea9c7c60..847b7c425 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -7,8 +7,9 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.Observable; -public class UAVTalk { +public class UAVTalk extends Observable{ private Thread inputProcessingThread = null; /** @@ -632,8 +633,8 @@ public class UAVTalk { if (respObj != null && respObj.getObjID() == obj.getObjID() && (respObj.getInstID() == obj.getInstID() || respAllInstances)) { respObj = null; - // TODO: Signals -// emit transactionCompleted(obj); + setChanged(); + notifyObservers(obj); } } From 55e08340514c85bb93929b8d8ffcb72113609afc Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 Mar 2011 02:39:33 -0600 Subject: [PATCH 025/284] Changes to TelemetryMonitor, ready for testing --- .../src/org/openpilot/uavtalk/Telemetry.java | 2 +- .../openpilot/uavtalk/TelemetryMonitor.java | 54 +++++++++++-------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 79e821fe3..4bed72fea 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -585,7 +585,7 @@ public class Telemetry { processObjectUpdates(obj, EV_UNPACKED, false, true); } - private synchronized void updateRequested(UAVObject obj) + public synchronized void updateRequested(UAVObject obj) { processObjectUpdates(obj, EV_UPDATE_REQ, false, true); } diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index 39d332457..dabbf1d4b 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -28,6 +28,7 @@ public class TelemetryMonitor { private UAVObject flightStatsObj; private Timer periodicTask; private int currentPeriod; + private long lastUpdateTime; private List queue; public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel) @@ -121,9 +122,15 @@ public class TelemetryMonitor { Log.d(TAG, "Retrieving object: " + obj.getName()) ; // Connect to object - //connect(obj, SIGNAL(transactionCompleted(UAVObject*,bool)), this, SLOT(transactionCompleted(UAVObject*,bool))); + obj.addTransactionCompleted(new Observer() { + public void update(Observable observable, Object data) { + UAVObject.TransactionResult result = (UAVObject.TransactionResult) data; + transactionCompleted(result.obj, result.success); + } + }); + // Request update - tel.requestUpdate(obj); + tel.updateRequested(obj); objPending = obj; } @@ -184,9 +191,10 @@ public class TelemetryMonitor { boolean connectionTimeout; if ( telStats.rxObjects > 0 ) { - //connectionTimer.start(); + lastUpdateTime = System.currentTimeMillis(); + } - if ( connectionTimer.elapsed() > CONNECTION_TIMEOUT_MS ) + if ( (System.currentTimeMillis() - lastUpdateTime) > CONNECTION_TIMEOUT_MS ) { connectionTimeout = true; } @@ -196,53 +204,53 @@ public class TelemetryMonitor { } // Update connection state - int oldStatus = gcsStats.Status; - if ( gcsStats.Status == GCSTelemetryStats::STATUS_DISCONNECTED ) + UAVObjectField statusField = gcsStatsObj.getField("Connection"); + String oldStatus = (String) statusField.getValue(); + if ( oldStatus.compareTo("Disconnected") == 0 ) { // Request connection - gcsStats.Status = GCSTelemetryStats::STATUS_HANDSHAKEREQ; + statusField.setValue("HandshakeReq"); } - else if ( gcsStats.Status == GCSTelemetryStats::STATUS_HANDSHAKEREQ ) + else if ( oldStatus.compareTo("HandshakeReq") == 0 ) { // Check for connection acknowledge - if ( flightStats.Status == FlightTelemetryStats::STATUS_HANDSHAKEACK ) + if ( ((String) flightStatsObj.getField("Status").getValue()).compareTo("HandshakeAck") == 0 ) { - gcsStats.Status = GCSTelemetryStats::STATUS_CONNECTED; + statusField.setValue("Connected"); } } - else if ( gcsStats.Status == GCSTelemetryStats::STATUS_CONNECTED ) + else if ( oldStatus.compareTo("Connected") == 0 ) { // Check if the connection is still active and the the autopilot is still connected - if (flightStats.Status == FlightTelemetryStats::STATUS_DISCONNECTED || connectionTimeout) + if ( ((String) flightStatsObj.getField("Status").getValue()).compareTo("Disconnected") == 0 || connectionTimeout) { - gcsStats.Status = GCSTelemetryStats::STATUS_DISCONNECTED; + statusField.setValue("Disconnected"); } } - // Set data - gcsStatsObj->setData(gcsStats); - // Force telemetry update if not yet connected - if ( gcsStats.Status != GCSTelemetryStats::STATUS_CONNECTED || - flightStats.Status != FlightTelemetryStats::STATUS_CONNECTED ) + boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue()); + boolean gcsConnected = ((String) statusField.getValue()).compareTo("Connected") == 0; + boolean gcsDisconnected = ((String) statusField.getValue()).compareTo("Disconnected") == 0; + if ( gcsStatusChanged || + ((String) flightStatsObj.getField("Status").getValue()).compareTo("Disconnected") != 0 ) { - gcsStatsObj->updated(); + gcsStatsObj.updated(); } // Act on new connections or disconnections - if (gcsStats.Status == GCSTelemetryStats::STATUS_CONNECTED && gcsStats.Status != oldStatus) + if (gcsConnected && gcsStatusChanged) { setPeriod(STATS_UPDATE_PERIOD_MS); - statsTimer->setInterval(STATS_UPDATE_PERIOD_MS); Log.d(TAG,"Connection with the autopilot established"); startRetrievingObjects(); } - if (gcsStats.Status == GCSTelemetryStats::STATUS_DISCONNECTED && gcsStats.Status != oldStatus) + if (gcsDisconnected && gcsStatusChanged) { setPeriod(STATS_CONNECT_PERIOD_MS); Log.d(TAG,"Connection with the autopilot lost"); Log.d(TAG,"Trying to connect to the autopilot"); - emit disconnected(); + //emit disconnected(); } } From 7b20773100121e15afc07edfe85245e3846c94a8 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 Mar 2011 12:27:27 -0600 Subject: [PATCH 026/284] Fixed bug in object signals that stopped updates sending. Various tweaks. --- .../src/org/openpilot/uavtalk/Telemetry.java | 33 ++++++++++------- .../openpilot/uavtalk/TelemetryMonitor.java | 35 +++++++++++++++---- .../org/openpilot/uavtalk/UAVDataObject.java | 2 +- .../src/org/openpilot/uavtalk/UAVObject.java | 8 +++-- .../org/openpilot/uavtalk/UAVObjectField.java | 4 +-- .../src/org/openpilot/uavtalk/UAVTalk.java | 15 +++++--- 6 files changed, 68 insertions(+), 29 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 4bed72fea..d2f82459b 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -1,5 +1,6 @@ package org.openpilot.uavtalk; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; @@ -91,6 +92,15 @@ public class Telemetry { // Setup transaction timer transPending = false; + // Setup and start the periodic timer + timeToNextUpdateMs = 0; + updateTimerSetPeriod(1000); + // Setup and start the stats timer + txErrors = 0; + txRetries = 0; + } + + synchronized void transTimerSetPeriod(int periodMs) { transTimer = new Timer(); transTimerTask = new TimerTask() { @Override @@ -98,9 +108,10 @@ public class Telemetry { transactionTimeout(); } }; - // Setup and start the periodic timer - timeToNextUpdateMs = 0; - + transTimer.schedule(transTimerTask, periodMs, periodMs); + } + + synchronized void updateTimerSetPeriod(int periodMs) { updateTimer = new Timer(); updateTimerTask = new TimerTask() { @Override @@ -108,10 +119,8 @@ public class Telemetry { processPeriodicUpdates(); } }; - updateTimer.scheduleAtFixedRate(updateTimerTask, 1000, 1000); - // Setup and start the stats timer - txErrors = 0; - txRetries = 0; + updateTimer.schedule(updateTimerTask, periodMs, periodMs); + } /** @@ -341,7 +350,7 @@ public class Telemetry { // Start timer if a response is expected if ( transInfo.objRequest || transInfo.acked == Acked.TRUE ) { - transTimer.scheduleAtFixedRate(transTimerTask, REQ_TIMEOUT_MS, REQ_TIMEOUT_MS); + transTimerSetPeriod(REQ_TIMEOUT_MS); } else { @@ -433,6 +442,7 @@ public class Telemetry { // Check if a connection has been established, only process GCSTelemetryStats updates // (used to establish the connection) + gcsStatsObj = objMngr.getObject("GCSTelemetryStats"); if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") != 0 ) { objQueue.clear(); @@ -538,8 +548,7 @@ public class Telemetry { timeToNextUpdateMs = minDelay; // Restart timer - //updateTimer->start(timeToNextUpdateMs); - updateTimer.scheduleAtFixedRate(updateTimerTask, timeToNextUpdateMs, timeToNextUpdateMs); + updateTimerSetPeriod(timeToNextUpdateMs); } public TelemetryStats getStats() @@ -607,10 +616,10 @@ public class Telemetry { private UAVObjectManager objMngr; private UAVTalk utalk; private UAVObject gcsStatsObj; - private List objList; + private List objList = new ArrayList(); private Queue objQueue = new LinkedList(); private Queue objPriorityQueue = new LinkedList(); - private ObjectTransactionInfo transInfo; + private ObjectTransactionInfo transInfo = new ObjectTransactionInfo(); private boolean transPending; private Timer updateTimer; diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index dabbf1d4b..bc0bfd6eb 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -92,7 +92,7 @@ public class TelemetryMonitor { } } // Start retrieving - Log.d(TAG,"Starting to retrieve meta and settings objects from the autopilot (%1 objects)" + queue.size()) ; + System.out.println(TAG + "Starting to retrieve meta and settings objects from the autopilot (" + queue.size() + " objects)"); retrieveNextObject(); } @@ -120,7 +120,7 @@ public class TelemetryMonitor { // Get next object from the queue UAVObject obj = queue.remove(0); - Log.d(TAG, "Retrieving object: " + obj.getName()) ; +// Log.d(TAG, "Retrieving object: " + obj.getName()) ; // Connect to object obj.addTransactionCompleted(new Observer() { public void update(Observable observable, Object data) { @@ -161,6 +161,10 @@ public class TelemetryMonitor { public synchronized void flightStatsUpdated(UAVObject obj) { // Force update if not yet connected + gcsStatsObj = objMngr.getObject("GCSTelemetryStats"); + flightStatsObj = objMngr.getObject("FlightTelemetryStats"); + + System.out.println(flightStatsObj.toString()); if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") != 0 || ((String) flightStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 ) { @@ -204,8 +208,17 @@ public class TelemetryMonitor { } // Update connection state - UAVObjectField statusField = gcsStatsObj.getField("Connection"); + gcsStatsObj = objMngr.getObject("GCSTelemetryStats"); + flightStatsObj = objMngr.getObject("FlightTelemetryStats"); + if(gcsStatsObj == null) { + System.out.println("No GCS stats yet"); + return; + } + UAVObjectField statusField = gcsStatsObj.getField("Status"); String oldStatus = (String) statusField.getValue(); + + System.out.println("GCS: " + statusField.getValue() + " Flight: " + flightStatsObj.getField("Status").getValue()); + if ( oldStatus.compareTo("Disconnected") == 0 ) { // Request connection @@ -217,6 +230,7 @@ public class TelemetryMonitor { if ( ((String) flightStatsObj.getField("Status").getValue()).compareTo("HandshakeAck") == 0 ) { statusField.setValue("Connected"); + System.out.println("Connected" + statusField.toString()); } } else if ( oldStatus.compareTo("Connected") == 0 ) @@ -230,11 +244,18 @@ public class TelemetryMonitor { // Force telemetry update if not yet connected boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue()); + + if(gcsStatusChanged) + System.out.println("GCS Status changed"); boolean gcsConnected = ((String) statusField.getValue()).compareTo("Connected") == 0; boolean gcsDisconnected = ((String) statusField.getValue()).compareTo("Disconnected") == 0; + + if(gcsConnected) + System.out.println("Detected here"); if ( gcsStatusChanged || ((String) flightStatsObj.getField("Status").getValue()).compareTo("Disconnected") != 0 ) { + System.out.println("Sending gcs status\n\n\n"); gcsStatsObj.updated(); } @@ -242,14 +263,15 @@ public class TelemetryMonitor { if (gcsConnected && gcsStatusChanged) { setPeriod(STATS_UPDATE_PERIOD_MS); - Log.d(TAG,"Connection with the autopilot established"); + System.out.println(TAG + " Connection with the autopilot established"); + //Log.d(TAG,"Connection with the autopilot established"); startRetrievingObjects(); } if (gcsDisconnected && gcsStatusChanged) { setPeriod(STATS_CONNECT_PERIOD_MS); - Log.d(TAG,"Connection with the autopilot lost"); - Log.d(TAG,"Trying to connect to the autopilot"); + System.out.println(TAG + " Connection with the autopilot lost"); + //Log.d(TAG,"Trying to connect to the autopilot"); //emit disconnected(); } } @@ -260,6 +282,7 @@ public class TelemetryMonitor { periodicTask.cancel(); currentPeriod = ms; + periodicTask = new Timer(); periodicTask.scheduleAtFixedRate(new TimerTask() { @Override public void run() { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java index 5694cc9d8..0acc02226 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java @@ -24,7 +24,7 @@ public abstract class UAVDataObject extends UAVObject { super.initialize(instID); } - public boolean isMetadata() { return true; }; + public boolean isMetadata() { return false; }; /** * Assign a metaobject */ diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 9e4f69a39..fac67cabc 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -53,11 +53,14 @@ public abstract class UAVObject { updatedListeners.addObserver(o); } } - void updated() { + void updated(boolean manually) { synchronized(updatedListeners) { updatedListeners.event(); } + if(manually) + updatedManual(); } + void updated() { updated(true); }; private CallbackListener unpackedListeners = new CallbackListener(this); public void addUnpackedObserver(Observer o) { @@ -67,7 +70,6 @@ public abstract class UAVObject { } void unpacked() { synchronized(unpackedListeners) { - System.out.println("Unpacked!: " + unpackedListeners.countObservers() + " " + getName()); unpackedListeners.event(); } } @@ -387,7 +389,7 @@ public abstract class UAVObject { // Trigger all the listeners for the unpack event unpacked(); - updated(); + updated(false); return numBytes; } diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 2fd7f7846..8d792bb39 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -131,7 +131,7 @@ public class UAVObjectField { case UINT32: // TODO: Deal properly with unsigned for (int index = 0; index < numElements; ++index) { - Integer val = (Integer) getValue(index); + Integer val = (int) ( ((Long) getValue(index)).longValue() & 0xffffffffL); dataOut.putInt(val); } break; @@ -364,7 +364,7 @@ public class UAVObjectField { public double getDouble() { return getDouble(0); }; public double getDouble(int index) { - return Double.valueOf((Double) getValue(index)); + return ((Number) getValue(index)).doubleValue(); } public void setDouble(double value) { setDouble(value, 0); }; diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 847b7c425..8576be78c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -200,9 +200,9 @@ public class UAVTalk extends Observable{ * \param[in] allInstances If set true then all instances will be updated * \return Success (true), Failure (false) */ - public boolean sendObject(UAVObject obj, boolean acked, boolean allInstances) + public synchronized boolean sendObject(UAVObject obj, boolean acked, boolean allInstances) { - //QMutexLocker locker(mutex); + System.out.println("Sending obj: " + obj.toString()); if (acked) { return objectTransaction(obj, TYPE_OBJ_ACK, allInstances); @@ -216,9 +216,8 @@ public class UAVTalk extends Observable{ /** * Cancel a pending transaction */ - public void cancelTransaction() + public synchronized void cancelTransaction() { - //QMutexLocker locker(mutex); respObj = null; } @@ -250,6 +249,7 @@ public class UAVTalk extends Observable{ } else if (type == TYPE_OBJ) { + System.out.println("Transmitting object: " + obj.toString()); return transmitObject(obj, TYPE_OBJ, allInstances); } else @@ -763,7 +763,12 @@ public class UAVTalk extends Observable{ bbuf.put((byte) (updateCRC(0, bbuf.array()) & 0xff)); try { - outStream.write(bbuf.array()); + int packlen = bbuf.position(); + bbuf.position(0); + byte [] dst = new byte[packlen]; + bbuf.get(dst,0,packlen); + System.out.println("Outputting: " + dst.length); + outStream.write(dst); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); From 621d31a52025d3a208862ac90c15222d0059cd65 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 Mar 2011 12:27:59 -0600 Subject: [PATCH 027/284] Unit test for telemetry --- .../uavtalk/TelemetryMonitorTest.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 androidgcs/tests/org/openpilot/uavtalk/TelemetryMonitorTest.java diff --git a/androidgcs/tests/org/openpilot/uavtalk/TelemetryMonitorTest.java b/androidgcs/tests/org/openpilot/uavtalk/TelemetryMonitorTest.java new file mode 100644 index 000000000..1fc02d145 --- /dev/null +++ b/androidgcs/tests/org/openpilot/uavtalk/TelemetryMonitorTest.java @@ -0,0 +1,64 @@ +package org.openpilot.uavtalk; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.Socket; +import java.nio.ByteBuffer; +import java.util.Observable; +import java.util.Observer; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; +import org.openpilot.uavtalk.UAVTalk; + + +public class TelemetryMonitorTest { + + static UAVObjectManager objMngr; + static UAVTalk talk; + static final String IP_ADDRDESS = new String("127.0.0.1"); + static final int PORT_NUM = 7777; + static Socket connection = null; + boolean succeed = false; + + @Test + public void testTelemetry() throws Exception { + objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + talk = null; + try{ + InetAddress ip = InetAddress.getByName(IP_ADDRDESS); + connection = new Socket(ip, PORT_NUM); + } catch (Exception e) { + e.printStackTrace(); + fail("Couldn't connect to test platform"); + } + + try { + talk = new UAVTalk(connection.getInputStream(), connection.getOutputStream(), objMngr); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail("Couldn't construct UAVTalk object"); + } + + Thread inputStream = talk.getInputProcessThread(); + inputStream.start(); + + Telemetry tel = new Telemetry(talk, objMngr); + TelemetryMonitor mon = new TelemetryMonitor(objMngr,tel); + + Thread.sleep(10000); + + System.out.println("Done"); + } + + +} From e12cef6b4bb99707366555d962ed24047eb7649c Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 Mar 2011 13:44:40 -0600 Subject: [PATCH 028/284] Little updates --- .../src/org/openpilot/uavtalk/UAVTalk.java | 16 +++--- .../tests/org/openpilot/uavtalk/TalkTest.java | 56 ++++++++++++++----- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 8576be78c..92b5585de 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -202,7 +202,6 @@ public class UAVTalk extends Observable{ */ public synchronized boolean sendObject(UAVObject obj, boolean acked, boolean allInstances) { - System.out.println("Sending obj: " + obj.toString()); if (acked) { return objectTransaction(obj, TYPE_OBJ_ACK, allInstances); @@ -249,7 +248,6 @@ public class UAVTalk extends Observable{ } else if (type == TYPE_OBJ) { - System.out.println("Transmitting object: " + obj.toString()); return transmitObject(obj, TYPE_OBJ, allInstances); } else @@ -263,7 +261,7 @@ public class UAVTalk extends Observable{ * \param[in] rxbyte Received byte * \return Success (true), Failure (false) */ - public boolean processInputByte(int rxbyte) + public synchronized boolean processInputByte(int rxbyte) { assert(objMngr != null); @@ -448,12 +446,10 @@ public class UAVTalk extends Observable{ break; } - //mutex->lock(); rxBuffer.position(0); receiveObject(rxType, rxObjId, rxInstId, rxBuffer); stats.rxObjectBytes += rxLength; stats.rxObjects++; - //mutex->unlock(); rxState = RxStateType.STATE_SYNC; break; @@ -484,13 +480,13 @@ public class UAVTalk extends Observable{ boolean error = false; boolean allInstances = (instId == ALL_INSTANCES? true : false); - System.out.println("Received object: " + objId + " " + objMngr.getObject(objId).getName()); // Process message type switch (type) { case TYPE_OBJ: // All instances, not allowed for OBJ messages if (!allInstances) { + System.out.println("Received object: " + objId + " " + objMngr.getObject(objId).getName()); // Get object and update its data obj = updateObject(objId, instId, data); // Check if an ack is pending @@ -512,6 +508,7 @@ public class UAVTalk extends Observable{ // All instances, not allowed for OBJ_ACK messages if (!allInstances) { + System.out.println("Received object ack: " + objId + " " + objMngr.getObject(objId).getName()); // Get object and update its data obj = updateObject(objId, instId, data); // Transmit ACK @@ -531,6 +528,7 @@ public class UAVTalk extends Observable{ break; case TYPE_OBJ_REQ: // Get object, if all instances are requested get instance 0 of the object + System.out.println("Received object request: " + objId + " " + objMngr.getObject(objId).getName()); if (allInstances) { obj = objMngr.getObject(objId); @@ -553,6 +551,7 @@ public class UAVTalk extends Observable{ // All instances, not allowed for ACK messages if (!allInstances) { + System.out.println("Received ack: " + objId + " " + objMngr.getObject(objId).getName()); // Get object obj = objMngr.getObject(objId, instId); // Check if an ack is pending @@ -578,7 +577,7 @@ public class UAVTalk extends Observable{ * If the object instance could not be found in the list, then a * new one is created. */ - public UAVObject updateObject(int objId, int instId, ByteBuffer data) + public synchronized UAVObject updateObject(int objId, int instId, ByteBuffer data) { assert(objMngr != null); @@ -613,13 +612,14 @@ public class UAVTalk extends Observable{ // TODO Auto-generated catch block e.printStackTrace(); } + System.out.println("Unpacking new object"); instobj.unpack(data); return instobj; } else { // Unpack data into object instance - // System.out.println("Unpacking: " + data.position() + " / " + data.capacity() ); + System.out.println("Unpacking existing object: " + data.position() + " / " + data.capacity() ); obj.unpack(data); return obj; } diff --git a/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java b/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java index 252927122..044ddfd06 100644 --- a/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java +++ b/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java @@ -1,10 +1,13 @@ package org.openpilot.uavtalk; import static org.junit.Assert.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; @@ -31,7 +34,7 @@ public class TalkTest { UAVObjectsInitialize.register(objMngr); } - @Test + //@Test public void testGetFlightStatus() { Socket connection = null; UAVTalk talk = null; @@ -78,22 +81,49 @@ public class TalkTest { @Test public void testSendObjectRequest() { - fail("Not yet implemented"); + ByteArrayInputStream is = new ByteArrayInputStream(new byte[0], 0, 0); + ByteArrayOutputStream os = new ByteArrayOutputStream(100); + + UAVTalk talk = new UAVTalk(is,os,objMngr); + UAVObject obj = objMngr.getObject("FlightTelemetryStats"); + obj.getField("Status").setValue("Connected"); + + talk.sendObject(obj, false, false); + + System.out.println("Size: " + os.size()); + byte [] array = os.toByteArray(); + for(int i = 0; i < array.length; i++) { + System.out.print("0x" + Integer.toHexString((int) array[i] & 0xff)); + if(i != array.length-1) + System.out.print(", "); + } + System.out.print("\n"); } - - @Test - public void testSendObject() { - fail("Not yet implemented"); - } - + @Test public void testReceiveObject() { - fail("Not yet implemented"); + ByteArrayInputStream is = new ByteArrayInputStream(new byte[0], 0, 0); + ByteArrayOutputStream os = new ByteArrayOutputStream(100); + + // Send object to create the test packet (should hard code in test string) + UAVTalk talk = new UAVTalk(is,os,objMngr); + UAVObject obj = objMngr.getObject("FlightTelemetryStats"); + obj.getField("Status").setValue("Connected"); + talk.sendObject(obj, false, false); + + obj.getField("Status").setValue("Disconnected"); + + // Test receiving from that stream + is = new ByteArrayInputStream(os.toByteArray(), 0, os.size()); + talk = new UAVTalk(is,os,objMngr); + Thread inputStream = talk.getInputProcessThread(); + inputStream.start(); + + System.out.println("Should be FlightTelemetry Stats:"); + System.out.println(objMngr.getObject("FlightTelemetryStats").toString()); + + fail("Not working yet"); } - @Test - public void testUpdateObject() { - fail("Not yet implemented"); - } } From 03b9bbbb8ace148c45581b71731a0684d4e166a8 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 Mar 2011 14:36:37 -0600 Subject: [PATCH 029/284] Fix the CRC calculation for java sending --- .../src/org/openpilot/uavtalk/UAVTalk.java | 13 ++++--- .../tests/org/openpilot/uavtalk/TalkTest.java | 34 ++++++++++++------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 92b5585de..d656aa707 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -175,7 +175,12 @@ public class UAVTalk extends Observable{ e.printStackTrace(); break; } - //System.out.println("Received byte " + val + " in state + " + rxState); + if(val == -1) { + System.out.println("End of stream, terminating processInputStream thread"); + break; + } + + System.out.println("Received byte " + val + " in state + " + rxState); processInputByte(val); } } @@ -760,7 +765,7 @@ public class UAVTalk extends Observable{ } // Calculate checksum - bbuf.put((byte) (updateCRC(0, bbuf.array()) & 0xff)); + bbuf.put((byte) (updateCRC(0, bbuf.array(), bbuf.position()) & 0xff)); try { int packlen = bbuf.position(); @@ -818,9 +823,9 @@ public class UAVTalk extends Observable{ { return crc_table[crc ^ (data & 0xff)]; } - int updateCRC(int crc, byte [] data) + int updateCRC(int crc, byte [] data, int length) { - for (int i = 0; i < data.length; i++) + for (int i = 0; i < length; i++) crc = updateCRC(crc, (int) data[i]); return crc; } diff --git a/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java b/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java index 044ddfd06..91f3aa198 100644 --- a/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java +++ b/androidgcs/tests/org/openpilot/uavtalk/TalkTest.java @@ -28,6 +28,16 @@ public class TalkTest { static final int PORT_NUM = 7777; boolean succeed = false; + byte[] flightStatsConnected = + {0x3c,0x20,0x1d,0x00, + (byte) 0x5e,(byte) 0x26,(byte) 0x0c,(byte) 0x66, + 0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,(byte) 0xAE}; + @BeforeClass public static void setUpBeforeClass() throws Exception { objMngr = new UAVObjectManager(); @@ -89,40 +99,40 @@ public class TalkTest { obj.getField("Status").setValue("Connected"); talk.sendObject(obj, false, false); - + System.out.println("Size: " + os.size()); byte [] array = os.toByteArray(); for(int i = 0; i < array.length; i++) { System.out.print("0x" + Integer.toHexString((int) array[i] & 0xff)); + System.out.print("/0x" + Integer.toHexString((int) flightStatsConnected[i] & 0xff)); if(i != array.length-1) - System.out.print(", "); + System.out.print("\n"); } System.out.print("\n"); + for(int i = 0; i < array.length; i++) + assertEquals(os.toByteArray()[i], flightStatsConnected[i]); } @Test - public void testReceiveObject() { - ByteArrayInputStream is = new ByteArrayInputStream(new byte[0], 0, 0); + public void testReceiveObject() throws InterruptedException { + ByteArrayInputStream is = new ByteArrayInputStream(flightStatsConnected, 0, flightStatsConnected.length); ByteArrayOutputStream os = new ByteArrayOutputStream(100); - // Send object to create the test packet (should hard code in test string) - UAVTalk talk = new UAVTalk(is,os,objMngr); + // Make the Status wrong initially UAVObject obj = objMngr.getObject("FlightTelemetryStats"); - obj.getField("Status").setValue("Connected"); - talk.sendObject(obj, false, false); - obj.getField("Status").setValue("Disconnected"); // Test receiving from that stream - is = new ByteArrayInputStream(os.toByteArray(), 0, os.size()); - talk = new UAVTalk(is,os,objMngr); + UAVTalk talk = new UAVTalk(is,os,objMngr); Thread inputStream = talk.getInputProcessThread(); inputStream.start(); + Thread.sleep(1000); + System.out.println("Should be FlightTelemetry Stats:"); System.out.println(objMngr.getObject("FlightTelemetryStats").toString()); - fail("Not working yet"); + assertEquals(obj.getField("Status").getValue(), new String("Connected")); } From 06f583ff754a0813171e789451cb95f7f6bb497e Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 Mar 2011 21:36:09 -0600 Subject: [PATCH 030/284] Fixed some timer issues. Got connection with this. --- .../src/org/openpilot/uavtalk/Telemetry.java | 9 ++++++++- .../org/openpilot/uavtalk/TelemetryMonitor.java | 3 --- .../src/org/openpilot/uavtalk/UAVTalk.java | 16 +++++++--------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index d2f82459b..7f04e344b 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -101,7 +101,14 @@ public class Telemetry { } synchronized void transTimerSetPeriod(int periodMs) { - transTimer = new Timer(); + if(transTimerTask != null) + transTimerTask.cancel(); + + if(transTimer != null) + transTimer.purge(); + + transTimer = new Timer(); + transTimerTask = new TimerTask() { @Override public void run() { diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index bc0bfd6eb..eb406923d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -164,7 +164,6 @@ public class TelemetryMonitor { gcsStatsObj = objMngr.getObject("GCSTelemetryStats"); flightStatsObj = objMngr.getObject("FlightTelemetryStats"); - System.out.println(flightStatsObj.toString()); if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") != 0 || ((String) flightStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 ) { @@ -250,8 +249,6 @@ public class TelemetryMonitor { boolean gcsConnected = ((String) statusField.getValue()).compareTo("Connected") == 0; boolean gcsDisconnected = ((String) statusField.getValue()).compareTo("Disconnected") == 0; - if(gcsConnected) - System.out.println("Detected here"); if ( gcsStatusChanged || ((String) flightStatsObj.getField("Status").getValue()).compareTo("Disconnected") != 0 ) { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index d656aa707..825f9d9fe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -180,7 +180,7 @@ public class UAVTalk extends Observable{ break; } - System.out.println("Received byte " + val + " in state + " + rxState); + //System.out.println("Received byte " + val + " in state + " + rxState); processInputByte(val); } } @@ -423,7 +423,6 @@ public class UAVTalk extends Observable{ // Update CRC rxCS = updateCRC(rxCS, rxbyte); - //System.out.println(rxCount + "/" + rxLength); rxBuffer.put(rxCount++, (byte) (rxbyte & 0xff)); if (rxCount < rxLength) break; @@ -491,7 +490,7 @@ public class UAVTalk extends Observable{ // All instances, not allowed for OBJ messages if (!allInstances) { - System.out.println("Received object: " + objId + " " + objMngr.getObject(objId).getName()); + System.out.println("Received object: " + objMngr.getObject(objId).getName()); // Get object and update its data obj = updateObject(objId, instId, data); // Check if an ack is pending @@ -513,7 +512,7 @@ public class UAVTalk extends Observable{ // All instances, not allowed for OBJ_ACK messages if (!allInstances) { - System.out.println("Received object ack: " + objId + " " + objMngr.getObject(objId).getName()); +// System.out.println("Received object ack: " + objId + " " + objMngr.getObject(objId).getName()); // Get object and update its data obj = updateObject(objId, instId, data); // Transmit ACK @@ -533,7 +532,7 @@ public class UAVTalk extends Observable{ break; case TYPE_OBJ_REQ: // Get object, if all instances are requested get instance 0 of the object - System.out.println("Received object request: " + objId + " " + objMngr.getObject(objId).getName()); +// System.out.println("Received object request: " + objId + " " + objMngr.getObject(objId).getName()); if (allInstances) { obj = objMngr.getObject(objId); @@ -556,7 +555,7 @@ public class UAVTalk extends Observable{ // All instances, not allowed for ACK messages if (!allInstances) { - System.out.println("Received ack: " + objId + " " + objMngr.getObject(objId).getName()); +// System.out.println("Received ack: " + objId + " " + objMngr.getObject(objId).getName()); // Get object obj = objMngr.getObject(objId, instId); // Check if an ack is pending @@ -617,14 +616,14 @@ public class UAVTalk extends Observable{ // TODO Auto-generated catch block e.printStackTrace(); } - System.out.println("Unpacking new object"); +// System.out.println("Unpacking new object"); instobj.unpack(data); return instobj; } else { // Unpack data into object instance - System.out.println("Unpacking existing object: " + data.position() + " / " + data.capacity() ); +// System.out.println("Unpacking existing object: " + data.position() + " / " + data.capacity() ); obj.unpack(data); return obj; } @@ -772,7 +771,6 @@ public class UAVTalk extends Observable{ bbuf.position(0); byte [] dst = new byte[packlen]; bbuf.get(dst,0,packlen); - System.out.println("Outputting: " + dst.length); outStream.write(dst); } catch (IOException e) { // TODO Auto-generated catch block From bd0a599e9687ecfa4d22e33c6a0b49b1b8e07dbe Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 13 Mar 2011 21:01:11 -0500 Subject: [PATCH 031/284] Works on Nook, but recursive loop too deep in registering objects --- androidgcs/AndroidManifest.xml | 12 +- androidgcs/default.properties | 2 +- androidgcs/res/layout/main.xml | 1 - androidgcs/res/values/strings.xml | 1 - .../openpilot/androidgcs/ObjectBrowser.java | 129 ++++++++++++++++++ .../src/org/openpilot/uavtalk/Telemetry.java | 47 ++++--- .../openpilot/uavtalk/TelemetryMonitor.java | 15 +- .../src/org/openpilot/uavtalk/UAVObject.java | 12 +- 8 files changed, 186 insertions(+), 33 deletions(-) create mode 100644 androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index 7a96a6600..8b3a9e4b3 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -5,8 +5,18 @@ android:versionName="1.0"> - + + + + + + + + + + \ No newline at end of file diff --git a/androidgcs/default.properties b/androidgcs/default.properties index 46769a720..66db0d159 100644 --- a/androidgcs/default.properties +++ b/androidgcs/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-7 +target=android-10 diff --git a/androidgcs/res/layout/main.xml b/androidgcs/res/layout/main.xml index 3a5f117d3..7e4a852bf 100644 --- a/androidgcs/res/layout/main.xml +++ b/androidgcs/res/layout/main.xml @@ -7,6 +7,5 @@ diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index 0d9f93bc2..52fa56534 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -1,5 +1,4 @@ - Hello World! OpenPilot GCS diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java new file mode 100644 index 000000000..3c6231258 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -0,0 +1,129 @@ +package org.openpilot.androidgcs; + +import java.io.IOException; +import java.util.Set; +import java.util.UUID; + +import android.app.Activity; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +import org.openpilot.androidgcs.*; +import org.openpilot.uavtalk.Telemetry; +import org.openpilot.uavtalk.TelemetryMonitor; +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVTalk; +import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; + +public class ObjectBrowser extends Activity { + + private final String TAG = "ObjectBrower"; + private final String DEVICE_NAME = "RN42-222D"; + private final int REQUEST_ENABLE_BT = 0; + private UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); + BluetoothAdapter mBluetoothAdapter; + UAVObjectManager objMngr; + UAVTalk uavTalk; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + Log.d(TAG, "Launching Object Browser"); + + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (mBluetoothAdapter == null) { + // Device does not support Bluetooth + Log.d(TAG, "Device does not support Bluetooth"); + return; + } + + if (!mBluetoothAdapter.isEnabled()) { + Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); + } else { + queryDevices(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if(requestCode == REQUEST_ENABLE_BT && resultCode == RESULT_OK) { + Log.d(TAG, "Bluetooth started succesfully"); + queryDevices(); + } + if(requestCode == REQUEST_ENABLE_BT && resultCode != RESULT_OK) + Log.d(TAG, "Bluetooth could not be started"); + + } + + public void queryDevices() { + Log.d(TAG, "Searching for devices"); + Set pairedDevices = mBluetoothAdapter.getBondedDevices(); + // If there are paired devices + if (pairedDevices.size() > 0) { + // Loop through paired devices + for (BluetoothDevice device : pairedDevices) { + // Add the name and address to an array adapter to show in a ListView + //mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); + Log.d(TAG, "Paired device: " + device.getName()); + if(device.getName().compareTo(DEVICE_NAME) == 0) { + openTelmetryBluetooth(device); + openTelmetryBluetooth(device); + } + } + } + + } + + private void openTelmetryBluetooth(BluetoothDevice device) { + Log.d(TAG, "Opening conncetion to " + device.getName()); + BluetoothSocket socket = null; + try { + socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID); + } catch (IOException e) { + Log.e(TAG,"Unable to create Rfcomm socket"); + e.printStackTrace(); + } + + mBluetoothAdapter.cancelDiscovery(); + + try { + socket.connect(); + } + catch (IOException e) { + Log.e(TAG,"Unable to connect to requested device", e); + try { + socket.close(); + } catch (IOException e2) { + Log.e(TAG, "unable to close() socket during connection failure", e2); + } + return; + } + + objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + + try { + uavTalk = new UAVTalk(socket.getInputStream(), socket.getOutputStream(), objMngr); + } catch (IOException e) { + Log.e(TAG,"Error starting UAVTalk"); + // TODO Auto-generated catch block + e.printStackTrace(); + return; + } + + Thread inputStream = uavTalk.getInputProcessThread(); + inputStream.start(); + + Telemetry tel = new Telemetry(uavTalk, objMngr); + TelemetryMonitor mon = new TelemetryMonitor(objMngr,tel); + + } +} diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 7f04e344b..b403f85e3 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -12,8 +12,12 @@ import java.util.TimerTask; import org.openpilot.uavtalk.UAVObject.Acked; +import android.util.Log; + public class Telemetry { + private final String TAG = "Telemetry"; + public class TelemetryStats { public int txBytes; public int rxBytes; @@ -133,7 +137,7 @@ public class Telemetry { /** * Register a new object for periodic updates (if enabled) */ - private void registerObject(UAVObject obj) + private synchronized void registerObject(UAVObject obj) { // Setup object for periodic updates addObject(obj); @@ -145,7 +149,7 @@ public class Telemetry { /** * Add an object in the list used for periodic updates */ - private void addObject(UAVObject obj) + private synchronized void addObject(UAVObject obj) { // Check if object type is already in the list ListIterator li = objList.listIterator(); @@ -169,7 +173,7 @@ public class Telemetry { /** * Update the object's timers */ - private void setUpdatePeriod(UAVObject obj, int periodMs) + private synchronized void setUpdatePeriod(UAVObject obj, int periodMs) { // Find object type (not instance!) and update its period ListIterator li = objList.listIterator(); @@ -186,7 +190,7 @@ public class Telemetry { /** * Connect to all instances of an object depending on the event mask specified */ - private void connectToObjectInstances(UAVObject obj, int eventMask) + private synchronized void connectToObjectInstances(UAVObject obj, int eventMask) { List objs = objMngr.getObjectInstances(obj.getObjID()); ListIterator li = objs.listIterator(); @@ -235,7 +239,7 @@ public class Telemetry { /** * Update an object based on its metadata properties */ - private void updateObject(UAVObject obj) + private synchronized void updateObject(UAVObject obj) { // Get metadata UAVObject.Metadata metadata = obj.getMetadata(); @@ -287,12 +291,12 @@ public class Telemetry { /** * Called when a transaction is successfully completed (uavtalk event) */ - private void transactionCompleted(UAVObject obj) + private synchronized void transactionCompleted(UAVObject obj) { // Check if there is a pending transaction and the objects match if ( transPending && transInfo.obj.getObjID() == obj.getObjID() ) { - // qDebug() << QString("Telemetry: transaction completed for %1").arg(obj->getName()); + Log.d(TAG,"Telemetry: transaction completed for " + obj.getName()); // Complete transaction transTimer.cancel(); transPending = false; @@ -302,16 +306,16 @@ public class Telemetry { processObjectQueue(); } else { - // qDebug() << "Error: received a transaction completed when did not expect it."; + Log.e(TAG,"Error: received a transaction completed when did not expect it."); } } /** * Called when a transaction is not completed within the timeout period (timer event) */ - private void transactionTimeout() + private synchronized void transactionTimeout() { -// qDebug() << "Telemetry: transaction timeout."; + Log.d(TAG,"Telemetry: transaction timeout."); transTimer.cancel(); // Proceed only if there is a pending transaction if ( transPending ) @@ -340,11 +344,11 @@ public class Telemetry { /** * Start an object transaction with UAVTalk, all information is stored in transInfo */ - private void processObjectTransaction() + private synchronized void processObjectTransaction() { if (transPending) { - // qDebug() << tr("Process Object transaction for %1").arg(transInfo.obj->getName()); + Log.d(TAG, "Process Object transaction for " + transInfo.obj.getName()); // Initiate transaction if (transInfo.objRequest) { @@ -366,17 +370,17 @@ public class Telemetry { } } else { - // qDebug() << "Error: inside of processObjectTransaction with no transPending"; + Log.e(TAG,"Error: inside of processObjectTransaction with no transPending"); } } /** * Process the event received from an object */ - private void processObjectUpdates(UAVObject obj, int event, boolean allInstances, boolean priority) + private synchronized void processObjectUpdates(UAVObject obj, int event, boolean allInstances, boolean priority) { // Push event into queue -// qDebug() << "Push event into queue for obj " << QString("%1 event %2").arg(obj->getName()).arg(event); + Log.d(TAG, "Push event into queue for obj " + obj.getName() + " event " + event); ObjectQueueInfo objInfo = new ObjectQueueInfo(); objInfo.obj = obj; objInfo.event = event; @@ -391,7 +395,7 @@ public class Telemetry { { ++txErrors; obj.transactionCompleted(false); - //qxtLog->warning(tr("Telemetry: priority event queue is full, event lost (%1)").arg(obj->getName())); + Log.w(TAG,"Telemetry: priority event queue is full, event lost " + obj.getName()); } } else @@ -410,25 +414,26 @@ public class Telemetry { // If there is no transaction in progress then process event if (!transPending) { - // qDebug() << "No transaction pending, process object queue..."; + processObjectQueue(); + } else { - // qDebug() << "Transaction pending, DO NOT process object queue..."; + Log.d(TAG,"Transaction pending, DO NOT process object queue..."); } } /** * Process events from the object queue */ - private void processObjectQueue() + private synchronized void processObjectQueue() { - // qDebug() << "Process object queue " << tr("- Depth (%1 %2)").arg(objQueue.length()).arg(objPriorityQueue.length()); + Log.d(TAG, "Process object queue - Depth " + objQueue.size() + " priority " + objPriorityQueue.size()); // Don nothing if a transaction is already in progress (should not happen) if (transPending) { -// qxtLog->error("Telemetry: Dequeue while a transaction pending!"); + Log.e(TAG,"Dequeue while a transaction pending"); return; } diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index eb406923d..e2050fc25 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -55,7 +55,7 @@ public class TelemetryMonitor { /** * Initiate object retrieval, initialize queue with objects to be retrieved. */ - public void startRetrievingObjects() + public synchronized void startRetrievingObjects() { // Clear object queue queue.clear(); @@ -108,7 +108,7 @@ public class TelemetryMonitor { /** * Retrieve the next object in the queue */ - public void retrieveNextObject() + public synchronized void retrieveNextObject() { // If queue is empty return if ( queue.isEmpty() ) @@ -120,7 +120,12 @@ public class TelemetryMonitor { // Get next object from the queue UAVObject obj = queue.remove(0); -// Log.d(TAG, "Retrieving object: " + obj.getName()) ; + if(obj == null) { + Log.e(TAG, "Got null object forom transaction queue"); + return; + } + + Log.d(TAG, "Retrieving object: " + obj.getName()) ; // Connect to object obj.addTransactionCompleted(new Observer() { public void update(Observable observable, Object data) { @@ -137,10 +142,12 @@ public class TelemetryMonitor { /** * Called by the retrieved object when a transaction is completed. */ - public void transactionCompleted(UAVObject obj, boolean success) + public synchronized void transactionCompleted(UAVObject obj, boolean success) { //QMutexLocker locker(mutex); // Disconnect from sending object + Log.d(TAG,"transactionCompleted"); + // TODO: Need to be able to disconnect signals //obj->disconnect(this); objPending = null; diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index fac67cabc..b74df9218 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -17,12 +17,16 @@ public abstract class UAVObject { } public void event () { - setChanged(); - notifyObservers(parent); + synchronized(this) { + setChanged(); + notifyObservers(parent); + } } public void event (Object data) { - setChanged(); - notifyObservers(data); + synchronized(this) { + setChanged(); + notifyObservers(data); + } } } From 77910a93ab1df0687180fb69a6c24ec9747f2d5f Mon Sep 17 00:00:00 2001 From: James Cotton Date: Wed, 16 Mar 2011 15:18:45 -0500 Subject: [PATCH 032/284] Update display to show connected icon --- androidgcs/res/drawable-hdpi/icon.png | Bin 4147 -> 48558 bytes androidgcs/res/drawable-ldpi/icon.png | Bin 1723 -> 48558 bytes androidgcs/res/drawable-mdpi/icon.png | Bin 2574 -> 48558 bytes androidgcs/res/layout/main.xml | 2 + .../openpilot/androidgcs/ObjectBrowser.java | 92 +++++++++++++++--- 5 files changed, 83 insertions(+), 11 deletions(-) diff --git a/androidgcs/res/drawable-hdpi/icon.png b/androidgcs/res/drawable-hdpi/icon.png index 8074c4c571b8cd19e27f4ee5545df367420686d7..eab1fc68fd7ad531ac025a53956f78de8d4e5180 100644 GIT binary patch literal 48558 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 H&ZK_;Db+pY literal 4147 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 diff --git a/androidgcs/res/drawable-ldpi/icon.png b/androidgcs/res/drawable-ldpi/icon.png index 1095584ec21f71cd0afc9e0993aa2209671b590c..eab1fc68fd7ad531ac025a53956f78de8d4e5180 100644 GIT binary patch literal 48558 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 H&ZK_;Db+pY literal 1723 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 H&ZK_;Db+pY literal 2574 zcmV+p3i0)cP)Q`Og{P|8RRXpj5bgrSmEzSMfBn+{{vpNxw?;5UX;iv9sYxy_`IQHs$i<61a_iv^L>h8s-`D(`e@|IgS*Fj zNGM876Gf;3D8*1UX9a%v>yJKD*QkCwW2AirU(L{qNA)JghmGItc;(H<$!ABY&gBy1vJIEUj-b8%el*o|VkG)LqNx#TG>Jvj^jIte!!+RY z)T4j$7+PoF1AkRBf}R#^T=-q|PaK1$c<4UH)Hpq3$4WA|xtr!ZQLC=*vNE>O6E9kp+5X0eKB$6>C(lPwI@3#oY zhS_%x7e|j!$yG?ECXmh~EH~^OeuK}+sWoJse3Z3?ha3n`MM9KvA?uqpEnBg4Q46)7 zM$p%a$@l;+O}vfvx%XjH`}a{(-HHth9!JaUwV0*VqGR48^gWNYN<&~7x)y$e!X>e` zZ5!6KZoxbKuV9XUDI%#M1~IVh?pNSdeb~6@$y`v|yk=XK+fHxnDqnUK4&=QRNyIVf zYbDM*cI>~qIy*a7=z7uqkw@agd(<=y-Q7L!ty_23SGdXmahO<;N=wB+j;lNm%=OHC zy zU|>La6h%92y4IPufI$9>Xu!@y`TaNgtg&41@PwMwBdmSm7)xAWDLoqjZ==P2#*k7! z3o1)cVSI3KP_!?d8G^Lg0FtLXC~JYdxi|c%h~lXEixY=%VSFF@!*3&&9>(Rb|iK54Cx5;s~PY5iaV1het%w`dgQFBAJ;aFK zImQC}(|QaCFYUm1JVfzSc)ebv=)ObI)0jwJb``}Zj9J0n0Xgn*Zc(rFM9$xh_makZbm-at_v5^SW zM1y1SW@%+FuIy*WR)i3A2N_q;(YO`O!A|Ts^%z}9ZepCj3ytlw#x%N_fNrKKtPh`< z|1{UqF`4LxHaCQ79+E=uUXCOZ35jAMRz%R%0(P!0FMv=sk>Nr8%+OzY^c-M9@+fz=G`qa@v4sF5u-2289-#$**LWnyNNDwDf1( zkUiMnw|y$tn>pQP=Vn!#|17L^5AGrjtBkN$D@v)Z7LXc5EFhLB4<;7Wehh)CMqX|W zqsiZaO^benJ_hwa&V0ub$-_HUk**?g6fm9|!@kguU6*zhK)$qn-<3*kFrYPIaqR=V zUaUvk>@F_89b@tHs8R!*QKY;INJ<2_U+K6Ca3e9Gsl2{qY0%a7J?uICWgHuLfj+MB z=GkAN1&ifT#2u}B+2S#~$5jA(Qn^;H%CCmIae4AE-Dsng|Hl*Ov!z72k3ZnJs{pp| z+pW`DDueC#mEWOf=ucJ!dTL}hzOeiS-i?m2E;`EKz4<&Lu~NnW?peqVU^@<+T3KKu z{yrI%Qy-Z%HEvLUz}n^~m?7x`xuCtNR#L2En!T>dQtIKdS#V-Hzt3RtwTeYtmQ&dR z6qXZvac*oc@BUYEH%@Ylv_1&tSjkbzzU6*h1(3^C`;1z;g_SmOtclS?KWk2VYE zM*oS<=C483XckW?GN|1jfh3Ro(h + + diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index 3c6231258..a8c58d58d 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -1,6 +1,8 @@ package org.openpilot.androidgcs; import java.io.IOException; +import java.util.Observable; +import java.util.Observer; import java.util.Set; import java.util.UUID; @@ -10,11 +12,15 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Intent; import android.os.Bundle; +import android.os.Handler; import android.util.Log; +import android.widget.TextView; +import android.widget.ToggleButton; import org.openpilot.androidgcs.*; import org.openpilot.uavtalk.Telemetry; import org.openpilot.uavtalk.TelemetryMonitor; +import org.openpilot.uavtalk.UAVObject; import org.openpilot.uavtalk.UAVObjectManager; import org.openpilot.uavtalk.UAVTalk; import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; @@ -26,9 +32,35 @@ public class ObjectBrowser extends Activity { private final int REQUEST_ENABLE_BT = 0; private UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); BluetoothAdapter mBluetoothAdapter; + BluetoothSocket socket; + boolean connected; UAVObjectManager objMngr; UAVTalk uavTalk; + final Handler uavobjHandler = new Handler(); + final Runnable updateText = new Runnable() { + public void run() { + ToggleButton button = (ToggleButton) findViewById(R.id.toggleButton1); + button.setChecked(!connected); + + Log.d(TAG,"HERE" + connected); + + TextView text = (TextView) findViewById(R.id.textView1); + + UAVObject obj1 = objMngr.getObject("SystemStats"); + UAVObject obj2 = objMngr.getObject("AttitudeRaw"); + UAVObject obj3 = objMngr.getObject("AttitudeActual"); + UAVObject obj4 = objMngr.getObject("SystemAlarms"); + + if(obj1 == null || obj2 == null || obj3 == null || obj4 == null) + return; + + Log.d(TAG,"And here"); + text.setText(obj1.toString() + "\n" + obj2.toString() + "\n" + obj3.toString() + "\n" + obj4.toString() ); + + } + }; + /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { @@ -36,11 +68,16 @@ public class ObjectBrowser extends Activity { setContentView(R.layout.main); Log.d(TAG, "Launching Object Browser"); + + connected = false; + objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { // Device does not support Bluetooth - Log.d(TAG, "Device does not support Bluetooth"); + Log.e(TAG, "Device does not support Bluetooth"); return; } @@ -50,16 +87,49 @@ public class ObjectBrowser extends Activity { } else { queryDevices(); } + + + UAVObject obj = objMngr.getObject("SystemStats"); + if(obj != null) + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + uavobjHandler.post(updateText); + } + }); + obj = objMngr.getObject("AttitudeRaw"); + if(obj != null) + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + uavobjHandler.post(updateText); + } + }); + obj = objMngr.getObject("AttitudeActual"); + if(obj != null) + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + uavobjHandler.post(updateText); + } + }); + obj = objMngr.getObject("SystemAlarms"); + if(obj != null) + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + uavobjHandler.post(updateText); + } + }); + + } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == REQUEST_ENABLE_BT && resultCode == RESULT_OK) { - Log.d(TAG, "Bluetooth started succesfully"); + //Log.d(TAG, "Bluetooth started succesfully"); queryDevices(); } - if(requestCode == REQUEST_ENABLE_BT && resultCode != RESULT_OK) - Log.d(TAG, "Bluetooth could not be started"); + if(requestCode == REQUEST_ENABLE_BT && resultCode != RESULT_OK) { + //Log.d(TAG, "Bluetooth could not be started"); + } } @@ -84,12 +154,13 @@ public class ObjectBrowser extends Activity { private void openTelmetryBluetooth(BluetoothDevice device) { Log.d(TAG, "Opening conncetion to " + device.getName()); - BluetoothSocket socket = null; + socket = null; + connected = false; try { socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG,"Unable to create Rfcomm socket"); - e.printStackTrace(); + //e.printStackTrace(); } mBluetoothAdapter.cancelDiscovery(); @@ -102,20 +173,19 @@ public class ObjectBrowser extends Activity { try { socket.close(); } catch (IOException e2) { - Log.e(TAG, "unable to close() socket during connection failure", e2); + //Log.e(TAG, "unable to close() socket during connection failure", e2); } return; } - objMngr = new UAVObjectManager(); - UAVObjectsInitialize.register(objMngr); - + connected = true; + try { uavTalk = new UAVTalk(socket.getInputStream(), socket.getOutputStream(), objMngr); } catch (IOException e) { Log.e(TAG,"Error starting UAVTalk"); // TODO Auto-generated catch block - e.printStackTrace(); + //e.printStackTrace(); return; } From 74ea0e5ac2c8b418234793de87952d40bc5bdfdb Mon Sep 17 00:00:00 2001 From: James Cotton Date: Wed, 16 Mar 2011 15:19:18 -0500 Subject: [PATCH 033/284] Make it easy to enable or disable logging in separate modules --- .../src/org/openpilot/uavtalk/Telemetry.java | 30 +- .../openpilot/uavtalk/TelemetryMonitor.java | 41 +- .../src/org/openpilot/uavtalk/UAVObject.java | 12 + .../org/openpilot/uavtalk/UAVObjectField.java | 2 +- .../src/org/openpilot/uavtalk/UAVTalk.java | 593 ++++++++---------- 5 files changed, 324 insertions(+), 354 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index b403f85e3..c754c8329 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -17,7 +17,10 @@ import android.util.Log; public class Telemetry { private final String TAG = "Telemetry"; - + public static int LOGLEVEL = 0; + public static boolean WARN = LOGLEVEL > 1; + public static boolean DEBUG = LOGLEVEL > 0; + public class TelemetryStats { public int txBytes; public int rxBytes; @@ -227,7 +230,7 @@ public class Telemetry { } if ( (eventMask&EV_UPDATE_REQ) != 0) { - obj.addUpdatedObserver(new Observer() { + obj.addUpdateRequestedObserver(new Observer() { public void update(Observable observable, Object data) { updateRequested( (UAVObject) data); } @@ -293,10 +296,11 @@ public class Telemetry { */ private synchronized void transactionCompleted(UAVObject obj) { + if (DEBUG) Log.d(TAG,"UAVTalk transactionCompleted"); // Check if there is a pending transaction and the objects match if ( transPending && transInfo.obj.getObjID() == obj.getObjID() ) { - Log.d(TAG,"Telemetry: transaction completed for " + obj.getName()); + if (DEBUG) Log.d(TAG,"Telemetry: transaction completed for " + obj.getName()); // Complete transaction transTimer.cancel(); transPending = false; @@ -315,7 +319,7 @@ public class Telemetry { */ private synchronized void transactionTimeout() { - Log.d(TAG,"Telemetry: transaction timeout."); + if (DEBUG) Log.d(TAG,"Telemetry: transaction timeout."); transTimer.cancel(); // Proceed only if there is a pending transaction if ( transPending ) @@ -348,7 +352,7 @@ public class Telemetry { { if (transPending) { - Log.d(TAG, "Process Object transaction for " + transInfo.obj.getName()); + if (DEBUG) Log.d(TAG, "Process Object transaction for " + transInfo.obj.getName()); // Initiate transaction if (transInfo.objRequest) { @@ -380,7 +384,9 @@ public class Telemetry { private synchronized void processObjectUpdates(UAVObject obj, int event, boolean allInstances, boolean priority) { // Push event into queue - Log.d(TAG, "Push event into queue for obj " + obj.getName() + " event " + event); + if (DEBUG) Log.d(TAG, "Push event into queue for obj " + obj.getName() + " event " + event); + if(event == 8 && obj.getName().compareTo("GCSTelemetryStats") == 0) + Thread.dumpStack(); ObjectQueueInfo objInfo = new ObjectQueueInfo(); objInfo.obj = obj; objInfo.event = event; @@ -414,12 +420,7 @@ public class Telemetry { // If there is no transaction in progress then process event if (!transPending) { - processObjectQueue(); - - } else - { - Log.d(TAG,"Transaction pending, DO NOT process object queue..."); } } @@ -428,7 +429,7 @@ public class Telemetry { */ private synchronized void processObjectQueue() { - Log.d(TAG, "Process object queue - Depth " + objQueue.size() + " priority " + objPriorityQueue.size()); + if (DEBUG) Log.d(TAG, "Process object queue - Depth " + objQueue.size() + " priority " + objPriorityQueue.size()); // Don nothing if a transaction is already in progress (should not happen) if (transPending) @@ -460,6 +461,9 @@ public class Telemetry { objQueue.clear(); if ( objInfo.obj.getObjID() != objMngr.getObject("GCSTelemetryStats").getObjID() ) { + if (DEBUG) Log.d(TAG,"transactionCompleted(false) due to receiving object not GCSTelemetryStats while not connected."); + System.out.println(gcsStatsObj.toString()); + System.out.println(objInfo.obj.toString()); objInfo.obj.transactionCompleted(false); return; } @@ -511,6 +515,8 @@ public class Telemetry { */ private synchronized void processPeriodicUpdates() { + + if (DEBUG) Log.d(TAG, "processPeriodicUpdates()"); // Stop timer updateTimer.cancel(); diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index e2050fc25..a5885e7bc 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -57,6 +57,8 @@ public class TelemetryMonitor { */ public synchronized void startRetrievingObjects() { + Log.d(TAG, "Start retrieving objects"); + // Clear object queue queue.clear(); // Get all objects, add metaobjects, settings and data objects with OnChange update mode to the queue @@ -101,7 +103,7 @@ public class TelemetryMonitor { */ public void stopRetrievingObjects() { - //qxtLog->debug("Object retrieval has been cancelled"); + Log.d(TAG, "Stop retrieving objects"); queue.clear(); } @@ -113,6 +115,7 @@ public class TelemetryMonitor { // If queue is empty return if ( queue.isEmpty() ) { + Log.d(TAG, "All objects retrieved: Connected Successfully"); //qxtLog->debug("Object retrieval completed"); //emit connected(); return; @@ -121,8 +124,7 @@ public class TelemetryMonitor { UAVObject obj = queue.remove(0); if(obj == null) { - Log.e(TAG, "Got null object forom transaction queue"); - return; + throw new Error("Got null object forom transaction queue"); } Log.d(TAG, "Retrieving object: " + obj.getName()) ; @@ -130,6 +132,7 @@ public class TelemetryMonitor { obj.addTransactionCompleted(new Observer() { public void update(Observable observable, Object data) { UAVObject.TransactionResult result = (UAVObject.TransactionResult) data; + Log.d(TAG,"Got transaction completed event from " + result.obj.getName() + " status: " + result.success); transactionCompleted(result.obj, result.success); } }); @@ -146,11 +149,16 @@ public class TelemetryMonitor { { //QMutexLocker locker(mutex); // Disconnect from sending object - Log.d(TAG,"transactionCompleted"); + Log.d(TAG,"transactionCompleted. Status: " + success); // TODO: Need to be able to disconnect signals //obj->disconnect(this); objPending = null; + if(!success) { + Log.e(TAG, "Transaction failed: " + obj.getName() + " sending again."); + return; + } + // Process next object if telemetry is still available if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 ) { @@ -184,6 +192,7 @@ public class TelemetryMonitor { public synchronized void processStatsUpdates() { // Get telemetry stats + Log.d(TAG, "processStatsUpdates()"); Telemetry.TelemetryStats telStats = tel.getStats(); tel.resetStats(); @@ -221,9 +230,9 @@ public class TelemetryMonitor { return; } UAVObjectField statusField = gcsStatsObj.getField("Status"); - String oldStatus = (String) statusField.getValue(); + String oldStatus = new String((String) statusField.getValue()); - System.out.println("GCS: " + statusField.getValue() + " Flight: " + flightStatsObj.getField("Status").getValue()); + Log.d(TAG,"GCS: " + statusField.getValue() + " Flight: " + flightStatsObj.getField("Status").getValue()); if ( oldStatus.compareTo("Disconnected") == 0 ) { @@ -236,7 +245,7 @@ public class TelemetryMonitor { if ( ((String) flightStatsObj.getField("Status").getValue()).compareTo("HandshakeAck") == 0 ) { statusField.setValue("Connected"); - System.out.println("Connected" + statusField.toString()); + Log.d(TAG,"Connected" + statusField.toString()); } } else if ( oldStatus.compareTo("Connected") == 0 ) @@ -251,31 +260,31 @@ public class TelemetryMonitor { // Force telemetry update if not yet connected boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue()); - if(gcsStatusChanged) - System.out.println("GCS Status changed"); + if(gcsStatusChanged) { + Log.d(TAG,"GCS Status changed"); + Log.d(TAG,"GCS: " + statusField.getValue() + " Flight: " + flightStatsObj.getField("Status").getValue()); + } boolean gcsConnected = ((String) statusField.getValue()).compareTo("Connected") == 0; boolean gcsDisconnected = ((String) statusField.getValue()).compareTo("Disconnected") == 0; + boolean flightConnected = ((String) flightStatsObj.getField("Status").getValue()).compareTo("Connected") == 0; - if ( gcsStatusChanged || - ((String) flightStatsObj.getField("Status").getValue()).compareTo("Disconnected") != 0 ) + if ( !gcsConnected || !flightConnected ) { - System.out.println("Sending gcs status\n\n\n"); + Log.d(TAG,"Sending gcs status"); gcsStatsObj.updated(); } // Act on new connections or disconnections if (gcsConnected && gcsStatusChanged) { + Log.d(TAG,"Connection with the autopilot established"); setPeriod(STATS_UPDATE_PERIOD_MS); - System.out.println(TAG + " Connection with the autopilot established"); - //Log.d(TAG,"Connection with the autopilot established"); startRetrievingObjects(); } if (gcsDisconnected && gcsStatusChanged) { + Log.d(TAG,"Trying to connect to the autopilot"); setPeriod(STATS_CONNECT_PERIOD_MS); - System.out.println(TAG + " Connection with the autopilot lost"); - //Log.d(TAG,"Trying to connect to the autopilot"); //emit disconnected(); } } diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index b74df9218..ba3bf1ae3 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -102,6 +102,18 @@ public abstract class UAVObject { } } + private CallbackListener updateRequestedListeners = new CallbackListener(this); + public void addUpdateRequestedObserver(Observer o) { + synchronized(updateRequestedListeners) { + updateRequestedListeners.addObserver(o); + } + } + void updateRequested() { + synchronized(updateRequestedListeners) { + updateRequestedListeners.event(); + } + } + public abstract boolean isMetadata(); /** diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 8d792bb39..de2059e90 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -358,7 +358,7 @@ public class UAVObjectField { //throw new Exception("Sorry I haven't implemented strings yet"); } } - obj.updated(); + //obj.updated(); } } diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 825f9d9fe..33daefab7 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -9,49 +9,66 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Observable; -public class UAVTalk extends Observable{ +import android.util.Log; + +public class UAVTalk extends Observable { + + static final String TAG = "UAVTalk"; + public static int LOGLEVEL = 0; + public static boolean WARN = LOGLEVEL > 1; + public static boolean DEBUG = LOGLEVEL > 0; private Thread inputProcessingThread = null; + /** * A reference to the thread for processing the incoming stream + * * @return */ public Thread getInputProcessThread() { - if(inputProcessingThread == null) + if (inputProcessingThread == null) inputProcessingThread = new Thread() { - public void run() { - processInputStream(); - } - }; + public void run() { + processInputStream(); + } + }; return inputProcessingThread; } - + /** * Constants */ private static final int SYNC_VAL = 0x3C; - private static final short crc_table[] = { - 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, - 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, - 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, - 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, - 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, - 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, - 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, - 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, - 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, - 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, - 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, - 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, - 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, - 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, - 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, - 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 - }; + private static final short crc_table[] = { 0x00, 0x07, 0x0e, 0x09, 0x1c, + 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, + 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, + 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, + 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 0x90, + 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, + 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, + 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, + 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, + 0x94, 0x9d, 0x9a, 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, + 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, + 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, + 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, + 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 0xf9, 0xfe, 0xf7, 0xf0, + 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, + 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, + 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10, 0x05, + 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, + 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, + 0x7f, 0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, + 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, + 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, + 0x8a, 0x8d, 0x84, 0x83, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, + 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 }; - enum RxStateType {STATE_SYNC, STATE_TYPE, STATE_SIZE, STATE_OBJID, STATE_INSTID, STATE_DATA, STATE_CS}; + enum RxStateType { + STATE_SYNC, STATE_TYPE, STATE_SIZE, STATE_OBJID, STATE_INSTID, STATE_DATA, STATE_CS + }; static final int TYPE_MASK = 0xFC; static final int TYPE_VER = 0x20; @@ -60,17 +77,21 @@ public class UAVTalk extends Observable{ static final int TYPE_OBJ_ACK = (TYPE_VER | 0x02); static final int TYPE_ACK = (TYPE_VER | 0x03); - static final int MIN_HEADER_LENGTH = 8; // sync(1), type (1), size(2), object ID(4) - static final int MAX_HEADER_LENGTH = 10; // sync(1), type (1), size(2), object ID (4), instance ID(2, not used in single objects) + static final int MIN_HEADER_LENGTH = 8; // sync(1), type (1), size(2), + // object ID(4) + static final int MAX_HEADER_LENGTH = 10; // sync(1), type (1), size(2), + // object ID (4), instance ID(2, + // not used in single objects) static final int CHECKSUM_LENGTH = 1; static final int MAX_PAYLOAD_LENGTH = 256; - static final int MAX_PACKET_LENGTH = (MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + CHECKSUM_LENGTH); + static final int MAX_PACKET_LENGTH = (MAX_HEADER_LENGTH + + MAX_PAYLOAD_LENGTH + CHECKSUM_LENGTH); static final int ALL_INSTANCES = 0xFFFF; - static final int TX_BUFFER_SIZE = 2*1024; + static final int TX_BUFFER_SIZE = 2 * 1024; /** * Private data @@ -93,12 +114,12 @@ public class UAVTalk extends Observable{ int rxCSPacket, rxCS; int rxCount; int packetSize; - RxStateType rxState; + RxStateType rxState; ComStats stats = new ComStats(); /** * Comm stats - */ + */ public class ComStats { public int txBytes = 0; public int rxBytes = 0; @@ -113,8 +134,8 @@ public class UAVTalk extends Observable{ /** * Constructor */ - public UAVTalk(InputStream inStream, OutputStream outStream, UAVObjectManager objMngr) - { + public UAVTalk(InputStream inStream, OutputStream outStream, + UAVObjectManager objMngr) { this.objMngr = objMngr; this.inStream = inStream; this.outStream = outStream; @@ -122,7 +143,7 @@ public class UAVTalk extends Observable{ rxState = RxStateType.STATE_SYNC; rxPacketLength = 0; - //mutex = new QMutex(QMutex::Recursive); + // mutex = new QMutex(QMutex::Recursive); respObj = null; resetStats(); @@ -131,88 +152,80 @@ public class UAVTalk extends Observable{ rxBuffer = ByteBuffer.allocate(MAX_PAYLOAD_LENGTH); rxBuffer.order(ByteOrder.LITTLE_ENDIAN); - // TOOD: Callback connect(io, SIGNAL(readyRead()), this, SLOT(processInputStream())); + // TOOD: Callback connect(io, SIGNAL(readyRead()), this, + // SLOT(processInputStream())); } /** * Reset the statistics counters */ - public void resetStats() - { - //QMutexLocker locker(mutex); + public void resetStats() { + // QMutexLocker locker(mutex); stats = new ComStats(); } /** * Get the statistics counters */ - public ComStats getStats() - { - //QMutexLocker locker(mutex); + public ComStats getStats() { + // QMutexLocker locker(mutex); return stats; } /** * Called each time there are data in the input buffer */ - public void processInputStream() - { + public void processInputStream() { int val; - - while (true) - { + + while (true) { try { - //inStream.wait(); + // inStream.wait(); val = inStream.read(); - } /*catch (InterruptedException e) { - // TODO Auto-generated catch block - System.out.println("Connection was aborted\n"); - e.printStackTrace(); - break; - }*/ catch (IOException e) { + } /* + * catch (InterruptedException e) { // TODO Auto-generated catch + * block System.out.println("Connection was aborted\n"); + * e.printStackTrace(); break; } + */catch (IOException e) { // TODO Auto-generated catch block System.out.println("Error reading from stream\n"); e.printStackTrace(); break; } - if(val == -1) { - System.out.println("End of stream, terminating processInputStream thread"); + if (val == -1) { + System.out + .println("End of stream, terminating processInputStream thread"); break; } - - //System.out.println("Received byte " + val + " in state + " + rxState); + + // System.out.println("Received byte " + val + " in state + " + + // rxState); processInputByte(val); } } /** - * Request an update for the specified object, on success the object data would have been - * updated by the GCS. - * \param[in] obj Object to update + * Request an update for the specified object, on success the object data + * would have been updated by the GCS. \param[in] obj Object to update * \param[in] allInstances If set true then all instances will be updated * \return Success (true), Failure (false) */ - public boolean sendObjectRequest(UAVObject obj, boolean allInstances) - { - //QMutexLocker locker(mutex); + public boolean sendObjectRequest(UAVObject obj, boolean allInstances) { + // QMutexLocker locker(mutex); return objectTransaction(obj, TYPE_OBJ_REQ, allInstances); } /** - * Send the specified object through the telemetry link. - * \param[in] obj Object to send - * \param[in] acked Selects if an ack is required - * \param[in] allInstances If set true then all instances will be updated - * \return Success (true), Failure (false) + * Send the specified object through the telemetry link. \param[in] obj + * Object to send \param[in] acked Selects if an ack is required \param[in] + * allInstances If set true then all instances will be updated \return + * Success (true), Failure (false) */ - public synchronized boolean sendObject(UAVObject obj, boolean acked, boolean allInstances) - { - if (acked) - { + public synchronized boolean sendObject(UAVObject obj, boolean acked, + boolean allInstances) { + if (acked) { return objectTransaction(obj, TYPE_OBJ_ACK, allInstances); - } - else - { + } else { return objectTransaction(obj, TYPE_OBJ, allInstances); } } @@ -220,64 +233,49 @@ public class UAVTalk extends Observable{ /** * Cancel a pending transaction */ - public synchronized void cancelTransaction() - { + public synchronized void cancelTransaction() { respObj = null; } /** - * Execute the requested transaction on an object. - * \param[in] obj Object - * \param[in] type Transaction type - * TYPE_OBJ: send object, - * TYPE_OBJ_REQ: request object update - * TYPE_OBJ_ACK: send object with an ack - * \param[in] allInstances If set true then all instances will be updated - * \return Success (true), Failure (false) + * Execute the requested transaction on an object. \param[in] obj Object + * \param[in] type Transaction type TYPE_OBJ: send object, TYPE_OBJ_REQ: + * request object update TYPE_OBJ_ACK: send object with an ack \param[in] + * allInstances If set true then all instances will be updated \return + * Success (true), Failure (false) */ - public boolean objectTransaction(UAVObject obj, int type, boolean allInstances) - { + public boolean objectTransaction(UAVObject obj, int type, + boolean allInstances) { // Send object depending on if a response is needed - if (type == TYPE_OBJ_ACK || type == TYPE_OBJ_REQ) - { - if ( transmitObject(obj, type, allInstances) ) - { + if (type == TYPE_OBJ_ACK || type == TYPE_OBJ_REQ) { + if (transmitObject(obj, type, allInstances)) { respObj = obj; - respAllInstances = allInstances; + respAllInstances = allInstances; return true; - } - else - { + } else { return false; } - } - else if (type == TYPE_OBJ) - { + } else if (type == TYPE_OBJ) { return transmitObject(obj, TYPE_OBJ, allInstances); - } - else - { + } else { return false; } } /** - * Process an byte from the telemetry stream. - * \param[in] rxbyte Received byte - * \return Success (true), Failure (false) + * Process an byte from the telemetry stream. \param[in] rxbyte Received + * byte \return Success (true), Failure (false) */ - public synchronized boolean processInputByte(int rxbyte) - { - assert(objMngr != null); + public synchronized boolean processInputByte(int rxbyte) { + assert (objMngr != null); // Update stats stats.rxBytes++; - rxPacketLength++; // update packet byte count + rxPacketLength++; // update packet byte count // Receive state machine - switch (rxState) - { + switch (rxState) { case STATE_SYNC: if (rxbyte != SYNC_VAL) @@ -296,8 +294,7 @@ public class UAVTalk extends Observable{ // Update CRC rxCS = updateCRC(rxCS, rxbyte); - if ((rxbyte & TYPE_MASK) != TYPE_VER) - { + if ((rxbyte & TYPE_MASK) != TYPE_VER) { rxState = RxStateType.STATE_SYNC; break; } @@ -315,8 +312,7 @@ public class UAVTalk extends Observable{ // Update CRC rxCS = updateCRC(rxCS, rxbyte); - if (rxCount == 0) - { + if (rxCount == 0) { packetSize += rxbyte; rxCount++; break; @@ -324,10 +320,12 @@ public class UAVTalk extends Observable{ packetSize += (rxbyte << 8) & 0xff00; - if (packetSize < MIN_HEADER_LENGTH || packetSize > MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH) - { // incorrect packet size + if (packetSize < MIN_HEADER_LENGTH + || packetSize > MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH) { // incorrect + // packet + // size rxState = RxStateType.STATE_SYNC; - break; + break; } rxCount = 0; @@ -348,8 +346,7 @@ public class UAVTalk extends Observable{ rxObjId = rxTmpBuffer.getInt(0); { UAVObject rxObj = objMngr.getObject(rxObjId); - if (rxObj == null) - { + if (rxObj == null) { stats.rxErrors++; rxState = RxStateType.STATE_SYNC; break; @@ -361,38 +358,38 @@ public class UAVTalk extends Observable{ else rxLength = rxObj.getNumBytes(); - // Check length and determine next state - if (rxLength >= MAX_PAYLOAD_LENGTH) - { - stats.rxErrors++; - rxState = RxStateType.STATE_SYNC; - break; - } + // Check length and determine next state + if (rxLength >= MAX_PAYLOAD_LENGTH) { + stats.rxErrors++; + rxState = RxStateType.STATE_SYNC; + break; + } - // Check the lengths match - if ((rxPacketLength + rxLength) != packetSize) - { // packet error - mismatched packet size - stats.rxErrors++; - rxState = RxStateType.STATE_SYNC; - break; - } + // Check the lengths match + if ((rxPacketLength + rxLength) != packetSize) { // packet error + // - + // mismatched + // packet + // size + stats.rxErrors++; + rxState = RxStateType.STATE_SYNC; + break; + } - // Check if this is a single instance object (i.e. if the instance ID field is coming next) - if (rxObj.isSingleInstance()) - { - // If there is a payload get it, otherwise receive checksum - if (rxLength > 0) - rxState = RxStateType.STATE_DATA; - else - rxState = RxStateType.STATE_CS; - rxInstId = 0; - rxCount = 0; - } + // Check if this is a single instance object (i.e. if the + // instance ID field is coming next) + if (rxObj.isSingleInstance()) { + // If there is a payload get it, otherwise receive checksum + if (rxLength > 0) + rxState = RxStateType.STATE_DATA; else - { - rxState = RxStateType.STATE_INSTID; - rxCount = 0; - } + rxState = RxStateType.STATE_CS; + rxInstId = 0; + rxCount = 0; + } else { + rxState = RxStateType.STATE_INSTID; + rxCount = 0; + } } break; @@ -419,7 +416,7 @@ public class UAVTalk extends Observable{ break; case STATE_DATA: - + // Update CRC rxCS = updateCRC(rxCS, rxbyte); @@ -436,15 +433,15 @@ public class UAVTalk extends Observable{ // The CRC byte rxCSPacket = rxbyte; - if (rxCS != rxCSPacket) - { // packet error - faulty CRC + if (rxCS != rxCSPacket) { // packet error - faulty CRC stats.rxErrors++; rxState = RxStateType.STATE_SYNC; break; } - if (rxPacketLength != (packetSize + 1)) - { // packet error - mismatched packet size + if (rxPacketLength != (packetSize + 1)) { // packet error - + // mismatched packet + // size stats.rxErrors++; rxState = RxStateType.STATE_SYNC; break; @@ -468,103 +465,84 @@ public class UAVTalk extends Observable{ } /** - * Receive an object. This function process objects received through the telemetry stream. - * \param[in] type Type of received message (TYPE_OBJ, TYPE_OBJ_REQ, TYPE_OBJ_ACK, TYPE_ACK) - * \param[in] obj Handle of the received object - * \param[in] instId The instance ID of UAVOBJ_ALL_INSTANCES for all instances. - * \param[in] data Data buffer - * \param[in] length Buffer length - * \return Success (true), Failure (false) + * Receive an object. This function process objects received through the + * telemetry stream. \param[in] type Type of received message (TYPE_OBJ, + * TYPE_OBJ_REQ, TYPE_OBJ_ACK, TYPE_ACK) \param[in] obj Handle of the + * received object \param[in] instId The instance ID of UAVOBJ_ALL_INSTANCES + * for all instances. \param[in] data Data buffer \param[in] length Buffer + * length \return Success (true), Failure (false) */ - public boolean receiveObject(int type, int objId, int instId, ByteBuffer data) - { - assert(objMngr != null); - + public boolean receiveObject(int type, int objId, int instId, + ByteBuffer data) { + assert (objMngr != null); + UAVObject obj = null; boolean error = false; - boolean allInstances = (instId == ALL_INSTANCES? true : false); + boolean allInstances = (instId == ALL_INSTANCES ? true : false); // Process message type switch (type) { case TYPE_OBJ: // All instances, not allowed for OBJ messages - if (!allInstances) - { - System.out.println("Received object: " + objMngr.getObject(objId).getName()); + if (!allInstances) { + if (DEBUG) Log.d(TAG,"Received object: " + objMngr.getObject(objId).getName()); // Get object and update its data obj = updateObject(objId, instId, data); // Check if an ack is pending - if ( obj != null ) - { + if (obj != null) { updateAck(obj); - } - else - { + } else { error = true; } - } - else - { + } else { error = true; } break; case TYPE_OBJ_ACK: // All instances, not allowed for OBJ_ACK messages - if (!allInstances) - { -// System.out.println("Received object ack: " + objId + " " + objMngr.getObject(objId).getName()); + if (!allInstances) { + // System.out.println("Received object ack: " + objId + " " + + // objMngr.getObject(objId).getName()); // Get object and update its data obj = updateObject(objId, instId, data); // Transmit ACK - if ( obj != null ) - { + if (obj != null) { transmitObject(obj, TYPE_ACK, false); - } - else - { + } else { error = true; } - } - else - { + } else { error = true; } break; case TYPE_OBJ_REQ: - // Get object, if all instances are requested get instance 0 of the object -// System.out.println("Received object request: " + objId + " " + objMngr.getObject(objId).getName()); - if (allInstances) - { + // Get object, if all instances are requested get instance 0 of the + // object + // System.out.println("Received object request: " + objId + " " + + // objMngr.getObject(objId).getName()); + if (allInstances) { obj = objMngr.getObject(objId); - } - else - { + } else { obj = objMngr.getObject(objId, instId); } // If object was found transmit it - if (obj != null) - { + if (obj != null) { transmitObject(obj, TYPE_OBJ, allInstances); - } - else - { + } else { error = true; } break; case TYPE_ACK: // All instances, not allowed for ACK messages - if (!allInstances) - { -// System.out.println("Received ack: " + objId + " " + objMngr.getObject(objId).getName()); + if (!allInstances) { + // System.out.println("Received ack: " + objId + " " + + // objMngr.getObject(objId).getName()); // Get object obj = objMngr.getObject(objId, instId); // Check if an ack is pending - if (obj != null) - { + if (obj != null) { updateAck(obj); - } - else - { + } else { error = true; } } @@ -577,23 +555,20 @@ public class UAVTalk extends Observable{ } /** - * Update the data of an object from a byte array (unpack). - * If the object instance could not be found in the list, then a - * new one is created. + * Update the data of an object from a byte array (unpack). If the object + * instance could not be found in the list, then a new one is created. */ - public synchronized UAVObject updateObject(int objId, int instId, ByteBuffer data) - { - assert(objMngr != null); + public synchronized UAVObject updateObject(int objId, int instId, + ByteBuffer data) { + assert (objMngr != null); // Get object UAVObject obj = objMngr.getObject(objId, instId); // If the instance does not exist create it - if (obj == null) - { + if (obj == null) { // Get the object type UAVObject tobj = objMngr.getObject(objId); - if (tobj == null) - { + if (tobj == null) { return null; } // Make sure this is a data object @@ -604,26 +579,26 @@ public class UAVTalk extends Observable{ // Failed to cast to a data object return null; } - + // Create a new instance, unpack and register UAVDataObject instobj = dobj.clone(instId); try { - if ( !objMngr.registerObject(instobj) ) - { + if (!objMngr.registerObject(instobj)) { return null; } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } -// System.out.println("Unpacking new object"); + // System.out.println("Unpacking new object"); + if (DEBUG) Log.d(TAG, "Unpacking new object"); instobj.unpack(data); return instobj; - } - else - { + } else { // Unpack data into object instance -// System.out.println("Unpacking existing object: " + data.position() + " / " + data.capacity() ); + // System.out.println("Unpacking existing object: " + + // data.position() + " / " + data.capacity() ); + if (DEBUG) Log.d(TAG, "Unpacking existing object: " + obj.getName()); obj.unpack(data); return obj; } @@ -632,10 +607,9 @@ public class UAVTalk extends Observable{ /** * Check if a transaction is pending and if yes complete it. */ - public void updateAck(UAVObject obj) - { - if (respObj != null && respObj.getObjID() == obj.getObjID() && (respObj.getInstID() == obj.getInstID() || respAllInstances)) - { + synchronized void updateAck(UAVObject obj) { + if (respObj != null && respObj.getObjID() == obj.getObjID() + && (respObj.getInstID() == obj.getInstID() || respAllInstances)) { respObj = null; setChanged(); notifyObservers(obj); @@ -643,111 +617,88 @@ public class UAVTalk extends Observable{ } /** - * Send an object through the telemetry link. - * \param[in] obj Object to send - * \param[in] type Transaction type - * \param[in] allInstances True is all instances of the object are to be sent - * \return Success (true), Failure (false) + * Send an object through the telemetry link. + * @param[in] obj Object to send + * @param[in] type Transaction type + * @param[in] allInstances True is all instances of the object are to be sent + * @return Success (true), Failure (false) */ - public boolean transmitObject(UAVObject obj, int type, boolean allInstances) - { - // If all instances are requested on a single instance object it is an error - if (allInstances && obj.isSingleInstance()) - { + public synchronized boolean transmitObject(UAVObject obj, int type, boolean allInstances) { + // If all instances are requested on a single instance object it is an + // error + if (allInstances && obj.isSingleInstance()) { allInstances = false; } // Process message type - if ( type == TYPE_OBJ || type == TYPE_OBJ_ACK ) - { - if (allInstances) - { + if (type == TYPE_OBJ || type == TYPE_OBJ_ACK) { + if (allInstances) { // Get number of instances int numInst = objMngr.getNumInstances(obj.getObjID()); // Send all instances - for (int instId = 0; instId < numInst; ++instId) - { + for (int instId = 0; instId < numInst; ++instId) { UAVObject inst = objMngr.getObject(obj.getObjID(), instId); transmitSingleObject(inst, type, false); } return true; - } - else - { + } else { return transmitSingleObject(obj, type, false); } - } - else if (type == TYPE_OBJ_REQ) - { + } else if (type == TYPE_OBJ_REQ) { return transmitSingleObject(obj, TYPE_OBJ_REQ, allInstances); - } - else if (type == TYPE_ACK) - { - if (!allInstances) - { + } else if (type == TYPE_ACK) { + if (!allInstances) { return transmitSingleObject(obj, TYPE_ACK, false); - } - else - { + } else { return false; } - } - else - { + } else { return false; } } - /** - * Send an object through the telemetry link. - * \param[in] obj Object handle to send - * \param[in] type Transaction type - * \return Success (true), Failure (false) + * Send an object through the telemetry link. \param[in] obj Object handle + * to send \param[in] type Transaction type \return Success (true), Failure + * (false) */ - public synchronized boolean transmitSingleObject(UAVObject obj, int type, boolean allInstances) - { + public synchronized boolean transmitSingleObject(UAVObject obj, int type, + boolean allInstances) { int length; int dataOffset; int objId; int instId; int allInstId = ALL_INSTANCES; - - assert(objMngr != null && outStream != null); - + + assert (objMngr != null && outStream != null); + ByteBuffer bbuf = ByteBuffer.allocate(MAX_PACKET_LENGTH); bbuf.order(ByteOrder.LITTLE_ENDIAN); // Determine data length - if (type == TYPE_OBJ_REQ || type == TYPE_ACK) - { + if (type == TYPE_OBJ_REQ || type == TYPE_ACK) { length = 0; - } - else - { + } else { length = obj.getNumBytes(); } - + // Setup type and object id fields bbuf.put((byte) (SYNC_VAL & 0xff)); bbuf.put((byte) (type & 0xff)); - bbuf.putShort((short) (length + - 2 /* SYNC, Type */ + - 2 /* Size */ + - 4 /* ObjID */ + - (obj.isSingleInstance() ? 0 : 2) )); + bbuf + .putShort((short) (length + 2 /* SYNC, Type */+ 2 /* Size */+ 4 /* ObjID */+ (obj + .isSingleInstance() ? 0 : 2))); bbuf.putInt(obj.getObjID()); - + // Setup instance ID if one is required - if ( !obj.isSingleInstance() ) - { + if (!obj.isSingleInstance()) { // Check if all instances are requested if (allInstances) bbuf.putShort((short) (allInstId & 0xffff)); else bbuf.putShort((short) (obj.getInstID() & 0xffff)); } - + // Check length if (length >= MAX_PAYLOAD_LENGTH) return false; @@ -755,7 +706,7 @@ public class UAVTalk extends Observable{ // Copy data (if any) if (length > 0) try { - if ( obj.pack(bbuf) == 0) + if (obj.pack(bbuf) == 0) return false; } catch (Exception e) { // TODO Auto-generated catch block @@ -769,26 +720,28 @@ public class UAVTalk extends Observable{ try { int packlen = bbuf.position(); bbuf.position(0); - byte [] dst = new byte[packlen]; - bbuf.get(dst,0,packlen); + byte[] dst = new byte[packlen]; + bbuf.get(dst, 0, packlen); outStream.write(dst); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } - -// //TODO: Need to use a different outStream type and check that the backlog isn't more than TX_BUFFER_SIZE -// // Send buffer, check that the transmit backlog does not grow above limit -// if ( io->bytesToWrite() < TX_BUFFER_SIZE ) -// { -// io->write((const char*)txBuffer, dataOffset+length+CHECKSUM_LENGTH); -// } -// else -// { -// ++stats.txErrors; -// return false; -// } + + // //TODO: Need to use a different outStream type and check that the + // backlog isn't more than TX_BUFFER_SIZE + // // Send buffer, check that the transmit backlog does not grow above + // limit + // if ( io->bytesToWrite() < TX_BUFFER_SIZE ) + // { + // io->write((const char*)txBuffer, dataOffset+length+CHECKSUM_LENGTH); + // } + // else + // { + // ++stats.txErrors; + // return false; + // } // Update stats ++stats.txObjects; @@ -801,33 +754,23 @@ public class UAVTalk extends Observable{ /** * Update the crc value with new data. - * - * Generated by pycrc v0.7.5, http://www.tty1.net/pycrc/ - * using the configuration: - * Width = 8 - * Poly = 0x07 - * XorIn = 0x00 - * ReflectIn = False - * XorOut = 0x00 - * ReflectOut = False - * Algorithm = table-driven - * - * \param crc The current crc value. - * \param data Pointer to a buffer of \a data_len bytes. - * \param length Number of bytes in the \a data buffer. - * \return The updated crc value. + * + * Generated by pycrc v0.7.5, http://www.tty1.net/pycrc/ using the + * configuration: Width = 8 Poly = 0x07 XorIn = 0x00 ReflectIn = False + * XorOut = 0x00 ReflectOut = False Algorithm = table-driven + * + * \param crc The current crc value. \param data Pointer to a buffer of \a + * data_len bytes. \param length Number of bytes in the \a data buffer. + * \return The updated crc value. */ - int updateCRC(int crc, int data) - { + int updateCRC(int crc, int data) { return crc_table[crc ^ (data & 0xff)]; } - int updateCRC(int crc, byte [] data, int length) - { + + int updateCRC(int crc, byte[] data, int length) { for (int i = 0; i < length; i++) crc = updateCRC(crc, (int) data[i]); - return crc; + return crc; } - - } From 38213de9aa40450a745e4bec8441057972c95e3a Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 17 Mar 2011 13:57:18 -0500 Subject: [PATCH 034/284] Make the UAVTalk object process one byte per call so it can be embedded in another loop. Also clean up some warnings. --- .../src/org/openpilot/uavtalk/UAVTalk.java | 59 +++++++++---------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 33daefab7..8671cdef9 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -1,7 +1,5 @@ package org.openpilot.uavtalk; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -30,7 +28,10 @@ public class UAVTalk extends Observable { inputProcessingThread = new Thread() { public void run() { - processInputStream(); + while(true) { + if( !processInputStream() ) + break; + } } }; return inputProcessingThread; @@ -173,37 +174,36 @@ public class UAVTalk extends Observable { } /** - * Called each time there are data in the input buffer + * Process any data in the queue */ - public void processInputStream() { + public boolean processInputStream() { int val; - while (true) { - try { - // inStream.wait(); - val = inStream.read(); - } /* - * catch (InterruptedException e) { // TODO Auto-generated catch - * block System.out.println("Connection was aborted\n"); - * e.printStackTrace(); break; } - */catch (IOException e) { - // TODO Auto-generated catch block - System.out.println("Error reading from stream\n"); - e.printStackTrace(); - break; - } - if (val == -1) { - System.out - .println("End of stream, terminating processInputStream thread"); - break; - } + try { + // inStream.wait(); + val = inStream.read(); + } /* + * catch (InterruptedException e) { // TODO Auto-generated catch + * block System.out.println("Connection was aborted\n"); + * e.printStackTrace(); break; } + */catch (IOException e) { + // TODO Auto-generated catch block + System.out.println("Error reading from stream\n"); + e.printStackTrace(); + return false; + } + if (val == -1) { + System.out.println("End of stream, terminating processInputStream thread"); + return false; + } - // System.out.println("Received byte " + val + " in state + " + - // rxState); - processInputByte(val); - } + // System.out.println("Received byte " + val + " in state + " + + // rxState); + processInputByte(val); + return true; } + /** * Request an update for the specified object, on success the object data * would have been updated by the GCS. \param[in] obj Object to update @@ -665,9 +665,6 @@ public class UAVTalk extends Observable { public synchronized boolean transmitSingleObject(UAVObject obj, int type, boolean allInstances) { int length; - int dataOffset; - int objId; - int instId; int allInstId = ALL_INSTANCES; assert (objMngr != null && outStream != null); From 6edafd2c5f63d678d3346a1baaf2a6f8a1cf7e8f Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 17 Mar 2011 13:58:55 -0500 Subject: [PATCH 035/284] Create a UAVTalk service that is called from the object browser --- androidgcs/AndroidManifest.xml | 1 + .../androidgcs/BluetoothUAVTalk.java | 146 ++++++++++++++++++ .../androidgcs/OPTelemetryService.java | 88 +++++++++++ .../openpilot/androidgcs/ObjectBrowser.java | 97 +----------- 4 files changed, 238 insertions(+), 94 deletions(-) create mode 100644 androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java create mode 100644 androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index 8b3a9e4b3..6c89f2632 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -18,5 +18,6 @@ + \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java new file mode 100644 index 000000000..b240f3adc --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java @@ -0,0 +1,146 @@ +package org.openpilot.androidgcs; + +import java.io.IOException; +import java.util.Set; +import java.util.UUID; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVTalk; + +import android.app.Activity; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +public class BluetoothUAVTalk { + private final String TAG = "BluetoothUAVTalk"; + public static int LOGLEVEL = 2; + public static boolean WARN = LOGLEVEL > 1; + public static boolean DEBUG = LOGLEVEL > 0; + + // Temporarily define fixed device name + public final static String DEVICE_NAME = "RN42-222D"; + private final static UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); + + private BluetoothAdapter mBluetoothAdapter; + private BluetoothSocket socket; + private BluetoothDevice device; + private UAVTalk uavTalk; + private boolean connected; + + public BluetoothUAVTalk(Context caller, String deviceName) { + if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + deviceName); + + connected = false; + device = null; + + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (mBluetoothAdapter == null) { + // Device does not support Bluetooth + Log.e(TAG, "Device does not support Bluetooth"); + return; + } + + if (!mBluetoothAdapter.isEnabled()) { + // Enable bluetooth if it isn't already + Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + caller.sendOrderedBroadcast(enableBtIntent, "android.permission.BLUETOOTH_ADMIN", new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Log.e(TAG,"Received " + context + intent); + //TODO: some logic here to see if it worked + queryDevices(); + } + }, null, Activity.RESULT_OK, null, null); + } else { + queryDevices(); + } + } + + public boolean connect(UAVObjectManager objMngr) { + if( getConnected() ) + return true; + if( !getFoundDevice() ) + return false; + if( !openTelemetryBluetooth(objMngr) ) + return false; + return true; + } + + public boolean getConnected() { + return connected; + } + + public boolean getFoundDevice() { + return (device != null); + } + + public UAVTalk getUavtalk() { + return uavTalk; + } + + private void queryDevices() { + Log.d(TAG, "Searching for devices"); + Set pairedDevices = mBluetoothAdapter.getBondedDevices(); + // If there are paired devices + if (pairedDevices.size() > 0) { + // Loop through paired devices + for (BluetoothDevice device : pairedDevices) { + // Add the name and address to an array adapter to show in a ListView + //mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); + Log.d(TAG, "Paired device: " + device.getName()); + if(device.getName().compareTo(DEVICE_NAME) == 0) { + this.device = device; + return; + } + } + } + + } + + private boolean openTelemetryBluetooth(UAVObjectManager objMngr) { + Log.d(TAG, "Opening conncetion to " + device.getName()); + socket = null; + connected = false; + try { + socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID); + } catch (IOException e) { + Log.e(TAG,"Unable to create Rfcomm socket"); + return false; + //e.printStackTrace(); + } + + mBluetoothAdapter.cancelDiscovery(); + + try { + socket.connect(); + } + catch (IOException e) { + Log.e(TAG,"Unable to connect to requested device", e); + try { + socket.close(); + } catch (IOException e2) { + Log.e(TAG, "unable to close() socket during connection failure", e2); + } + return false; + } + + connected = true; + + try { + uavTalk = new UAVTalk(socket.getInputStream(), socket.getOutputStream(), objMngr); + } catch (IOException e) { + Log.e(TAG,"Error starting UAVTalk"); + // TODO Auto-generated catch block + //e.printStackTrace(); + return false; + } + + return true; + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java new file mode 100644 index 000000000..2994be6d2 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -0,0 +1,88 @@ +package org.openpilot.androidgcs; + +import org.openpilot.uavtalk.Telemetry; +import org.openpilot.uavtalk.TelemetryMonitor; +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVTalk; +import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.os.Looper; +import android.util.Log; + +public class OPTelemetryService extends Service { + private final String TAG = "OPTElemetryService"; + public static int LOGLEVEL = 2; + public static boolean WARN = LOGLEVEL > 1; + public static boolean DEBUG = LOGLEVEL > 0; + + private UAVObjectManager objMngr; + private UAVTalk uavTalk; + private Telemetry tel; + private TelemetryMonitor mon; + + @Override + public IBinder onBind(Intent arg0) { + return null; + } + + @Override + public void onCreate() { + super.onCreate(); + + if (DEBUG) Log.d(TAG, "Telemetry Service started"); + + Thread telemetryThread = new Thread(telemetryRunnable); + telemetryThread.start(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + private final Runnable telemetryRunnable = new Runnable() { + + public void run() { + Looper.prepare(); + + if (DEBUG) Log.d(TAG, "Telemetry Thread started"); + + objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + + BluetoothUAVTalk bt = new BluetoothUAVTalk(OPTelemetryService.this, BluetoothUAVTalk.DEVICE_NAME); + while(true) { + if (DEBUG) Log.d(TAG, "Attempting Bluetooth Connection"); + if(! bt.getConnected() ) + bt.connect(objMngr); + else + break; + Looper.loop(); + } + + if (DEBUG) Log.d(TAG, "Connected via bluetooth"); + + uavTalk = bt.getUavtalk(); + tel = new Telemetry(uavTalk, objMngr); + mon = new TelemetryMonitor(objMngr,tel); + + if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop"); + while(true) { + if( !uavTalk.processInputStream() ) + break; + Looper.loop(); + } + if (DEBUG) Log.d(TAG, "UAVTalk stream disconnected"); + } + + }; + + public UAVObjectManager getObjMngr() { return objMngr; }; + public UAVTalk getUavTalk() { return uavTalk; }; + public Telemetry getTelemetry() { return tel; }; + public TelemetryMonitor getTelemetryMonitor() { return mon; }; + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index a8c58d58d..6bb217930 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -69,26 +69,12 @@ public class ObjectBrowser extends Activity { Log.d(TAG, "Launching Object Browser"); - connected = false; + Log.d(TAG, "Start OP Telemetry Service"); + startService( new Intent( this, OPTelemetryService.class ) ); objMngr = new UAVObjectManager(); UAVObjectsInitialize.register(objMngr); - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mBluetoothAdapter == null) { - // Device does not support Bluetooth - Log.e(TAG, "Device does not support Bluetooth"); - return; - } - - if (!mBluetoothAdapter.isEnabled()) { - Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); - startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); - } else { - queryDevices(); - } - - UAVObject obj = objMngr.getObject("SystemStats"); if(obj != null) obj.addUpdatedObserver(new Observer() { @@ -116,84 +102,7 @@ public class ObjectBrowser extends Activity { public void update(Observable observable, Object data) { uavobjHandler.post(updateText); } - }); - - + }); } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if(requestCode == REQUEST_ENABLE_BT && resultCode == RESULT_OK) { - //Log.d(TAG, "Bluetooth started succesfully"); - queryDevices(); - } - if(requestCode == REQUEST_ENABLE_BT && resultCode != RESULT_OK) { - //Log.d(TAG, "Bluetooth could not be started"); - } - - } - - public void queryDevices() { - Log.d(TAG, "Searching for devices"); - Set pairedDevices = mBluetoothAdapter.getBondedDevices(); - // If there are paired devices - if (pairedDevices.size() > 0) { - // Loop through paired devices - for (BluetoothDevice device : pairedDevices) { - // Add the name and address to an array adapter to show in a ListView - //mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); - Log.d(TAG, "Paired device: " + device.getName()); - if(device.getName().compareTo(DEVICE_NAME) == 0) { - openTelmetryBluetooth(device); - openTelmetryBluetooth(device); - } - } - } - - } - - private void openTelmetryBluetooth(BluetoothDevice device) { - Log.d(TAG, "Opening conncetion to " + device.getName()); - socket = null; - connected = false; - try { - socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID); - } catch (IOException e) { - Log.e(TAG,"Unable to create Rfcomm socket"); - //e.printStackTrace(); - } - - mBluetoothAdapter.cancelDiscovery(); - - try { - socket.connect(); - } - catch (IOException e) { - Log.e(TAG,"Unable to connect to requested device", e); - try { - socket.close(); - } catch (IOException e2) { - //Log.e(TAG, "unable to close() socket during connection failure", e2); - } - return; - } - - connected = true; - - try { - uavTalk = new UAVTalk(socket.getInputStream(), socket.getOutputStream(), objMngr); - } catch (IOException e) { - Log.e(TAG,"Error starting UAVTalk"); - // TODO Auto-generated catch block - //e.printStackTrace(); - return; - } - - Thread inputStream = uavTalk.getInputProcessThread(); - inputStream.start(); - - Telemetry tel = new Telemetry(uavTalk, objMngr); - TelemetryMonitor mon = new TelemetryMonitor(objMngr,tel); - - } } From 5e2c2a0ec3868f5e3d61f8c5e927cf93de99fbe8 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 19 Mar 2011 10:09:35 -0500 Subject: [PATCH 036/284] Clean up the logging somewhat --- .../androidgcs/OPTelemetryService.java | 62 ++++++++++++++++--- .../openpilot/uavtalk/TelemetryMonitor.java | 31 +++++----- flight/Revolution/Makefile.osx | 5 +- 3 files changed, 72 insertions(+), 26 deletions(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 2994be6d2..5a48bbc05 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -6,8 +6,14 @@ import org.openpilot.uavtalk.UAVObjectManager; import org.openpilot.uavtalk.UAVTalk; import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.app.Service; +import android.content.Context; import android.content.Intent; +import android.net.Uri; +import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.util.Log; @@ -18,10 +24,16 @@ public class OPTelemetryService extends Service { public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; + final int DISCONNECT_MESSAGE = 0; + final int CONNECT_MESSAGE = 1; + final int CONNECT_FAILED_MESSAGE = 2; + private UAVObjectManager objMngr; private UAVTalk uavTalk; private Telemetry tel; private TelemetryMonitor mon; + + private Handler handler; @Override public IBinder onBind(Intent arg0) { @@ -46,22 +58,38 @@ public class OPTelemetryService extends Service { private final Runnable telemetryRunnable = new Runnable() { public void run() { - Looper.prepare(); - if (DEBUG) Log.d(TAG, "Telemetry Thread started"); + + Looper.prepare(); objMngr = new UAVObjectManager(); UAVObjectsInitialize.register(objMngr); - + + postNotification(CONNECT_FAILED_MESSAGE, "Connecting"); BluetoothUAVTalk bt = new BluetoothUAVTalk(OPTelemetryService.this, BluetoothUAVTalk.DEVICE_NAME); - while(true) { + for( int i = 0; i < 10; i++ ) { if (DEBUG) Log.d(TAG, "Attempting Bluetooth Connection"); - if(! bt.getConnected() ) - bt.connect(objMngr); - else + + bt.connect(objMngr); + + if (DEBUG) Log.d(TAG, "Done attempting connection"); + if( bt.getConnected() ) break; - Looper.loop(); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + Log.e(TAG, "Thread interrupted while trying to connect"); + e.printStackTrace(); + return; + } } + if( ! bt.getConnected() ) { + postNotification(CONNECT_FAILED_MESSAGE, "Could not connect to UAV"); + return; + } + + postNotification(CONNECT_MESSAGE, "Connected to UAV port"); if (DEBUG) Log.d(TAG, "Connected via bluetooth"); @@ -73,13 +101,29 @@ public class OPTelemetryService extends Service { while(true) { if( !uavTalk.processInputStream() ) break; - Looper.loop(); } if (DEBUG) Log.d(TAG, "UAVTalk stream disconnected"); + postNotification(DISCONNECT_MESSAGE,"UAVTalk stream disconnected"); } }; + void postNotification(int id, String message) { + String ns = Context.NOTIFICATION_SERVICE; + NotificationManager mNManager = (NotificationManager) getSystemService(ns); + final Notification msg = new Notification(R.drawable.icon, message, System.currentTimeMillis()); + + Context context = getApplicationContext(); + CharSequence contentTitle = "OpenPilot"; + CharSequence contentText = message; + Intent msgIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://forums.openpilot.org")); + PendingIntent intent = PendingIntent.getActivity(this, 0, msgIntent, Intent.FLAG_ACTIVITY_NEW_TASK); + + msg.setLatestEventInfo(context, contentTitle, contentText, intent); + + mNManager.notify(id, msg); + } + public UAVObjectManager getObjMngr() { return objMngr; }; public UAVTalk getUavTalk() { return uavTalk; }; public Telemetry getTelemetry() { return tel; }; diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index a5885e7bc..9b4474d8e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -16,7 +16,10 @@ import android.util.Log; public class TelemetryMonitor { private static final String TAG = "TelemetryMonitor"; - + public static int LOGLEVEL = 0; + public static boolean WARN = LOGLEVEL > 1; + public static boolean DEBUG = LOGLEVEL > 0; + static final int STATS_UPDATE_PERIOD_MS = 4000; static final int STATS_CONNECT_PERIOD_MS = 1000; static final int CONNECTION_TIMEOUT_MS = 8000; @@ -57,7 +60,7 @@ public class TelemetryMonitor { */ public synchronized void startRetrievingObjects() { - Log.d(TAG, "Start retrieving objects"); + if (DEBUG) Log.d(TAG, "Start retrieving objects"); // Clear object queue queue.clear(); @@ -115,7 +118,7 @@ public class TelemetryMonitor { // If queue is empty return if ( queue.isEmpty() ) { - Log.d(TAG, "All objects retrieved: Connected Successfully"); + if (DEBUG) Log.d(TAG, "All objects retrieved: Connected Successfully"); //qxtLog->debug("Object retrieval completed"); //emit connected(); return; @@ -127,12 +130,12 @@ public class TelemetryMonitor { throw new Error("Got null object forom transaction queue"); } - Log.d(TAG, "Retrieving object: " + obj.getName()) ; + if (DEBUG) Log.d(TAG, "Retrieving object: " + obj.getName()) ; // Connect to object obj.addTransactionCompleted(new Observer() { public void update(Observable observable, Object data) { UAVObject.TransactionResult result = (UAVObject.TransactionResult) data; - Log.d(TAG,"Got transaction completed event from " + result.obj.getName() + " status: " + result.success); + if (DEBUG) Log.d(TAG,"Got transaction completed event from " + result.obj.getName() + " status: " + result.success); transactionCompleted(result.obj, result.success); } }); @@ -149,7 +152,7 @@ public class TelemetryMonitor { { //QMutexLocker locker(mutex); // Disconnect from sending object - Log.d(TAG,"transactionCompleted. Status: " + success); + if (DEBUG) Log.d(TAG,"transactionCompleted. Status: " + success); // TODO: Need to be able to disconnect signals //obj->disconnect(this); objPending = null; @@ -192,7 +195,7 @@ public class TelemetryMonitor { public synchronized void processStatsUpdates() { // Get telemetry stats - Log.d(TAG, "processStatsUpdates()"); + if (DEBUG) Log.d(TAG, "processStatsUpdates()"); Telemetry.TelemetryStats telStats = tel.getStats(); tel.resetStats(); @@ -232,7 +235,7 @@ public class TelemetryMonitor { UAVObjectField statusField = gcsStatsObj.getField("Status"); String oldStatus = new String((String) statusField.getValue()); - Log.d(TAG,"GCS: " + statusField.getValue() + " Flight: " + flightStatsObj.getField("Status").getValue()); + if (DEBUG) Log.d(TAG,"GCS: " + statusField.getValue() + " Flight: " + flightStatsObj.getField("Status").getValue()); if ( oldStatus.compareTo("Disconnected") == 0 ) { @@ -245,7 +248,7 @@ public class TelemetryMonitor { if ( ((String) flightStatsObj.getField("Status").getValue()).compareTo("HandshakeAck") == 0 ) { statusField.setValue("Connected"); - Log.d(TAG,"Connected" + statusField.toString()); + if (DEBUG) Log.d(TAG,"Connected" + statusField.toString()); } } else if ( oldStatus.compareTo("Connected") == 0 ) @@ -260,30 +263,26 @@ public class TelemetryMonitor { // Force telemetry update if not yet connected boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue()); - if(gcsStatusChanged) { - Log.d(TAG,"GCS Status changed"); - Log.d(TAG,"GCS: " + statusField.getValue() + " Flight: " + flightStatsObj.getField("Status").getValue()); - } boolean gcsConnected = ((String) statusField.getValue()).compareTo("Connected") == 0; boolean gcsDisconnected = ((String) statusField.getValue()).compareTo("Disconnected") == 0; boolean flightConnected = ((String) flightStatsObj.getField("Status").getValue()).compareTo("Connected") == 0; if ( !gcsConnected || !flightConnected ) { - Log.d(TAG,"Sending gcs status"); + if (DEBUG) Log.d(TAG,"Sending gcs status"); gcsStatsObj.updated(); } // Act on new connections or disconnections if (gcsConnected && gcsStatusChanged) { - Log.d(TAG,"Connection with the autopilot established"); + if (DEBUG) Log.d(TAG,"Connection with the autopilot established"); setPeriod(STATS_UPDATE_PERIOD_MS); startRetrievingObjects(); } if (gcsDisconnected && gcsStatusChanged) { - Log.d(TAG,"Trying to connect to the autopilot"); + if (DEBUG) Log.d(TAG,"Trying to connect to the autopilot"); setPeriod(STATS_CONNECT_PERIOD_MS); //emit disconnected(); } diff --git a/flight/Revolution/Makefile.osx b/flight/Revolution/Makefile.osx index 91bddb9a5..e2c8ea694 100644 --- a/flight/Revolution/Makefile.osx +++ b/flight/Revolution/Makefile.osx @@ -41,7 +41,7 @@ USE_BOOTLOADER ?= NO CODE_SOURCERY ?= NO # Toolchain prefix (i.e arm-elf- -> arm-elf-gcc.exe) -TCHAIN_PREFIX ?= "" +TCHAIN_PREFIX ?= /usr/local/android-ndk-r5/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi- # Remove command is different for Code Sourcery on Windows REMOVE_CMD ?= rm @@ -320,6 +320,9 @@ CFLAGS += -mtune=$(MCU) CFLAGS += $(CDEFS) CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I. +#CFLAGS += ARCH=arm +#CROSS_COMPILE=/usr/local/android-ndk-r5/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi- + CFLAGS += -fomit-frame-pointer ifeq ($(CODE_SOURCERY), YES) CFLAGS += -fpromote-loop-indices From 529b450f1dccc2d120d98b9fd8977b7e319689ed Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 19 Mar 2011 19:58:57 -0500 Subject: [PATCH 037/284] Common Activity class that binds to the Telemetry service --- .../androidgcs/ObjectManagerActivity.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java new file mode 100644 index 000000000..9f57796dc --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java @@ -0,0 +1,97 @@ +package org.openpilot.androidgcs; + +import org.openpilot.androidgcs.OPTelemetryService.LocalBinder; +import org.openpilot.androidgcs.OPTelemetryService.TelemTask; +import org.openpilot.uavtalk.UAVObjectManager; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.util.Log; + +public abstract class ObjectManagerActivity extends Activity { + + private final String TAG = "ObjectManagerActivity"; + private static int LOGLEVEL = 2; +// private static boolean WARN = LOGLEVEL > 1; + private static boolean DEBUG = LOGLEVEL > 0; + + UAVObjectManager objMngr; + boolean mBound = false; + boolean mConnected = false; + LocalBinder binder; + + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + BroadcastReceiver connectedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Log.d(TAG, "Received intent"); + TelemTask task; + if(intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_CONNECTED) == 0) { + + if(binder == null) + return; + if((task = binder.getTelemTask(0)) == null) + return; + objMngr = task.getObjectManager(); + mConnected = true; + onOPConnected(); + Log.d(TAG, "Connected()"); + } else if (intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_DISCONNECTED) == 0) { + objMngr = null; + mConnected = false; + onOPDisconnected(); + Log.d(TAG, "Disonnected()"); + } + } + }; + + IntentFilter filter = new IntentFilter(); + filter.addCategory(OPTelemetryService.INTENT_CATEGORY_GCS); + filter.addAction(OPTelemetryService.INTENT_ACTION_CONNECTED); + filter.addAction(OPTelemetryService.INTENT_ACTION_DISCONNECTED); + registerReceiver(connectedReceiver, filter); + } + + void onOPConnected() { + + } + + void onOPDisconnected() { + + } + + @Override + public void onStart() { + super.onStart(); + Intent intent = new Intent(this, OPTelemetryService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + /** Defines callbacks for service binding, passed to bindService() */ + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName arg0, IBinder service) { + // We've bound to LocalService, cast the IBinder and attempt to open a connection + if (DEBUG) Log.d(TAG,"Service bound"); + binder = (LocalBinder) service; + binder.openFakeConnection(); + } + + public void onServiceDisconnected(ComponentName name) { + mBound = false; + mConnected = false; + objMngr = null; + } + }; +} From 515a4c4fd1c6cc3a033c137f806d310ab7bdfda4 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 19 Mar 2011 20:00:12 -0500 Subject: [PATCH 038/284] Start of a widget for monitoring telemetry status --- androidgcs/AndroidManifest.xml | 43 +++++++++++++------ androidgcs/res/layout/telemetry_widget.xml | 7 +++ .../openpilot/androidgcs/TelemetryWidget.java | 31 +++++++++++++ 3 files changed, 67 insertions(+), 14 deletions(-) create mode 100644 androidgcs/res/layout/telemetry_widget.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index 6c89f2632..9a3d1dd25 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -1,23 +1,38 @@ - + package="org.openpilot.androidgcs" android:versionCode="1" + android:versionName="1.0"> + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/androidgcs/res/layout/telemetry_widget.xml b/androidgcs/res/layout/telemetry_widget.xml new file mode 100644 index 000000000..6af378104 --- /dev/null +++ b/androidgcs/res/layout/telemetry_widget.xml @@ -0,0 +1,7 @@ + + + + diff --git a/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java b/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java new file mode 100644 index 000000000..90ab80899 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java @@ -0,0 +1,31 @@ +package org.openpilot.androidgcs; + +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.widget.RemoteViews; + +public class TelemetryWidget extends AppWidgetProvider { + + private static boolean connected = false; + + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + final int N = appWidgetIds.length; + + // Perform this loop procedure for each App Widget that belongs to this provider + for (int i=0; i Date: Sat, 19 Mar 2011 20:01:01 -0500 Subject: [PATCH 039/284] Get rid of lots of warnings --- .../androidgcs/OPTelemetryService.java | 211 ++++++++++++++---- .../openpilot/androidgcs/ObjectBrowser.java | 83 ++----- .../openpilot/androidgcs/TelemetryWidget.java | 4 - .../src/org/openpilot/uavtalk/Telemetry.java | 1 - .../openpilot/uavtalk/TelemetryMonitor.java | 11 +- .../src/org/openpilot/uavtalk/UAVObject.java | 2 +- .../org/openpilot/uavtalk/UAVObjectField.java | 11 +- 7 files changed, 194 insertions(+), 129 deletions(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 5a48bbc05..557c3b256 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -2,6 +2,7 @@ package org.openpilot.androidgcs; import org.openpilot.uavtalk.Telemetry; import org.openpilot.uavtalk.TelemetryMonitor; +import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObjectManager; import org.openpilot.uavtalk.UAVTalk; import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; @@ -13,69 +14,192 @@ import android.app.Service; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Binder; import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; +import android.os.Message; +import android.os.Process; import android.util.Log; +import android.widget.Toast; public class OPTelemetryService extends Service { + + // Logging settings private final String TAG = "OPTElemetryService"; public static int LOGLEVEL = 2; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; - final int DISCONNECT_MESSAGE = 0; - final int CONNECT_MESSAGE = 1; - final int CONNECT_FAILED_MESSAGE = 2; - - private UAVObjectManager objMngr; - private UAVTalk uavTalk; - private Telemetry tel; - private TelemetryMonitor mon; - - private Handler handler; + // Intent category + public final static String INTENT_CATEGORY_GCS = "org.openpilot.intent.category.GCS"; - @Override - public IBinder onBind(Intent arg0) { - return null; - } + // Intent actions + public final static String INTENT_ACTION_CONNECTED = "org.openpilot.intent.action.CONNECTED"; + public final static String INTENT_ACTION_DISCONNECTED = "org.openpilot.intent.action.DISCONNECTED"; + + // Variables for local message handler thread + private Looper mServiceLooper; + private ServiceHandler mServiceHandler; + + // Message ids + final int MSG_START = 0; + final int MSG_CONNECT_BT = 1; + final int MSG_CONNECT_FAKE = 2; + final int MSG_TOAST = 100; + + private Thread activeTelem; + + private final IBinder mBinder = new LocalBinder(); + + private final class ServiceHandler extends Handler { + public ServiceHandler(Looper looper) { + super(looper); + } + @Override + public void handleMessage(Message msg) { + switch(msg.arg1) { + case MSG_START: + Toast.makeText(OPTelemetryService.this, "HERE", Toast.LENGTH_SHORT); + System.out.println("HERE"); + stopSelf(msg.arg2); + case MSG_CONNECT_BT: + activeTelem = new BTTelemetryThread(); + activeTelem.start(); + break; + case MSG_CONNECT_FAKE: + activeTelem = new FakeTelemetryThread(); + activeTelem.start(); + break; + case MSG_TOAST: + Toast.makeText(OPTelemetryService.this, (String) msg.obj, Toast.LENGTH_SHORT); + break; + default: + System.out.println(msg.toString()); + throw new Error("Invalid message"); + } + } + }; @Override public void onCreate() { - super.onCreate(); - - if (DEBUG) Log.d(TAG, "Telemetry Service started"); + // Low priority thread for message handling with service + HandlerThread thread = new HandlerThread("TelemetryServiceHandler", + Process.THREAD_PRIORITY_BACKGROUND); + thread.start(); - Thread telemetryThread = new Thread(telemetryRunnable); - telemetryThread.start(); - } + // Get the HandlerThread's Looper and use it for our Handler + mServiceLooper = thread.getLooper(); + mServiceHandler = new ServiceHandler(mServiceLooper); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Toast.makeText(this, "Telemetry service starting", Toast.LENGTH_SHORT).show(); + + System.out.println("Start"); + // For each start request, send a message to start a job and deliver the + // start ID so we know which request we're stopping when we finish the job + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = MSG_START; + msg.arg2 = startId; + mServiceHandler.sendMessage(msg); + + // If we get killed, after returning from here, restart + return START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } @Override public void onDestroy() { - super.onDestroy(); + Toast.makeText(this, "Telemetry service done", Toast.LENGTH_SHORT).show(); } + + public class LocalBinder extends Binder { + public TelemTask getTelemTask(int id) { + return (TelemTask) activeTelem; + } + public void openFakeConnection() { + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = MSG_CONNECT_FAKE; + mServiceHandler.sendMessage(msg); + } + }; - private final Runnable telemetryRunnable = new Runnable() { + public void toastMessage(String msgText) { + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = MSG_TOAST; + msg.obj = msgText; + mServiceHandler.sendMessage(msg); + } + + public interface TelemTask { + public UAVObjectManager getObjectManager(); + }; + + // Fake class for testing, simply emits periodic updates on + private class FakeTelemetryThread extends Thread implements TelemTask { + private UAVObjectManager objMngr; + public UAVObjectManager getObjectManager() { return objMngr; }; + + FakeTelemetryThread() { + objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + } + + public void run() { + System.out.println("Runnin fake thread"); + + Intent intent = new Intent(); + intent.setAction(INTENT_ACTION_CONNECTED); + sendBroadcast(intent,null); + + //toastMessage("Started fake telemetry thread"); + UAVDataObject systemStats = (UAVDataObject) objMngr.getObject("SystemStats"); + while(true) { + systemStats.updated(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + break; + } + } + } + } + private class BTTelemetryThread extends Thread implements TelemTask { + + private UAVObjectManager objMngr; + private UAVTalk uavTalk; + private Telemetry tel; + //private TelemetryMonitor mon; + + public UAVObjectManager getObjectManager() { return objMngr; }; + + BTTelemetryThread() { + objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + } public void run() { if (DEBUG) Log.d(TAG, "Telemetry Thread started"); Looper.prepare(); - - objMngr = new UAVObjectManager(); - UAVObjectsInitialize.register(objMngr); - - postNotification(CONNECT_FAILED_MESSAGE, "Connecting"); + BluetoothUAVTalk bt = new BluetoothUAVTalk(OPTelemetryService.this, BluetoothUAVTalk.DEVICE_NAME); for( int i = 0; i < 10; i++ ) { if (DEBUG) Log.d(TAG, "Attempting Bluetooth Connection"); - + bt.connect(objMngr); - + if (DEBUG) Log.d(TAG, "Done attempting connection"); if( bt.getConnected() ) break; - + try { Thread.sleep(1000); } catch (InterruptedException e) { @@ -85,17 +209,15 @@ public class OPTelemetryService extends Service { } } if( ! bt.getConnected() ) { - postNotification(CONNECT_FAILED_MESSAGE, "Could not connect to UAV"); return; } - - postNotification(CONNECT_MESSAGE, "Connected to UAV port"); - + + if (DEBUG) Log.d(TAG, "Connected via bluetooth"); - + uavTalk = bt.getUavtalk(); tel = new Telemetry(uavTalk, objMngr); - mon = new TelemetryMonitor(objMngr,tel); + new TelemetryMonitor(objMngr,tel); if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop"); while(true) { @@ -103,30 +225,23 @@ public class OPTelemetryService extends Service { break; } if (DEBUG) Log.d(TAG, "UAVTalk stream disconnected"); - postNotification(DISCONNECT_MESSAGE,"UAVTalk stream disconnected"); } - + }; - + void postNotification(int id, String message) { String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNManager = (NotificationManager) getSystemService(ns); final Notification msg = new Notification(R.drawable.icon, message, System.currentTimeMillis()); - + Context context = getApplicationContext(); CharSequence contentTitle = "OpenPilot"; CharSequence contentText = message; Intent msgIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://forums.openpilot.org")); PendingIntent intent = PendingIntent.getActivity(this, 0, msgIntent, Intent.FLAG_ACTIVITY_NEW_TASK); - + msg.setLatestEventInfo(context, contentTitle, contentText, intent); - + mNManager.notify(id, msg); } - - public UAVObjectManager getObjMngr() { return objMngr; }; - public UAVTalk getUavTalk() { return uavTalk; }; - public Telemetry getTelemetry() { return tel; }; - public TelemetryMonitor getTelemetryMonitor() { return mon; }; - } diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index 6bb217930..48aa1cd10 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -1,42 +1,21 @@ package org.openpilot.androidgcs; -import java.io.IOException; import java.util.Observable; import java.util.Observer; -import java.util.Set; -import java.util.UUID; -import android.app.Activity; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothSocket; -import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.widget.TextView; import android.widget.ToggleButton; -import org.openpilot.androidgcs.*; -import org.openpilot.uavtalk.Telemetry; -import org.openpilot.uavtalk.TelemetryMonitor; import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVTalk; -import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; -public class ObjectBrowser extends Activity { - +public class ObjectBrowser extends ObjectManagerActivity { + private final String TAG = "ObjectBrower"; - private final String DEVICE_NAME = "RN42-222D"; - private final int REQUEST_ENABLE_BT = 0; - private UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); - BluetoothAdapter mBluetoothAdapter; - BluetoothSocket socket; boolean connected; - UAVObjectManager objMngr; - UAVTalk uavTalk; - + final Handler uavobjHandler = new Handler(); final Runnable updateText = new Runnable() { public void run() { @@ -44,9 +23,9 @@ public class ObjectBrowser extends Activity { button.setChecked(!connected); Log.d(TAG,"HERE" + connected); - + TextView text = (TextView) findViewById(R.id.textView1); - + UAVObject obj1 = objMngr.getObject("SystemStats"); UAVObject obj2 = objMngr.getObject("AttitudeRaw"); UAVObject obj3 = objMngr.getObject("AttitudeActual"); @@ -57,52 +36,30 @@ public class ObjectBrowser extends Activity { Log.d(TAG,"And here"); text.setText(obj1.toString() + "\n" + obj2.toString() + "\n" + obj3.toString() + "\n" + obj4.toString() ); - + } }; - - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main); - - Log.d(TAG, "Launching Object Browser"); - Log.d(TAG, "Start OP Telemetry Service"); - startService( new Intent( this, OPTelemetryService.class ) ); - - objMngr = new UAVObjectManager(); - UAVObjectsInitialize.register(objMngr); + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } + + @Override + void onOPConnected() { + // Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT); + Log.d(TAG, "onOPConnected()"); UAVObject obj = objMngr.getObject("SystemStats"); + Log.d(TAG, ((Boolean) (obj == null)).toString()); if(obj != null) obj.addUpdatedObserver(new Observer() { public void update(Observable observable, Object data) { uavobjHandler.post(updateText); } }); - obj = objMngr.getObject("AttitudeRaw"); - if(obj != null) - obj.addUpdatedObserver(new Observer() { - public void update(Observable observable, Object data) { - uavobjHandler.post(updateText); - } - }); - obj = objMngr.getObject("AttitudeActual"); - if(obj != null) - obj.addUpdatedObserver(new Observer() { - public void update(Observable observable, Object data) { - uavobjHandler.post(updateText); - } - }); - obj = objMngr.getObject("SystemAlarms"); - if(obj != null) - obj.addUpdatedObserver(new Observer() { - public void update(Observable observable, Object data) { - uavobjHandler.post(updateText); - } - }); - } - + + } } diff --git a/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java b/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java index 90ab80899..d316526ef 100644 --- a/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java +++ b/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java @@ -3,14 +3,10 @@ package org.openpilot.androidgcs; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; -import android.content.Intent; -import android.os.Bundle; import android.widget.RemoteViews; public class TelemetryWidget extends AppWidgetProvider { - private static boolean connected = false; - public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N = appWidgetIds.length; diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index c754c8329..1395a5c08 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -630,7 +630,6 @@ public class Telemetry { /** * Private variables */ - private TelemetryStats stats; private UAVObjectManager objMngr; private UAVTalk utalk; private UAVObject gcsStatsObj; diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index 9b4474d8e..7208181ad 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -8,9 +8,6 @@ import java.util.Observer; import java.util.Timer; import java.util.TimerTask; -import org.openpilot.uavtalk.uavobjects.FlightTelemetryStats; -import org.openpilot.uavtalk.uavobjects.GCSTelemetryStats; - import android.util.Log; public class TelemetryMonitor { @@ -26,7 +23,7 @@ public class TelemetryMonitor { private UAVObjectManager objMngr; private Telemetry tel; - private UAVObject objPending; +// private UAVObject objPending; private UAVObject gcsStatsObj; private UAVObject flightStatsObj; private Timer periodicTask; @@ -38,7 +35,7 @@ public class TelemetryMonitor { { this.objMngr = objMngr; this.tel = tel; - this.objPending = null; +// this.objPending = null; queue = new ArrayList(); // Get stats objects @@ -142,7 +139,7 @@ public class TelemetryMonitor { // Request update tel.updateRequested(obj); - objPending = obj; +// objPending = obj; } /** @@ -155,7 +152,7 @@ public class TelemetryMonitor { if (DEBUG) Log.d(TAG,"transactionCompleted. Status: " + success); // TODO: Need to be able to disconnect signals //obj->disconnect(this); - objPending = null; +// objPending = null; if(!success) { Log.e(TAG, "Transaction failed: " + obj.getName() + " sending again."); diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index ba3bf1ae3..940b076a5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -64,7 +64,7 @@ public abstract class UAVObject { if(manually) updatedManual(); } - void updated() { updated(true); }; + public void updated() { updated(true); }; private CallbackListener unpackedListeners = new CallbackListener(this); public void addUnpackedObserver(Observer o) { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index de2059e90..78ad70630 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -1,6 +1,5 @@ package org.openpilot.uavtalk; -import java.io.Serializable; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; @@ -91,7 +90,8 @@ public class UAVObjectField { * @param dataOut * @return the number of bytes added **/ - public synchronized int pack(ByteBuffer dataOut) { + @SuppressWarnings("unchecked") + public synchronized int pack(ByteBuffer dataOut) { // Pack each element in output buffer dataOut.order(ByteOrder.LITTLE_ENDIAN); switch (type) @@ -152,7 +152,8 @@ public class UAVObjectField { return getNumBytes(); } - public synchronized int unpack(ByteBuffer dataIn) { + @SuppressWarnings("unchecked") + public synchronized int unpack(ByteBuffer dataIn) { // Unpack each element from input buffer dataIn.order(ByteOrder.LITTLE_ENDIAN); switch (type) @@ -436,9 +437,9 @@ public class UAVObjectField { } } - public String toString() { + public String toString() { String sout = new String(); - sout += name + ": " + ((List) data).toString() + " (" + units + ")\n"; + sout += name + ": " + data.toString() + " (" + units + ")\n"; return sout; } From e2a90b2265d721e1fc28f76b6630dfa979dc5fd8 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 20 Mar 2011 06:09:06 -0500 Subject: [PATCH 040/284] Added some missing files. Improved object browser to use ListView. ExpandableListView next. --- androidgcs/Doc/.AndroidArchitecture.txt.swp | Bin 0 -> 12288 bytes androidgcs/Doc/AndroidArchitecture.txt | 31 +++++++ androidgcs/res/layout/main.xml | 17 ++-- androidgcs/res/layout/object_view.xml | 7 ++ androidgcs/res/menu/options_menu.xml | 6 ++ androidgcs/res/values/strings.xml | 4 + androidgcs/res/xml/telemetry_widget_info.xml | 9 ++ .../androidgcs/OPTelemetryService.java | 69 +++++++++++--- .../openpilot/androidgcs/ObjectBrowser.java | 84 +++++++++++++----- .../androidgcs/ObjectManagerActivity.java | 1 - .../openpilot/uavtalk/TelemetryMonitor.java | 30 +++++-- .../src/org/openpilot/uavtalk/UAVTalk.java | 3 +- 12 files changed, 202 insertions(+), 59 deletions(-) create mode 100644 androidgcs/Doc/.AndroidArchitecture.txt.swp create mode 100644 androidgcs/Doc/AndroidArchitecture.txt create mode 100644 androidgcs/res/layout/object_view.xml create mode 100644 androidgcs/res/menu/options_menu.xml create mode 100644 androidgcs/res/xml/telemetry_widget_info.xml diff --git a/androidgcs/Doc/.AndroidArchitecture.txt.swp b/androidgcs/Doc/.AndroidArchitecture.txt.swp new file mode 100644 index 0000000000000000000000000000000000000000..167a072526a8207b396d71d6dd7d3e7a417cba19 GIT binary patch literal 12288 zcmeHNzmFS56rMwnA3z`iK>^J`id>>QJ0S%T4RS8dVU#03?7Kh}jd#cP-0jXRGqdLy zB_JeP;2%IhK?4;OL^LQ=G-;^`1>rxSqu_h9yY}UZv?yp!`Qr2bn0fDe-}~N1+2N_J z-UffYb%x>RC}UrI^6`eazqIt*H;ip3#(SgBo~CmT`FUIA`E0F~nM7m{xr}`{U$A}N zBxNqOckRp8jIGFXrN`|{h18c-W_(-d)EbqJ6GxY}JJr{YO(x3A#FtjK{0;xG&EmPp zKxAOSK2dF}KmI(Y2WSNQYKZ7$Bo-y#E%fyh8)ATkgchzvvqA_I|u|2+e~ zSYjU`%g5?WFVvq)`#$Th@gp)28Hfx-1|kEIfyh8)ATkgchzvvqA_I|uN00%LGPe3S zW8w(}kN^K~{{8>wvy6QWdgNH7@GiVz&YUWBaGb!egqV740sWE0XPKw z{4`@0=mO_~lfb>F82cRP0!M*ofjdt!whJr+$AP~NGj<=i3)}=&fZq=>_6u+am;%ed z%fL&(-Ghw%0DKSJ0&W6r;2>}SxP5@J?|^TC1b7#?2Al(q0{?)6KY)9{ufSKpm%uIH zCJ;D!1Zx~ajtoQw{v!rDLzO8%3N*zup~i9E8`N zJjt(=($1ROmC@XJ;Y%0Jt%)q-ixtDMb+s$`1g~IalEU^A$uAAJvEPQ!Vk~WlMhc{| z+1bJ!d>}KKOOH)@=af#RWz3aDVXT*Fi}iSFw8t_^?}Wu_0x0t`OR*ESqfJcV5uM{= zXiCqg6IJbi16DEy2JlW;QP7eDT)l4K9sH7M5==$7f5Rz69N4eGEt)$7oa0aK>dR<<+V;*EZhkKkq=f0;#uJWRh7h|Lk)@Mia*XtyY#&& zZ&P+!eJnl81(K?`_p@bp0t|FA4-tfozxuZv%GMYV5G@j`J6 zy5|AVh8{o$Lu5PWw$TtDS(68fK+`@G=y$Jf_13zT3-nFZvp2l7T4daWb|zs;NP;A2 z<(RC7`h?s^4AJ|}YlBe!Esc)S*+4( zVXz0Jx=DhbcZh^O(6Wiip%Xq8!7NiU9#D!uWPYRr+*Jk6mt6^O5H9GbdN-7=fY?G2 zKqZt<w>-1wnI&T9)>r`IggCxCM`qiRMFH(r;p=PLhmUW2tq;~>J3K{ zE@~y3gMwQW(#?=$4srAA~;j1tIlNGZG^8G*3NuIRz$>-_K0|9#2o7)E zy0$aPj`Sd1^D6_g-Fh==!;D$w8{K}tv)<*GJN z%~W%*a@k^KkwQ03=yfqrhy(^WMiQ{XP&Dw5tf{9ObFD)iG$zf~s?3mXt&3{yFhFYt zLUMI{W)!}SFonYu2;1PDnASejO27?lH&?XqC1*CKB2< zJRd2H4ssgICx|G+fTt48MX*tgmL`RI(p33h$kce^=a=@Oe8i7VUSI1!c$Bh$@MKO} z)yAt)QxAH8;9x{Ma{lmmg0?`p(M<5NMIcQCRwfb;P%hM!HY3^6{aAa>5fmB5hHtb? zVZnXGHoT4&hb!U1?v2pE^H6zZEvPGvF2pr&X_;cKVK49(?j|=txdk7|DGdht+4F>0 I9l+o0U$ht(TmS$7 literal 0 HcmV?d00001 diff --git a/androidgcs/Doc/AndroidArchitecture.txt b/androidgcs/Doc/AndroidArchitecture.txt new file mode 100644 index 000000000..d9cdf2ada --- /dev/null +++ b/androidgcs/Doc/AndroidArchitecture.txt @@ -0,0 +1,31 @@ +------- TELEMETRY --------- +The Telemetry system has been implemented, and is composed of a few +major components: + +Telemetry.java - receives command to transmit objects through telemetry and +also emits notification when transactions are completed + +TelemetryMonitor.java - monitors the FlightTelemetryStats and GCSTelemetryStats +to establish when a working connection is in place. Also initiates downloading +all the objects on a new connection. + +UAVObjectManager.java - the central data store. The data is actually stored +within objects, but this maintains the handles to all of them. + +UAVTalk.java - the actual communication layer. Can packetize an object and +insert into stream and process the incoming stream and update objects +accordingly. + +---- MESSAGE PASSING ---- +The current implementation/analog to the slots/sockets in QT are Observers +which are registered as added to an Observable. This is used extensibly within +the telemetry system. I will continue to use this _within_ the Telemetry +module so it doesn't depend on any android features. + +In android there is a constraint that UI operations should all be done from the +UI thread. The most common way to do this is for the UI object (such as +Activity) to instantiate a Handler to which messages or runnables are posted. + +So for external objects they will register a runnable somehow... + + diff --git a/androidgcs/res/layout/main.xml b/androidgcs/res/layout/main.xml index 9e5f90add..880e276ff 100644 --- a/androidgcs/res/layout/main.xml +++ b/androidgcs/res/layout/main.xml @@ -1,13 +1,6 @@ - - - - - + + + diff --git a/androidgcs/res/layout/object_view.xml b/androidgcs/res/layout/object_view.xml new file mode 100644 index 000000000..fdf5a0bae --- /dev/null +++ b/androidgcs/res/layout/object_view.xml @@ -0,0 +1,7 @@ + + + diff --git a/androidgcs/res/menu/options_menu.xml b/androidgcs/res/menu/options_menu.xml new file mode 100644 index 000000000..db86aa670 --- /dev/null +++ b/androidgcs/res/menu/options_menu.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index 52fa56534..8daa0ec36 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -1,4 +1,8 @@ OpenPilot GCS + Settings + Connect + Disconnect + OpenPilot Object Browser diff --git a/androidgcs/res/xml/telemetry_widget_info.xml b/androidgcs/res/xml/telemetry_widget_info.xml new file mode 100644 index 000000000..f2ced6645 --- /dev/null +++ b/androidgcs/res/xml/telemetry_widget_info.xml @@ -0,0 +1,9 @@ + + + android:minWidth="294dp" + android:minHeight="72dp" + android:updatePeriodMillis="86400000" + android:initialLayout="@layout/telemetry_widget"> + + diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 557c3b256..7b3030d4f 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -1,5 +1,8 @@ package org.openpilot.androidgcs; +import java.util.Observable; +import java.util.Observer; + import org.openpilot.uavtalk.Telemetry; import org.openpilot.uavtalk.TelemetryMonitor; import org.openpilot.uavtalk.UAVDataObject; @@ -27,7 +30,7 @@ import android.widget.Toast; public class OPTelemetryService extends Service { // Logging settings - private final String TAG = "OPTElemetryService"; + private final String TAG = "OPTelemetryService"; public static int LOGLEVEL = 2; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; @@ -44,10 +47,13 @@ public class OPTelemetryService extends Service { private ServiceHandler mServiceHandler; // Message ids - final int MSG_START = 0; - final int MSG_CONNECT_BT = 1; - final int MSG_CONNECT_FAKE = 2; - final int MSG_TOAST = 100; + static final int MSG_START = 0; + static final int MSG_CONNECT_BT = 1; + static final int MSG_CONNECT_FAKE = 2; + static final int MSG_DISCONNECT = 3; + static final int MSG_TOAST = 100; + + private boolean terminate = false; private Thread activeTelem; @@ -65,12 +71,28 @@ public class OPTelemetryService extends Service { System.out.println("HERE"); stopSelf(msg.arg2); case MSG_CONNECT_BT: + terminate = false; activeTelem = new BTTelemetryThread(); activeTelem.start(); break; case MSG_CONNECT_FAKE: + terminate = false; activeTelem = new FakeTelemetryThread(); activeTelem.start(); + break; + case MSG_DISCONNECT: + terminate = true; + try { + activeTelem.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + activeTelem = null; + + Intent intent = new Intent(); + intent.setAction(INTENT_ACTION_DISCONNECTED); + sendBroadcast(intent,null); + break; case MSG_TOAST: Toast.makeText(OPTelemetryService.this, (String) msg.obj, Toast.LENGTH_SHORT); @@ -129,8 +151,18 @@ public class OPTelemetryService extends Service { msg.arg1 = MSG_CONNECT_FAKE; mServiceHandler.sendMessage(msg); } + public void openBTConnection() { + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = MSG_CONNECT_BT; + mServiceHandler.sendMessage(msg); + } + public void stopConnection() { + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = MSG_DISCONNECT; + mServiceHandler.sendMessage(msg); + } }; - + public void toastMessage(String msgText) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = MSG_TOAST; @@ -151,17 +183,17 @@ public class OPTelemetryService extends Service { objMngr = new UAVObjectManager(); UAVObjectsInitialize.register(objMngr); } - + public void run() { - System.out.println("Runnin fake thread"); + System.out.println("Running fake thread"); Intent intent = new Intent(); intent.setAction(INTENT_ACTION_CONNECTED); sendBroadcast(intent,null); - + //toastMessage("Started fake telemetry thread"); UAVDataObject systemStats = (UAVDataObject) objMngr.getObject("SystemStats"); - while(true) { + while( !terminate ) { systemStats.updated(); try { Thread.sleep(1000); @@ -176,7 +208,7 @@ public class OPTelemetryService extends Service { private UAVObjectManager objMngr; private UAVTalk uavTalk; private Telemetry tel; - //private TelemetryMonitor mon; + private TelemetryMonitor mon; public UAVObjectManager getObjectManager() { return objMngr; }; @@ -217,10 +249,21 @@ public class OPTelemetryService extends Service { uavTalk = bt.getUavtalk(); tel = new Telemetry(uavTalk, objMngr); - new TelemetryMonitor(objMngr,tel); + mon = new TelemetryMonitor(objMngr,tel); + mon.addObserver(new Observer() { + public void update(Observable arg0, Object arg1) { + System.out.println("Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated()); + if(mon.getConnected() /*&& mon.getObjectsUpdated()*/) { + Intent intent = new Intent(); + intent.setAction(INTENT_ACTION_CONNECTED); + sendBroadcast(intent,null); + } + } + }); + if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop"); - while(true) { + while( !terminate ) { if( !uavTalk.processInputStream() ) break; } diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index 48aa1cd10..f68e839c1 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -1,42 +1,67 @@ package org.openpilot.androidgcs; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; import java.util.Observable; import java.util.Observer; +import android.database.DataSetObserver; import android.os.Bundle; import android.os.Handler; import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ExpandableListAdapter; +import android.widget.ExpandableListView; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.SimpleExpandableListAdapter; import android.widget.TextView; -import android.widget.ToggleButton; +import android.widget.Toast; +import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObject; public class ObjectBrowser extends ObjectManagerActivity { + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.menu_connect: + binder.openBTConnection(); + return true; + case R.id.menu_disconnect: + binder.stopConnection(); + updateText.run(); + return true; + case R.id.menu_settings: + return true; + default: + return super.onOptionsItemSelected(item); + } + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.options_menu, menu); + return true; + } + private final String TAG = "ObjectBrower"; boolean connected; final Handler uavobjHandler = new Handler(); final Runnable updateText = new Runnable() { public void run() { - ToggleButton button = (ToggleButton) findViewById(R.id.toggleButton1); - button.setChecked(!connected); - - Log.d(TAG,"HERE" + connected); - - TextView text = (TextView) findViewById(R.id.textView1); - - UAVObject obj1 = objMngr.getObject("SystemStats"); - UAVObject obj2 = objMngr.getObject("AttitudeRaw"); - UAVObject obj3 = objMngr.getObject("AttitudeActual"); - UAVObject obj4 = objMngr.getObject("SystemAlarms"); - - if(obj1 == null || obj2 == null || obj3 == null || obj4 == null) - return; - - Log.d(TAG,"And here"); - text.setText(obj1.toString() + "\n" + obj2.toString() + "\n" + obj3.toString() + "\n" + obj4.toString() ); - + Log.d(TAG,"Update"); + update(); } }; @@ -44,16 +69,15 @@ public class ObjectBrowser extends ObjectManagerActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.main); + setContentView(R.layout.main); } @Override void onOPConnected() { - // Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT); + Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT); Log.d(TAG, "onOPConnected()"); - + UAVObject obj = objMngr.getObject("SystemStats"); - Log.d(TAG, ((Boolean) (obj == null)).toString()); if(obj != null) obj.addUpdatedObserver(new Observer() { public void update(Observable observable, Object data) { @@ -62,4 +86,18 @@ public class ObjectBrowser extends ObjectManagerActivity { }); } + + public void update() { + List> allobjects = objMngr.getDataObjects(); + List linearized = new ArrayList(); + ListIterator> li = allobjects.listIterator(); + while(li.hasNext()) { + linearized.addAll(li.next()); + } + + ArrayAdapter adapter = new ArrayAdapter(this,R.layout.object_view, linearized); + ListView objects = (ListView) findViewById(R.id.object_list); + objects.setAdapter(adapter); + + } } diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java index 9f57796dc..12a072de7 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java @@ -85,7 +85,6 @@ public abstract class ObjectManagerActivity extends Activity { // We've bound to LocalService, cast the IBinder and attempt to open a connection if (DEBUG) Log.d(TAG,"Service bound"); binder = (LocalBinder) service; - binder.openFakeConnection(); } public void onServiceDisconnected(ComponentName name) { diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index 7208181ad..daedcc85b 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -10,10 +10,10 @@ import java.util.TimerTask; import android.util.Log; -public class TelemetryMonitor { +public class TelemetryMonitor extends Observable{ private static final String TAG = "TelemetryMonitor"; - public static int LOGLEVEL = 0; + public static int LOGLEVEL = 2; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; @@ -31,6 +31,12 @@ public class TelemetryMonitor { private long lastUpdateTime; private List queue; + private boolean connected = false; + private boolean objects_updated = false; + + public boolean getConnected() { return connected; }; + public boolean getObjectsUpdated() { return objects_updated; }; + public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel) { this.objMngr = objMngr; @@ -116,8 +122,9 @@ public class TelemetryMonitor { if ( queue.isEmpty() ) { if (DEBUG) Log.d(TAG, "All objects retrieved: Connected Successfully"); - //qxtLog->debug("Object retrieval completed"); - //emit connected(); + objects_updated = true; + setChanged(); + notifyObservers(); return; } // Get next object from the queue @@ -260,9 +267,9 @@ public class TelemetryMonitor { // Force telemetry update if not yet connected boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue()); - boolean gcsConnected = ((String) statusField.getValue()).compareTo("Connected") == 0; - boolean gcsDisconnected = ((String) statusField.getValue()).compareTo("Disconnected") == 0; - boolean flightConnected = ((String) flightStatsObj.getField("Status").getValue()).compareTo("Connected") == 0; + boolean gcsConnected = statusField.getValue().equals("Connected"); + boolean gcsDisconnected = statusField.getValue().equals("Disconnected"); + boolean flightConnected = flightStatsObj.getField("Status").equals("Connected"); if ( !gcsConnected || !flightConnected ) { @@ -275,14 +282,21 @@ public class TelemetryMonitor { { if (DEBUG) Log.d(TAG,"Connection with the autopilot established"); setPeriod(STATS_UPDATE_PERIOD_MS); + connected = true; + objects_updated = false; startRetrievingObjects(); + setChanged(); } if (gcsDisconnected && gcsStatusChanged) { if (DEBUG) Log.d(TAG,"Trying to connect to the autopilot"); setPeriod(STATS_CONNECT_PERIOD_MS); - //emit disconnected(); + connected = false; + objects_updated = false; + setChanged(); } + notifyObservers(); + } private void setPeriod(int ms) { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 8671cdef9..39c1f6ee7 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -197,8 +197,7 @@ public class UAVTalk extends Observable { return false; } - // System.out.println("Received byte " + val + " in state + " + - // rxState); + //System.out.println("Received byte " + val + " in state + " + rxState); processInputByte(val); return true; } From 68e0e27f75ed64fc3929fed6b1135d64faef5900 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 20 Mar 2011 21:34:03 -0500 Subject: [PATCH 041/284] Added a home page, added an option to select connection type. Made the ListView adapter trigger updates on the data. --- androidgcs/AndroidManifest.xml | 8 ++- androidgcs/Doc/AndroidArchitecture.txt | 39 +++++++++++ androidgcs/res/layout/gcs_home.xml | 7 ++ androidgcs/res/values/arrays.xml | 15 +++++ androidgcs/res/values/strings.xml | 9 ++- androidgcs/res/xml/preferences.xml | 12 ++++ .../org/openpilot/androidgcs/HomePage.java | 23 +++++++ .../androidgcs/OPTelemetryService.java | 39 ++++++----- .../openpilot/androidgcs/ObjectBrowser.java | 65 ++++++++----------- .../androidgcs/ObjectManagerActivity.java | 28 ++++++++ .../org/openpilot/androidgcs/Preferences.java | 12 ++++ 11 files changed, 201 insertions(+), 56 deletions(-) create mode 100644 androidgcs/res/layout/gcs_home.xml create mode 100644 androidgcs/res/values/arrays.xml create mode 100644 androidgcs/res/xml/preferences.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/HomePage.java create mode 100644 androidgcs/src/org/openpilot/androidgcs/Preferences.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index 9a3d1dd25..a791d0fbb 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -10,17 +10,23 @@ - + + + + + + + diff --git a/androidgcs/Doc/AndroidArchitecture.txt b/androidgcs/Doc/AndroidArchitecture.txt index d9cdf2ada..0a17a8dfa 100644 --- a/androidgcs/Doc/AndroidArchitecture.txt +++ b/androidgcs/Doc/AndroidArchitecture.txt @@ -16,6 +16,11 @@ UAVTalk.java - the actual communication layer. Can packetize an object and insert into stream and process the incoming stream and update objects accordingly. +** Threading +Currently object updates run within the thread of the function that called +update. This should be changed so that it adds a message to the Telemetry +thread which will then send on its own time. + ---- MESSAGE PASSING ---- The current implementation/analog to the slots/sockets in QT are Observers which are registered as added to an Observable. This is used extensibly within @@ -28,4 +33,38 @@ Activity) to instantiate a Handler to which messages or runnables are posted. So for external objects they will register a runnable somehow... +--- TELEMETRY SERVICE --- +The telemetry connection will be maintained by a service separate from the the +main activity(s). Although it is a bit unusual, the service will support being +started and stopped, as well as being bound. Binding will be required to get +access to the Object Manager. +In addition, to make it forward looking, the start intent can specify a +connection to open. This will allow the service in future to monitor multiple +connections. + +The service will destroy itself only when all active connections disappear and +all activies are unbound. + +It will also handle any logging desired (I think). + +There will be a primary message handler thread. This thread will separately +launch telemetry threads when required. + +The service should send broadcast intents whenever a connection is estabilished +or dropped. + +I dont think the service should have the options about which UAVs are +supported. + +** Telemetry IBinder +*** Give handle to the ObjectManager for each UAV +*** Call disconnect +*** Query conncetion status + +--- TELEMETRY WIDGET --- +Listens for conncet/disconnect intents + +Also show if service is running? + +Ability to launch service? diff --git a/androidgcs/res/layout/gcs_home.xml b/androidgcs/res/layout/gcs_home.xml new file mode 100644 index 000000000..e6f4ea567 --- /dev/null +++ b/androidgcs/res/layout/gcs_home.xml @@ -0,0 +1,7 @@ + + + + diff --git a/androidgcs/res/values/arrays.xml b/androidgcs/res/values/arrays.xml new file mode 100644 index 000000000..18ee52298 --- /dev/null +++ b/androidgcs/res/values/arrays.xml @@ -0,0 +1,15 @@ + + + + None + Fake + Bluetooth + Network + + + 0 + 1 + 2 + 3 + + \ No newline at end of file diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index 8daa0ec36..e9b66a312 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -1,8 +1,13 @@ - OpenPilot GCS + OpenPilot GCS Home + OpenPilot Object Browser Settings Connect Disconnect - OpenPilot Object Browser + Settings + Automatically Connect + Connection Type + Bluetooth + Select the connection method diff --git a/androidgcs/res/xml/preferences.xml b/androidgcs/res/xml/preferences.xml new file mode 100644 index 000000000..d731f59dd --- /dev/null +++ b/androidgcs/res/xml/preferences.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/androidgcs/src/org/openpilot/androidgcs/HomePage.java b/androidgcs/src/org/openpilot/androidgcs/HomePage.java new file mode 100644 index 000000000..478c7cdca --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/HomePage.java @@ -0,0 +1,23 @@ +package org.openpilot.androidgcs; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; + +public class HomePage extends ObjectManagerActivity { + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.gcs_home); + Button objectBrowser = (Button) findViewById(R.id.launch_object_browser); + objectBrowser.setOnClickListener(new OnClickListener() { + public void onClick(View arg0) { + startActivity(new Intent(HomePage.this, ObjectBrowser.class)); + } + }); + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 7b3030d4f..5af7c7d60 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -16,6 +16,7 @@ import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Binder; import android.os.Handler; @@ -24,6 +25,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Process; +import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; @@ -48,8 +50,7 @@ public class OPTelemetryService extends Service { // Message ids static final int MSG_START = 0; - static final int MSG_CONNECT_BT = 1; - static final int MSG_CONNECT_FAKE = 2; + static final int MSG_CONNECT = 1; static final int MSG_DISCONNECT = 3; static final int MSG_TOAST = 100; @@ -70,14 +71,22 @@ public class OPTelemetryService extends Service { Toast.makeText(OPTelemetryService.this, "HERE", Toast.LENGTH_SHORT); System.out.println("HERE"); stopSelf(msg.arg2); - case MSG_CONNECT_BT: + case MSG_CONNECT: terminate = false; - activeTelem = new BTTelemetryThread(); - activeTelem.start(); - break; - case MSG_CONNECT_FAKE: - terminate = false; - activeTelem = new FakeTelemetryThread(); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); + int connection_type = Integer.decode(prefs.getString("connection_type", "")); + switch(connection_type) { + case 0: // No connection + return; + case 1: + activeTelem = new FakeTelemetryThread(); + break; + case 2: + activeTelem = new BTTelemetryThread(); + break; + case 3: + throw new Error("Unsupported"); + } activeTelem.start(); break; case MSG_DISCONNECT: @@ -146,14 +155,9 @@ public class OPTelemetryService extends Service { public TelemTask getTelemTask(int id) { return (TelemTask) activeTelem; } - public void openFakeConnection() { + public void openConnection() { Message msg = mServiceHandler.obtainMessage(); - msg.arg1 = MSG_CONNECT_FAKE; - mServiceHandler.sendMessage(msg); - } - public void openBTConnection() { - Message msg = mServiceHandler.obtainMessage(); - msg.arg1 = MSG_CONNECT_BT; + msg.arg1 = MSG_CONNECT; mServiceHandler.sendMessage(msg); } public void stopConnection() { @@ -161,6 +165,9 @@ public class OPTelemetryService extends Service { msg.arg1 = MSG_DISCONNECT; mServiceHandler.sendMessage(msg); } + public boolean isConnected() { + return activeTelem != null; + } }; public void toastMessage(String msgText) { diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index f68e839c1..f3cc56d47 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -6,15 +6,20 @@ import java.util.ListIterator; import java.util.Observable; import java.util.Observer; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.database.DataSetObserver; import android.os.Bundle; import android.os.Handler; +import android.preference.PreferenceManager; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.Adapter; import android.widget.ArrayAdapter; import android.widget.ExpandableListAdapter; import android.widget.ExpandableListView; @@ -27,36 +32,13 @@ import android.widget.Toast; import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObject; -public class ObjectBrowser extends ObjectManagerActivity { - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch(item.getItemId()) { - case R.id.menu_connect: - binder.openBTConnection(); - return true; - case R.id.menu_disconnect: - binder.stopConnection(); - updateText.run(); - return true; - case R.id.menu_settings: - return true; - default: - return super.onOptionsItemSelected(item); - } - - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.options_menu, menu); - return true; - } +public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPreferenceChangeListener { private final String TAG = "ObjectBrower"; boolean connected; - + SharedPreferences prefs; + ArrayAdapter adapter; + final Handler uavobjHandler = new Handler(); final Runnable updateText = new Runnable() { public void run() { @@ -70,6 +52,8 @@ public class ObjectBrowser extends ObjectManagerActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); + prefs = PreferenceManager.getDefaultSharedPreferences(this); + prefs.registerOnSharedPreferenceChangeListener(this); } @Override @@ -77,6 +61,17 @@ public class ObjectBrowser extends ObjectManagerActivity { Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT); Log.d(TAG, "onOPConnected()"); + List> allobjects = objMngr.getDataObjects(); + List linearized = new ArrayList(); + ListIterator> li = allobjects.listIterator(); + while(li.hasNext()) { + linearized.addAll(li.next()); + } + + adapter = new ArrayAdapter(this,R.layout.object_view, linearized); + ListView objects = (ListView) findViewById(R.id.object_list); + objects.setAdapter(adapter); + UAVObject obj = objMngr.getObject("SystemStats"); if(obj != null) obj.addUpdatedObserver(new Observer() { @@ -88,16 +83,12 @@ public class ObjectBrowser extends ObjectManagerActivity { } public void update() { - List> allobjects = objMngr.getDataObjects(); - List linearized = new ArrayList(); - ListIterator> li = allobjects.listIterator(); - while(li.hasNext()) { - linearized.addAll(li.next()); - } - - ArrayAdapter adapter = new ArrayAdapter(this,R.layout.object_view, linearized); - ListView objects = (ListView) findViewById(R.id.object_list); - objects.setAdapter(adapter); + adapter.notifyDataSetChanged(); + } + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + // TODO Auto-generated method stub + } } diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java index 12a072de7..d91946b92 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java @@ -14,6 +14,9 @@ import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; public abstract class ObjectManagerActivity extends Activity { @@ -72,6 +75,31 @@ public abstract class ObjectManagerActivity extends Activity { } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.menu_connect: + binder.openConnection(); + return true; + case R.id.menu_disconnect: + binder.stopConnection(); + return true; + case R.id.menu_settings: + startActivity(new Intent(this, Preferences.class)); + return true; + default: + return super.onOptionsItemSelected(item); + } + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.options_menu, menu); + return true; + } + @Override public void onStart() { super.onStart(); diff --git a/androidgcs/src/org/openpilot/androidgcs/Preferences.java b/androidgcs/src/org/openpilot/androidgcs/Preferences.java new file mode 100644 index 000000000..913de0f73 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/Preferences.java @@ -0,0 +1,12 @@ +package org.openpilot.androidgcs; + +import android.os.Bundle; +import android.preference.PreferenceActivity; + +public class Preferences extends PreferenceActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + } +} From 545dd029d6d8e2a2c52b255f5e8cf5897250c471 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Mon, 21 Mar 2011 18:33:47 -0500 Subject: [PATCH 042/284] More work on the object browser/editor. Hard to make it resize itself though. --- androidgcs/AndroidManifest.xml | 1 + androidgcs/Doc/.AndroidArchitecture.txt.swp | Bin 12288 -> 0 bytes .../layout/{main.xml => object_browser.xml} | 0 androidgcs/res/layout/object_edit.xml | 9 +++ .../openpilot/androidgcs/ObjectBrowser.java | 44 ++++++++------- .../openpilot/androidgcs/ObjectEditor.java | 52 ++++++++++++++++++ .../androidgcs/ObjectManagerActivity.java | 23 +++++++- 7 files changed, 108 insertions(+), 21 deletions(-) delete mode 100644 androidgcs/Doc/.AndroidArchitecture.txt.swp rename androidgcs/res/layout/{main.xml => object_browser.xml} (100%) create mode 100644 androidgcs/res/layout/object_edit.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index a791d0fbb..fe8c6ae9a 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -26,6 +26,7 @@ + diff --git a/androidgcs/Doc/.AndroidArchitecture.txt.swp b/androidgcs/Doc/.AndroidArchitecture.txt.swp deleted file mode 100644 index 167a072526a8207b396d71d6dd7d3e7a417cba19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeHNzmFS56rMwnA3z`iK>^J`id>>QJ0S%T4RS8dVU#03?7Kh}jd#cP-0jXRGqdLy zB_JeP;2%IhK?4;OL^LQ=G-;^`1>rxSqu_h9yY}UZv?yp!`Qr2bn0fDe-}~N1+2N_J z-UffYb%x>RC}UrI^6`eazqIt*H;ip3#(SgBo~CmT`FUIA`E0F~nM7m{xr}`{U$A}N zBxNqOckRp8jIGFXrN`|{h18c-W_(-d)EbqJ6GxY}JJr{YO(x3A#FtjK{0;xG&EmPp zKxAOSK2dF}KmI(Y2WSNQYKZ7$Bo-y#E%fyh8)ATkgchzvvqA_I|u|2+e~ zSYjU`%g5?WFVvq)`#$Th@gp)28Hfx-1|kEIfyh8)ATkgchzvvqA_I|uN00%LGPe3S zW8w(}kN^K~{{8>wvy6QWdgNH7@GiVz&YUWBaGb!egqV740sWE0XPKw z{4`@0=mO_~lfb>F82cRP0!M*ofjdt!whJr+$AP~NGj<=i3)}=&fZq=>_6u+am;%ed z%fL&(-Ghw%0DKSJ0&W6r;2>}SxP5@J?|^TC1b7#?2Al(q0{?)6KY)9{ufSKpm%uIH zCJ;D!1Zx~ajtoQw{v!rDLzO8%3N*zup~i9E8`N zJjt(=($1ROmC@XJ;Y%0Jt%)q-ixtDMb+s$`1g~IalEU^A$uAAJvEPQ!Vk~WlMhc{| z+1bJ!d>}KKOOH)@=af#RWz3aDVXT*Fi}iSFw8t_^?}Wu_0x0t`OR*ESqfJcV5uM{= zXiCqg6IJbi16DEy2JlW;QP7eDT)l4K9sH7M5==$7f5Rz69N4eGEt)$7oa0aK>dR<<+V;*EZhkKkq=f0;#uJWRh7h|Lk)@Mia*XtyY#&& zZ&P+!eJnl81(K?`_p@bp0t|FA4-tfozxuZv%GMYV5G@j`J6 zy5|AVh8{o$Lu5PWw$TtDS(68fK+`@G=y$Jf_13zT3-nFZvp2l7T4daWb|zs;NP;A2 z<(RC7`h?s^4AJ|}YlBe!Esc)S*+4( zVXz0Jx=DhbcZh^O(6Wiip%Xq8!7NiU9#D!uWPYRr+*Jk6mt6^O5H9GbdN-7=fY?G2 zKqZt<w>-1wnI&T9)>r`IggCxCM`qiRMFH(r;p=PLhmUW2tq;~>J3K{ zE@~y3gMwQW(#?=$4srAA~;j1tIlNGZG^8G*3NuIRz$>-_K0|9#2o7)E zy0$aPj`Sd1^D6_g-Fh==!;D$w8{K}tv)<*GJN z%~W%*a@k^KkwQ03=yfqrhy(^WMiQ{XP&Dw5tf{9ObFD)iG$zf~s?3mXt&3{yFhFYt zLUMI{W)!}SFonYu2;1PDnASejO27?lH&?XqC1*CKB2< zJRd2H4ssgICx|G+fTt48MX*tgmL`RI(p33h$kce^=a=@Oe8i7VUSI1!c$Bh$@MKO} z)yAt)QxAH8;9x{Ma{lmmg0?`p(M<5NMIcQCRwfb;P%hM!HY3^6{aAa>5fmB5hHtb? zVZnXGHoT4&hb!U1?v2pE^H6zZEvPGvF2pr&X_;cKVK49(?j|=txdk7|DGdht+4F>0 I9l+o0U$ht(TmS$7 diff --git a/androidgcs/res/layout/main.xml b/androidgcs/res/layout/object_browser.xml similarity index 100% rename from androidgcs/res/layout/main.xml rename to androidgcs/res/layout/object_browser.xml diff --git a/androidgcs/res/layout/object_edit.xml b/androidgcs/res/layout/object_edit.xml new file mode 100644 index 000000000..62a482be9 --- /dev/null +++ b/androidgcs/res/layout/object_edit.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index f3cc56d47..df2d114a4 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -9,25 +9,16 @@ import java.util.Observer; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.database.DataSetObserver; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; -import android.widget.Adapter; +import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.ExpandableListAdapter; -import android.widget.ExpandableListView; import android.widget.ListView; -import android.widget.SimpleAdapter; -import android.widget.SimpleExpandableListAdapter; -import android.widget.TextView; import android.widget.Toast; +import android.widget.AdapterView.OnItemClickListener; import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObject; @@ -38,6 +29,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref boolean connected; SharedPreferences prefs; ArrayAdapter adapter; + List allObjects; final Handler uavobjHandler = new Handler(); final Runnable updateText = new Runnable() { @@ -51,7 +43,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.main); + setContentView(R.layout.object_browser); prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); } @@ -60,18 +52,32 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref void onOPConnected() { Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT); Log.d(TAG, "onOPConnected()"); - + List> allobjects = objMngr.getDataObjects(); - List linearized = new ArrayList(); + allObjects = new ArrayList(); ListIterator> li = allobjects.listIterator(); while(li.hasNext()) { - linearized.addAll(li.next()); + allObjects.addAll(li.next()); } - - adapter = new ArrayAdapter(this,R.layout.object_view, linearized); + + adapter = new ArrayAdapter(this,R.layout.object_view, allObjects); ListView objects = (ListView) findViewById(R.id.object_list); objects.setAdapter(adapter); + objects.setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, + int position, long id) { + /*Toast.makeText(getApplicationContext(), ((TextView) view).getText(), + Toast.LENGTH_SHORT).show();*/ + Intent intent = new Intent(ObjectBrowser.this, ObjectEditor.class); + intent.putExtra("org.openpilot.androidgcs.ObjectName", allObjects.get(position).getName()); + intent.putExtra("org.openpilot.androidgcs.ObjectId", allObjects.get(position).getObjID()); + intent.putExtra("org.openpilot.androidgcs.InstId", allObjects.get(position).getInstID()); + startActivity(intent); + } + }); + + UAVObject obj = objMngr.getObject("SystemStats"); if(obj != null) obj.addUpdatedObserver(new Observer() { @@ -81,7 +87,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref }); } - + public void update() { adapter.notifyDataSetChanged(); } @@ -89,6 +95,6 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // TODO Auto-generated method stub - + } } diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java b/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java new file mode 100644 index 000000000..33d0e2f8e --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java @@ -0,0 +1,52 @@ +package org.openpilot.androidgcs; + +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVObjectField; + +import android.os.Bundle; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +public class ObjectEditor extends ObjectManagerActivity { + + String objectName; + int objectID; + int instID; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.object_edit); + + System.out.println("Started. Intent:" + getIntent()); + Bundle extras = getIntent().getExtras(); + if(extras != null){ + objectName = extras.getString("org.openpilot.androidgcs.ObjectName"); + objectID = extras.getInt("org.openpilot.androidgcs.ObjectId"); + instID = extras.getInt("org.openpilot.androidgcs.InstId"); + } + } + + public void onOPConnected() { + UAVObject obj = objMngr.getObject(objectID, instID); + Toast.makeText(getApplicationContext(), obj.toString(), Toast.LENGTH_SHORT); + + TextView objectName = (TextView) findViewById(R.id.object_edit_name); + objectName.setText(obj.getName()); + + LinearLayout fieldViewList = (LinearLayout) findViewById(R.id.object_edit_fields); + List fields = obj.getFields(); + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + UAVObjectField field = li.next(); + TextView fieldName = new TextView(this); + fieldName.setText(field.getName()); + fieldViewList.addView(fieldName); + } + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java index d91946b92..5027d4d24 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java @@ -21,7 +21,7 @@ import android.view.MenuItem; public abstract class ObjectManagerActivity extends Activity { private final String TAG = "ObjectManagerActivity"; - private static int LOGLEVEL = 2; + private static int LOGLEVEL = 0; // private static boolean WARN = LOGLEVEL > 1; private static boolean DEBUG = LOGLEVEL > 0; @@ -106,19 +106,38 @@ public abstract class ObjectManagerActivity extends Activity { Intent intent = new Intent(this, OPTelemetryService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } + + public void onBind() { + + } /** Defines callbacks for service binding, passed to bindService() */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName arg0, IBinder service) { // We've bound to LocalService, cast the IBinder and attempt to open a connection if (DEBUG) Log.d(TAG,"Service bound"); - binder = (LocalBinder) service; + mBound = true; + binder = (LocalBinder) service; + + if(binder.isConnected()) { + TelemTask task; + if((task = binder.getTelemTask(0)) != null) { + objMngr = task.getObjectManager(); + mConnected = true; + onOPConnected(); + } + + } } public void onServiceDisconnected(ComponentName name) { mBound = false; + binder = null; mConnected = false; objMngr = null; + objMngr = null; + mConnected = false; + onOPDisconnected(); } }; } From 5669a3fc33a7faa1f96273c49572f433101ff53f Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 12:59:01 -0500 Subject: [PATCH 043/284] Added a simple PFD --- androidgcs/AndroidManifest.xml | 9 +- androidgcs/res/drawable-hdpi/browser_icon.png | Bin 0 -> 456 bytes androidgcs/res/drawable-ldpi/browser_icon.png | Bin 0 -> 456 bytes androidgcs/res/drawable-mdpi/browser_icon.png | Bin 0 -> 456 bytes androidgcs/res/layout/gcs_home.xml | 9 +- androidgcs/res/layout/pfd.xml | 8 + androidgcs/res/values/colors.xml | 6 + androidgcs/res/values/strings.xml | 6 + .../openpilot/androidgcs/AttitudeView.java | 89 +++++++++++ .../org/openpilot/androidgcs/CompassView.java | 139 ++++++++++++++++++ .../org/openpilot/androidgcs/HomePage.java | 9 ++ .../src/org/openpilot/androidgcs/PFD.java | 51 +++++++ 12 files changed, 318 insertions(+), 8 deletions(-) create mode 100644 androidgcs/res/drawable-hdpi/browser_icon.png create mode 100644 androidgcs/res/drawable-ldpi/browser_icon.png create mode 100644 androidgcs/res/drawable-mdpi/browser_icon.png create mode 100644 androidgcs/res/layout/pfd.xml create mode 100644 androidgcs/res/values/colors.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/AttitudeView.java create mode 100644 androidgcs/src/org/openpilot/androidgcs/CompassView.java create mode 100644 androidgcs/src/org/openpilot/androidgcs/PFD.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index fe8c6ae9a..1942146c4 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -18,13 +18,8 @@ - - - - - - - + + diff --git a/androidgcs/res/drawable-hdpi/browser_icon.png b/androidgcs/res/drawable-hdpi/browser_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3fcee485245922172e66bad2eb2203db14cdac39 GIT binary patch literal 456 zcmV;(0XP1MP)2!duSV%belNQ;||iLJSe+;1>Z9S#NM0kJ-$^wmm*RY+To8 zv9OU+Vp%S#Dwxlg2qCa-7b$%#%SVV+t!?|?eYIMiWKtswJ$f(3w;l5V%m%S&OW63?^9=i}S!{|oRH^?GKj631~Um0~;V0=*5_l}PE6%PFYp yZavDW{)W@(8>Xp~%_jEdoebdExV#6+x#JU=$8dKofqu*Y00002!duSV%belNQ;||iLJSe+;1>Z9S#NM0kJ-$^wmm*RY+To8 zv9OU+Vp%S#Dwxlg2qCa-7b$%#%SVV+t!?|?eYIMiWKtswJ$f(3w;l5V%m%S&OW63?^9=i}S!{|oRH^?GKj631~Um0~;V0=*5_l}PE6%PFYp yZavDW{)W@(8>Xp~%_jEdoebdExV#6+x#JU=$8dKofqu*Y00002!duSV%belNQ;||iLJSe+;1>Z9S#NM0kJ-$^wmm*RY+To8 zv9OU+Vp%S#Dwxlg2qCa-7b$%#%SVV+t!?|?eYIMiWKtswJ$f(3w;l5V%m%S&OW63?^9=i}S!{|oRH^?GKj631~Um0~;V0=*5_l}PE6%PFYp yZavDW{)W@(8>Xp~%_jEdoebdExV#6+x#JU=$8dKofqu*Y0000 - + diff --git a/androidgcs/res/layout/pfd.xml b/androidgcs/res/layout/pfd.xml new file mode 100644 index 000000000..191a80eb9 --- /dev/null +++ b/androidgcs/res/layout/pfd.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/androidgcs/res/values/colors.xml b/androidgcs/res/values/colors.xml new file mode 100644 index 000000000..dc8eaf315 --- /dev/null +++ b/androidgcs/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #F555 + #AFFF + #AFFF + diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index e9b66a312..3b3a38d02 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -2,6 +2,7 @@ OpenPilot GCS Home OpenPilot Object Browser + OpenPilot PFD Settings Connect Disconnect @@ -10,4 +11,9 @@ Connection Type Bluetooth Select the connection method + Compass + N + E + S + W diff --git a/androidgcs/src/org/openpilot/androidgcs/AttitudeView.java b/androidgcs/src/org/openpilot/androidgcs/AttitudeView.java new file mode 100644 index 000000000..24a8bf5f0 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/AttitudeView.java @@ -0,0 +1,89 @@ +package org.openpilot.androidgcs; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.view.View; + +public class AttitudeView extends View { + + public AttitudeView(Context context) { + super(context); + initAttitudeView(); + } + + public AttitudeView(Context context, AttributeSet ats, int defaultStyle) { + super(context, ats, defaultStyle); + initAttitudeView(); + } + + public AttitudeView(Context context, AttributeSet ats) { + super(context, ats); + initAttitudeView(); + } + + protected void initAttitudeView() { + setFocusable(true); + + circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + circlePaint.setColor(R.color.background_color); + circlePaint.setStrokeWidth(1); + circlePaint.setStyle(Paint.Style.FILL_AND_STROKE); + Resources r = this.getResources(); + textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + textPaint.setColor(r.getColor(R.color.text_color)); + markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + markerPaint.setColor(r.getColor(R.color.marker_color)); + } + + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int measuredWidth = measure(widthMeasureSpec); + int measuredHeight = measure(heightMeasureSpec); + int d = Math.min(measuredWidth, measuredHeight); + setMeasuredDimension(d/2, d/2); + } + + private int measure(int measureSpec) { + int result = 0; + // Decode the measurement specifications. + + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.UNSPECIFIED) { // Return a default size of 200 if no bounds are specified. + result = 200; + } else { + // As you want to fill the available space + // always return the full available bounds. + result = specSize; + } + return result; + } + + private double roll; + public void setRoll(double roll) { + this.roll = roll; + } + private double pitch; + public void setPitch(double d) { + this.pitch = d; + } + + // Drawing related code + private Paint markerPaint; + private Paint textPaint; + private Paint circlePaint; + + @Override + protected void onDraw(Canvas canvas) { + int px = getMeasuredWidth() / 2; + int py = getMeasuredHeight() /2 ; + int radius = Math.min(px, py); + + canvas.drawLine(px,py, (int) (px+radius * Math.cos(roll)), (int) (py + radius * Math.sin(roll)), markerPaint); + canvas.drawLine(px,py, (int) (px+radius * Math.cos(pitch)), (int) (py + radius * Math.sin(pitch)), markerPaint); + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/CompassView.java b/androidgcs/src/org/openpilot/androidgcs/CompassView.java new file mode 100644 index 000000000..50e4abc0a --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/CompassView.java @@ -0,0 +1,139 @@ +package org.openpilot.androidgcs; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.view.View; + +public class CompassView extends View { + + public CompassView(Context context) { + super(context); + initCompassView(); + } + + public CompassView(Context context, AttributeSet ats, int defaultStyle) { + super(context, ats, defaultStyle); + initCompassView(); + } + + public CompassView(Context context, AttributeSet ats) { + super(context, ats); + initCompassView(); + } + + protected void initCompassView() { + setFocusable(true); + + circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + circlePaint.setColor(R.color.background_color); + circlePaint.setStrokeWidth(1); + circlePaint.setStyle(Paint.Style.FILL_AND_STROKE); + Resources r = this.getResources(); + northString = r.getString(R.string.cardinal_north); + eastString = r.getString(R.string.cardinal_east); + southString = r.getString(R.string.cardinal_south); + westString = r.getString(R.string.cardinal_west); + textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + textPaint.setColor(r.getColor(R.color.text_color)); + textHeight = (int)textPaint.measureText("yY"); + markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + markerPaint.setColor(r.getColor(R.color.marker_color)); + } + + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int measuredWidth = measure(widthMeasureSpec); + int measuredHeight = measure(heightMeasureSpec); + int d = Math.min(measuredWidth, measuredHeight); + setMeasuredDimension(d/2, d/2); + } + + private int measure(int measureSpec) { + int result = 0; + // Decode the measurement specifications. + + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.UNSPECIFIED) { // Return a default size of 200 if no bounds are specified. + result = 200; + } else { + // As you want to fill the available space + // always return the full available bounds. + result = specSize; + } + return result; + } + + private double bearing; + public void setBearing(double bearing) { + this.bearing = bearing; + } + + // Drawing related code + private Paint markerPaint; + private Paint textPaint; + private Paint circlePaint; + private String northString; + private String eastString; + private String southString; + private String westString; + private int textHeight; + + @Override + protected void onDraw(Canvas canvas) { + int px = getMeasuredWidth() / 2; + int py = getMeasuredHeight() /2 ; + int radius = Math.min(px, py); + // Draw the background + canvas.drawCircle(px, py, radius, circlePaint); + + // Rotate our perspective so that the ÔtopÕ is + // facing the current bearing. + canvas.save(); + canvas.rotate((float) -bearing, px, py); + + int textWidth = (int)textPaint.measureText("W"); + int cardinalX = px-textWidth/2; + int cardinalY = py-radius+textHeight; + + // Draw the marker every 15 degrees and text every 45. + for (int i = 0; i < 24; i++) { + // Draw a marker. + canvas.drawLine(px, py-radius, px, py-radius+10, markerPaint); + canvas.save(); + canvas.translate(0, textHeight); + // Draw the cardinal points + if (i % 6 == 0) { + String dirString = null; + switch (i) { + case 0 : { + dirString = northString; + int arrowY = 2*textHeight; + canvas.drawLine(px, arrowY, px-5, 3*textHeight, markerPaint); + canvas.drawLine(px, arrowY, px+5, 3*textHeight, markerPaint); + break; + } + case 6: dirString = eastString; break; + case 12: dirString = southString; break; + case 18: dirString = westString; break; + } + canvas.drawText(dirString, cardinalX, cardinalY, textPaint); + } + else if (i % 3 == 0) { + // Draw the text every alternate 45deg + String angle = String.valueOf(i*15); + float angleTextWidth = textPaint.measureText(angle); + + int angleTextX = (int)(px-angleTextWidth/2); + int angleTextY = py-radius+textHeight; + canvas.drawText(angle, angleTextX, angleTextY, textPaint); + } + canvas.restore(); + canvas.rotate(15, px, py); + } + canvas.restore(); + } +} diff --git a/androidgcs/src/org/openpilot/androidgcs/HomePage.java b/androidgcs/src/org/openpilot/androidgcs/HomePage.java index 478c7cdca..7d03e1b04 100644 --- a/androidgcs/src/org/openpilot/androidgcs/HomePage.java +++ b/androidgcs/src/org/openpilot/androidgcs/HomePage.java @@ -12,12 +12,21 @@ public class HomePage extends ObjectManagerActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gcs_home); + Button objectBrowser = (Button) findViewById(R.id.launch_object_browser); objectBrowser.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { startActivity(new Intent(HomePage.this, ObjectBrowser.class)); } }); + + Button pfd = (Button) findViewById(R.id.launch_pfd); + pfd.setOnClickListener(new OnClickListener() { + public void onClick(View arg0) { + startActivity(new Intent(HomePage.this, PFD.class)); + } + }); + } } diff --git a/androidgcs/src/org/openpilot/androidgcs/PFD.java b/androidgcs/src/org/openpilot/androidgcs/PFD.java new file mode 100644 index 000000000..e0d1b9f24 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/PFD.java @@ -0,0 +1,51 @@ +package org.openpilot.androidgcs; + +import java.util.Observable; +import java.util.Observer; + +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObject; + +import android.os.Bundle; + +public class PFD extends ObjectManagerActivity { + + double heading; + double roll; + double pitch; + + Runnable update = new Runnable() { + public void run() { + CompassView compass = (CompassView) findViewById(R.id.compass_view); + compass.setBearing((int) heading); + compass.invalidate(); + + AttitudeView attitude = (AttitudeView) findViewById(R.id.attitude_view); + attitude.setRoll(roll / 180 * Math.PI); + attitude.setPitch(pitch / 180 * Math.PI); + attitude.invalidate(); + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.pfd); + } + + @Override + void onOPConnected() { + + UAVObject obj = objMngr.getObject("AttitudeActual"); + if(obj != null) + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + UAVDataObject obj = (UAVDataObject) data; + heading = obj.getField("Yaw").getDouble(); + pitch = obj.getField("Pitch").getDouble(); + roll = obj.getField("Roll").getDouble(); + runOnUiThread(update); + } + }); + } +} From 56aca6a8ec5960a39541377c61e7629bbf1e0056 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 12:59:17 -0500 Subject: [PATCH 044/284] Make fake telemetry show rotating attitude. --- .../org/openpilot/androidgcs/OPTelemetryService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 5af7c7d60..43cc13b04 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -200,8 +200,19 @@ public class OPTelemetryService extends Service { //toastMessage("Started fake telemetry thread"); UAVDataObject systemStats = (UAVDataObject) objMngr.getObject("SystemStats"); + UAVDataObject attitudeActual = (UAVDataObject) objMngr.getObject("AttitudeActual"); + double roll = 0; + double pitch = 0; + double yaw = 0; while( !terminate ) { + attitudeActual.getField("Roll").setDouble(roll); + attitudeActual.getField("Pitch").setDouble(pitch); + attitudeActual.getField("Yaw").setDouble(yaw); + roll = (roll + 10) % 180; + pitch = (pitch + 10) % 180; + yaw = (yaw + 10) % 360; systemStats.updated(); + attitudeActual.updated(); try { Thread.sleep(1000); } catch (InterruptedException e) { From 936ec069668626906559f05722c6b03459a47c4a Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 13:14:11 -0500 Subject: [PATCH 045/284] Make auto starting work. For now removed support for standalone service but easy to add back. --- .../androidgcs/OPTelemetryService.java | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 43cc13b04..67ee56d4e 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -68,10 +68,10 @@ public class OPTelemetryService extends Service { public void handleMessage(Message msg) { switch(msg.arg1) { case MSG_START: - Toast.makeText(OPTelemetryService.this, "HERE", Toast.LENGTH_SHORT); - System.out.println("HERE"); stopSelf(msg.arg2); - case MSG_CONNECT: + break; + case MSG_CONNECT: + Toast.makeText(getApplicationContext(), "Attempting connection", Toast.LENGTH_SHORT).show(); terminate = false; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); int connection_type = Integer.decode(prefs.getString("connection_type", "")); @@ -90,6 +90,7 @@ public class OPTelemetryService extends Service { activeTelem.start(); break; case MSG_DISCONNECT: + Toast.makeText(getApplicationContext(), "Disconnct", Toast.LENGTH_SHORT).show(); terminate = true; try { activeTelem.join(); @@ -101,6 +102,8 @@ public class OPTelemetryService extends Service { Intent intent = new Intent(); intent.setAction(INTENT_ACTION_DISCONNECTED); sendBroadcast(intent,null); + + stopSelf(); break; case MSG_TOAST: @@ -113,9 +116,9 @@ public class OPTelemetryService extends Service { } }; - @Override - public void onCreate() { - // Low priority thread for message handling with service + public void startup() { + Toast.makeText(getApplicationContext(), "Telemetry service starting", Toast.LENGTH_SHORT).show(); + HandlerThread thread = new HandlerThread("TelemetryServiceHandler", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); @@ -123,20 +126,27 @@ public class OPTelemetryService extends Service { // Get the HandlerThread's Looper and use it for our Handler mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); + if(prefs.getBoolean("autoconnect", false)) { + Toast.makeText(getApplicationContext(), "Should auto connect", Toast.LENGTH_SHORT); + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = MSG_CONNECT; + msg.arg2 = 0; + mServiceHandler.sendMessage(msg); + } + + } + + @Override + public void onCreate() { + startup(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { - Toast.makeText(this, "Telemetry service starting", Toast.LENGTH_SHORT).show(); - - System.out.println("Start"); - // For each start request, send a message to start a job and deliver the - // start ID so we know which request we're stopping when we finish the job - Message msg = mServiceHandler.obtainMessage(); - msg.arg1 = MSG_START; - msg.arg2 = startId; - mServiceHandler.sendMessage(msg); - + // Currently only using as bound service + // If we get killed, after returning from here, restart return START_STICKY; } @@ -156,6 +166,7 @@ public class OPTelemetryService extends Service { return (TelemTask) activeTelem; } public void openConnection() { + Toast.makeText(getApplicationContext(), "Requested open connection", Toast.LENGTH_SHORT); Message msg = mServiceHandler.obtainMessage(); msg.arg1 = MSG_CONNECT; mServiceHandler.sendMessage(msg); From 3f5be92cc3eddec44db16fdf5f4f6a7bb14925ca Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 21:39:44 -0500 Subject: [PATCH 046/284] Added location feature and made fake stream create movement --- androidgcs/AndroidManifest.xml | 18 +- androidgcs/default.properties | 2 +- androidgcs/res/layout/gcs_home.xml | 1 + androidgcs/res/layout/map_layout.xml | 10 + androidgcs/res/values/strings.xml | 37 ++- .../org/openpilot/androidgcs/HomePage.java | 6 + .../androidgcs/OPTelemetryService.java | 27 ++ .../org/openpilot/androidgcs/UAVLocation.java | 273 ++++++++++++++++++ 8 files changed, 351 insertions(+), 23 deletions(-) create mode 100644 androidgcs/res/layout/map_layout.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/UAVLocation.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index 1942146c4..c18dc0cb1 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -4,10 +4,14 @@ android:versionName="1.0"> + + + + @@ -16,13 +20,15 @@ - - + + - - - - + + + + + diff --git a/androidgcs/default.properties b/androidgcs/default.properties index 66db0d159..420db56e3 100644 --- a/androidgcs/default.properties +++ b/androidgcs/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-10 +target=Google Inc.:Google APIs:8 diff --git a/androidgcs/res/layout/gcs_home.xml b/androidgcs/res/layout/gcs_home.xml index 1a5a81cd7..e07f5b003 100644 --- a/androidgcs/res/layout/gcs_home.xml +++ b/androidgcs/res/layout/gcs_home.xml @@ -11,4 +11,5 @@ android:id="@+id/launch_object_browser" android:drawableLeft="@drawable/browser_icon" android:layout_centerHorizontal="true"/> + diff --git a/androidgcs/res/layout/map_layout.xml b/androidgcs/res/layout/map_layout.xml new file mode 100644 index 000000000..64c64b16e --- /dev/null +++ b/androidgcs/res/layout/map_layout.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index 3b3a38d02..7cef563e7 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -1,19 +1,24 @@ - OpenPilot GCS Home - OpenPilot Object Browser - OpenPilot PFD - Settings - Connect - Disconnect - Settings - Automatically Connect - Connection Type - Bluetooth - Select the connection method - Compass - N - E - S - W + OpenPilot GCS Home + OpenPilot Object Browser + OpenPilot PFD + OpenPilot Location + + Settings + Connect + Disconnect + + Settings + Automatically Connect + Connection Type + Bluetooth + Select the connection method + + Compass + N + E + S + W + Connected diff --git a/androidgcs/src/org/openpilot/androidgcs/HomePage.java b/androidgcs/src/org/openpilot/androidgcs/HomePage.java index 7d03e1b04..cf9664d14 100644 --- a/androidgcs/src/org/openpilot/androidgcs/HomePage.java +++ b/androidgcs/src/org/openpilot/androidgcs/HomePage.java @@ -27,6 +27,12 @@ public class HomePage extends ObjectManagerActivity { } }); + Button location = (Button) findViewById(R.id.launch_location); + location.setOnClickListener(new OnClickListener() { + public void onClick(View arg0) { + startActivity(new Intent(HomePage.this, UAVLocation.class)); + } + }); } } diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 67ee56d4e..c2914f34a 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -212,18 +212,45 @@ public class OPTelemetryService extends Service { //toastMessage("Started fake telemetry thread"); UAVDataObject systemStats = (UAVDataObject) objMngr.getObject("SystemStats"); UAVDataObject attitudeActual = (UAVDataObject) objMngr.getObject("AttitudeActual"); + UAVDataObject homeLocation = (UAVDataObject) objMngr.getObject("HomeLocation"); + UAVDataObject positionActual = (UAVDataObject) objMngr.getObject("PositionActual"); + + homeLocation.getField("Latitude").setDouble(379420315); + homeLocation.getField("Longitude").setDouble(-88330078); + homeLocation.getField("ECEF").setDouble(497665694,0); + homeLocation.getField("ECEF").setDouble(-77336320,1); + homeLocation.getField("ECEF").setDouble(390037169,2); + homeLocation.getField("RNE").setDouble(-0.60757166,0); + homeLocation.getField("RNE").setDouble(0.09441550,1); + homeLocation.getField("RNE").setDouble(0.78863323,2); + homeLocation.getField("RNE").setDouble(0.15355512,3); + homeLocation.getField("RNE").setDouble(0.98814011,4); + homeLocation.getField("RNE").setDouble(0,5); + homeLocation.getField("RNE").setDouble(-0.77928013,6); + homeLocation.getField("RNE").setDouble(0.12109867,7); + homeLocation.getField("RNE").setDouble(-0.61486387,8); + homeLocation.getField("Be").setDouble(26702.78710938,0); + homeLocation.getField("Be").setDouble(-1468.33605957,1); + homeLocation.getField("Be").setDouble(34181.78515625,2); + + double roll = 0; double pitch = 0; double yaw = 0; + double north = 0; + double east = 0; while( !terminate ) { attitudeActual.getField("Roll").setDouble(roll); attitudeActual.getField("Pitch").setDouble(pitch); attitudeActual.getField("Yaw").setDouble(yaw); + positionActual.getField("North").setDouble(north += 100); + positionActual.getField("East").setDouble(east += 100); roll = (roll + 10) % 180; pitch = (pitch + 10) % 180; yaw = (yaw + 10) % 360; systemStats.updated(); attitudeActual.updated(); + positionActual.updated(); try { Thread.sleep(1000); } catch (InterruptedException e) { diff --git a/androidgcs/src/org/openpilot/androidgcs/UAVLocation.java b/androidgcs/src/org/openpilot/androidgcs/UAVLocation.java new file mode 100644 index 000000000..72085c1d6 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/UAVLocation.java @@ -0,0 +1,273 @@ +package org.openpilot.androidgcs; + +import java.util.List; +import java.util.Observable; +import java.util.Observer; + +import org.openpilot.androidgcs.OPTelemetryService.LocalBinder; +import org.openpilot.androidgcs.OPTelemetryService.TelemTask; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVObjectManager; + +import com.google.android.maps.GeoPoint; +import com.google.android.maps.MapActivity; +import com.google.android.maps.MapController; +import com.google.android.maps.MapView; +import com.google.android.maps.Overlay; +import com.google.android.maps.Projection; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Point; +import android.graphics.RectF; +import android.os.Bundle; +import android.os.IBinder; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; + +public class UAVLocation extends MapActivity +{ + private final String TAG = "UAVLocation"; + private static int LOGLEVEL = 0; +// private static boolean WARN = LOGLEVEL > 1; + private static boolean DEBUG = LOGLEVEL > 0; + + private MapView mapView; + private MapController mapController; + + UAVObjectManager objMngr; + boolean mBound = false; + boolean mConnected = false; + LocalBinder binder; + + GeoPoint homeLocation; + GeoPoint uavLocation; + + @Override public void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.map_layout); + mapView = (MapView)findViewById(R.id.map_view); + mapController = mapView.getController(); + + mapView.displayZoomControls(true); + Double lat = 37.422006*1E6; + Double lng = -122.084095*1E6; + homeLocation = new GeoPoint(lat.intValue(), lng.intValue()); + uavLocation = homeLocation; + mapController.setCenter(homeLocation); + mapController.setZoom(18); + + List overlays = mapView.getOverlays(); + UAVOverlay myOverlay = new UAVOverlay(); + overlays.add(myOverlay); + mapView.postInvalidate(); + + // ObjectManager related stuff (can't inherit standard class) + BroadcastReceiver connectedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Log.d(TAG, "Received intent"); + TelemTask task; + if(intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_CONNECTED) == 0) { + + if(binder == null) + return; + if((task = binder.getTelemTask(0)) == null) + return; + objMngr = task.getObjectManager(); + mConnected = true; + onOPConnected(); + Log.d(TAG, "Connected()"); + } else if (intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_DISCONNECTED) == 0) { + objMngr = null; + mConnected = false; + onOPDisconnected(); + Log.d(TAG, "Disonnected()"); + } + } + }; + + IntentFilter filter = new IntentFilter(); + filter.addCategory(OPTelemetryService.INTENT_CATEGORY_GCS); + filter.addAction(OPTelemetryService.INTENT_ACTION_CONNECTED); + filter.addAction(OPTelemetryService.INTENT_ACTION_DISCONNECTED); + registerReceiver(connectedReceiver, filter); + } + + //@Override + protected boolean isRouteDisplayed() { + // IMPORTANT: This method must return true if your Activity // is displaying driving directions. Otherwise return false. + return false; + } + + public class UAVOverlay extends Overlay { + @Override + public void draw(Canvas canvas, MapView mapView, boolean shadow) { + + Projection projection = mapView.getProjection(); + + if (shadow == false) { + Point myPoint = new Point(); + projection.toPixels(uavLocation, myPoint); + + //// Draw UAV + // Create and setup your paint brush + Paint paint = new Paint(); + paint.setARGB(250, 255, 0, 0); + paint.setAntiAlias(true); + paint.setFakeBoldText(true); + + // Create the circle + int rad = 5; + RectF oval = new RectF(myPoint.x-rad, myPoint.y-rad, myPoint.x+rad, myPoint.y+rad); + + // Draw on the canvas + canvas.drawOval(oval, paint); + canvas.drawText("UAV", myPoint.x+rad, myPoint.y, paint); + + //// Draw Home + myPoint = new Point(); + projection.toPixels(homeLocation, myPoint); + + // Create and setup your paint brush + paint.setARGB(250, 0, 0, 0); + paint.setAntiAlias(true); + paint.setFakeBoldText(true); + + // Create the circle + rad = 5; + oval = new RectF(myPoint.x-rad, myPoint.y-rad, myPoint.x+rad, myPoint.y+rad); + + // Draw on the canvas + canvas.drawOval(oval, paint); + canvas.drawText("Home", myPoint.x+rad, myPoint.y, paint); + + } + } + + @Override + public boolean onTap(GeoPoint point, MapView mapView1) { + // Return true if screen tap is handled by this overlay + return false; + } + } + + void onOPConnected() { + UAVObject obj = objMngr.getObject("HomeLocation"); + if(obj != null) + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + UAVDataObject obj = (UAVDataObject) data; + Double lat = obj.getField("Latitude").getDouble() / 10; + Double lon = obj.getField("Longitude").getDouble() / 10; + homeLocation = new GeoPoint(lat.intValue(), lon.intValue()); + runOnUiThread(new Runnable() { + public void run() { + mapController.setCenter(homeLocation); + } + }); + System.out.println("HomeLocation: " + homeLocation.toString()); + } + }); + // Hacky - trigger an update + obj.updated(); + + obj = objMngr.getObject("PositionActual"); + if(obj != null) + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + UAVDataObject obj = (UAVDataObject) data; + Double north = obj.getField("North").getDouble(); + Double east = obj.getField("East").getDouble(); + // TODO: Correct convertion from NED to LLA. This is erroneous conversion from cm to deg + uavLocation = new GeoPoint((int) (homeLocation.getLatitudeE6() + north / 100 * 1e6 / 78847), + (int) (homeLocation.getLongitudeE6() + east / 100 * 1e6 / 78847)); + runOnUiThread(new Runnable() { + public void run() { + mapView.invalidate(); + } + }); + } + }); + + } + + void onOPDisconnected() { + + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.menu_connect: + binder.openConnection(); + return true; + case R.id.menu_disconnect: + binder.stopConnection(); + return true; + case R.id.menu_settings: + startActivity(new Intent(this, Preferences.class)); + return true; + default: + return super.onOptionsItemSelected(item); + } + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.options_menu, menu); + return true; + } + + @Override + public void onStart() { + super.onStart(); + Intent intent = new Intent(this, OPTelemetryService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + public void onBind() { + + } + + /** Defines callbacks for service binding, passed to bindService() */ + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName arg0, IBinder service) { + // We've bound to LocalService, cast the IBinder and attempt to open a connection + if (DEBUG) Log.d(TAG,"Service bound"); + mBound = true; + binder = (LocalBinder) service; + + if(binder.isConnected()) { + TelemTask task; + if((task = binder.getTelemTask(0)) != null) { + objMngr = task.getObjectManager(); + mConnected = true; + onOPConnected(); + } + + } + } + + public void onServiceDisconnected(ComponentName name) { + mBound = false; + binder = null; + mConnected = false; + objMngr = null; + objMngr = null; + mConnected = false; + onOPDisconnected(); + } + }; +} From 1a4db3332859acf2218083bdd4cc2e8db7639063 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 21:59:36 -0500 Subject: [PATCH 047/284] Few tweaks and suppress some warnings --- androidgcs/default.properties | 2 +- androidgcs/res/xml/preferences.xml | 23 ++++++++++-------- .../openpilot/androidgcs/TelemetryWidget.java | 24 ++++++++++++++++++- .../uavobjects/UAVObjectsInitialize.java | 2 +- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/androidgcs/default.properties b/androidgcs/default.properties index 420db56e3..728f51f97 100644 --- a/androidgcs/default.properties +++ b/androidgcs/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=Google Inc.:Google APIs:8 +target=Google Inc.:Google APIs:11 diff --git a/androidgcs/res/xml/preferences.xml b/androidgcs/res/xml/preferences.xml index d731f59dd..24fd43b5e 100644 --- a/androidgcs/res/xml/preferences.xml +++ b/androidgcs/res/xml/preferences.xml @@ -1,12 +1,15 @@ - - - + + + + + + diff --git a/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java b/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java index d316526ef..51afdf568 100644 --- a/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java +++ b/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java @@ -2,11 +2,34 @@ package org.openpilot.androidgcs; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.widget.RemoteViews; public class TelemetryWidget extends AppWidgetProvider { + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getAction().equals(OPTelemetryService.INTENT_ACTION_CONNECTED)) { + changeStatus(context, true); + } + if(intent.getAction().equals(OPTelemetryService.INTENT_ACTION_DISCONNECTED)) { + changeStatus(context, false); + } + + super.onReceive(context, intent); + } + + public void changeStatus(Context context, boolean status) { + RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.telemetry_widget); + updateViews.setTextViewText(R.id.telemetryWidgetStatus, "Connection status: " + status); + ComponentName thisWidget = new ComponentName(context, TelemetryWidget.class); + AppWidgetManager manager = AppWidgetManager.getInstance(context); + manager.updateAppWidget(thisWidget, updateViews); + + } + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N = appWidgetIds.length; @@ -16,7 +39,6 @@ public class TelemetryWidget extends AppWidgetProvider { // Get the layout for the App Widget and attach an on-click listener to the button RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.telemetry_widget); - //views.setOnClickPendingIntent(R.id.button, pendingIntent); // Tell the AppWidgetManager to perform an update on the current App Widget appWidgetManager.updateAppWidget(appWidgetId, views); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java index 4eca6ea82..d1d47aebb 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java @@ -28,7 +28,7 @@ package org.openpilot.uavtalk.uavobjects; -import org.openpilot.uavtalk.uavobjects.*; +//import org.openpilot.uavtalk.uavobjects.*; import org.openpilot.uavtalk.UAVObjectManager; public class UAVObjectsInitialize { From caeaa0169f13587531154d792714abb52425244c Mon Sep 17 00:00:00 2001 From: James Cotton Date: Wed, 23 Mar 2011 11:37:20 -0500 Subject: [PATCH 048/284] Cleaner editor interface --- androidgcs/default.properties | 2 +- androidgcs/res/layout/object_browser.xml | 3 +- androidgcs/res/layout/object_edit.xml | 6 +- androidgcs/res/layout/object_editor.xml | 6 + androidgcs/res/values/strings.xml | 3 + .../androidgcs/OPTelemetryService.java | 5 +- .../openpilot/androidgcs/ObjectBrowser.java | 3 + .../openpilot/androidgcs/ObjectEditView.java | 114 ++++++++++++++++++ .../openpilot/androidgcs/ObjectEditor.java | 12 +- 9 files changed, 138 insertions(+), 16 deletions(-) create mode 100644 androidgcs/res/layout/object_editor.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/ObjectEditView.java diff --git a/androidgcs/default.properties b/androidgcs/default.properties index 728f51f97..fd1cedd24 100644 --- a/androidgcs/default.properties +++ b/androidgcs/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=Google Inc.:Google APIs:11 +target=Google Inc.:Google APIs:10 diff --git a/androidgcs/res/layout/object_browser.xml b/androidgcs/res/layout/object_browser.xml index 880e276ff..9c7456915 100644 --- a/androidgcs/res/layout/object_browser.xml +++ b/androidgcs/res/layout/object_browser.xml @@ -2,5 +2,6 @@ - + + diff --git a/androidgcs/res/layout/object_edit.xml b/androidgcs/res/layout/object_edit.xml index 62a482be9..c161caa4c 100644 --- a/androidgcs/res/layout/object_edit.xml +++ b/androidgcs/res/layout/object_edit.xml @@ -3,7 +3,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> - - - + + + diff --git a/androidgcs/res/layout/object_editor.xml b/androidgcs/res/layout/object_editor.xml new file mode 100644 index 000000000..d93b1a097 --- /dev/null +++ b/androidgcs/res/layout/object_editor.xml @@ -0,0 +1,6 @@ + + + diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index 7cef563e7..6d69e4126 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -21,4 +21,7 @@ S W Connected + Update + Save + Send diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index c2914f34a..ce90f5a48 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -74,7 +74,8 @@ public class OPTelemetryService extends Service { Toast.makeText(getApplicationContext(), "Attempting connection", Toast.LENGTH_SHORT).show(); terminate = false; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); - int connection_type = Integer.decode(prefs.getString("connection_type", "")); + //int connection_type = Integer.decode(prefs.getString("connection_type", "")); + int connection_type = 1; switch(connection_type) { case 0: // No connection return; @@ -128,7 +129,7 @@ public class OPTelemetryService extends Service { mServiceHandler = new ServiceHandler(mServiceLooper); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); - if(prefs.getBoolean("autoconnect", false)) { + if(prefs.getBoolean("autoconnect", false) || true) { Toast.makeText(getApplicationContext(), "Should auto connect", Toast.LENGTH_SHORT); Message msg = mServiceHandler.obtainMessage(); msg.arg1 = MSG_CONNECT; diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index df2d114a4..a6ed177a2 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -17,6 +17,7 @@ import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; +import android.widget.Spinner; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; @@ -46,6 +47,8 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref setContentView(R.layout.object_browser); prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); + + Spinner objectFilter = (Spinner) findViewById(R.id.object_list_filter); } @Override diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectEditView.java b/androidgcs/src/org/openpilot/androidgcs/ObjectEditView.java new file mode 100644 index 000000000..7b81ff18c --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectEditView.java @@ -0,0 +1,114 @@ +package org.openpilot.androidgcs; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectField; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class ObjectEditView extends LinearLayout { + + TextView objectName; + List fields; + + public ObjectEditView(Context context) { + super(context); + initObjectEditView(); + } + + public ObjectEditView(Context context, AttributeSet ats, int defaultStyle) { + super(context, ats); + initObjectEditView(); + } + + public ObjectEditView(Context context, AttributeSet ats) { + super(context, ats); + initObjectEditView(); + } + + public void initObjectEditView() { + // Set orientation of layout to vertical + setOrientation(LinearLayout.VERTICAL); + + objectName = new TextView(getContext()); + objectName.setText(""); + objectName.setTextSize(14); + + // Lay them out in the compound control. + int lHeight = LayoutParams.WRAP_CONTENT; + int lWidth = LayoutParams.FILL_PARENT; + addView(objectName, new LinearLayout.LayoutParams(lWidth, lHeight)); + + fields = new ArrayList(); + } + + public void setName(String name) { + objectName.setText(name); + } + + public void addField(UAVObjectField field) { + if(field.getNumElements() == 1) { + FieldValue fieldView = new FieldValue(getContext()); + fieldView.setName(field.getName()); + if(field.isNumeric()) { + fieldView.setValue(new Double(field.getDouble()).toString()); + } else { + fieldView.setValue(field.getValue().toString()); + } + fields.add(fieldView); + addView(fieldView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT)); + } + else { + ListIterator names = field.getElementNames().listIterator(); + int i = 0; + while(names.hasNext()) { + FieldValue fieldView = new FieldValue(getContext()); + fieldView.setName(field.getName() + "-" + names.next()); + if(field.isNumeric()) { + fieldView.setValue(new Double(field.getDouble(i)).toString()); + } else { + fieldView.setValue(field.getValue(i).toString()); + } + i++; + fields.add(fieldView); + addView(fieldView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT)); + + } + } + } + + public class FieldValue extends LinearLayout { + + TextView fieldName; + EditText fieldValue; + + public FieldValue(Context context) { + super(context); + setOrientation(LinearLayout.HORIZONTAL); + + fieldName = new TextView(getContext()); + fieldValue = new EditText(getContext()); + + // Lay them out in the compound control. + addView(fieldName, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT)); + fieldValue.setWidth(300); + addView(fieldValue, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + } + + public void setName(String name) { + fieldName.setText(name); + } + + public void setValue(String value) { + fieldValue.setText(value); + } + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java b/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java index 33d0e2f8e..afbddb5e5 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java @@ -7,8 +7,6 @@ import org.openpilot.uavtalk.UAVObject; import org.openpilot.uavtalk.UAVObjectField; import android.os.Bundle; -import android.widget.LinearLayout; -import android.widget.TextView; import android.widget.Toast; public class ObjectEditor extends ObjectManagerActivity { @@ -35,17 +33,13 @@ public class ObjectEditor extends ObjectManagerActivity { UAVObject obj = objMngr.getObject(objectID, instID); Toast.makeText(getApplicationContext(), obj.toString(), Toast.LENGTH_SHORT); - TextView objectName = (TextView) findViewById(R.id.object_edit_name); - objectName.setText(obj.getName()); + ObjectEditView editView = (ObjectEditView) findViewById(R.id.object_edit_view); + editView.setName(obj.getName()); - LinearLayout fieldViewList = (LinearLayout) findViewById(R.id.object_edit_fields); List fields = obj.getFields(); ListIterator li = fields.listIterator(); while(li.hasNext()) { - UAVObjectField field = li.next(); - TextView fieldName = new TextView(this); - fieldName.setText(field.getName()); - fieldViewList.addView(fieldName); + editView.addField(li.next()); } } From 38e4960fa5311e77bcfc4c0f25ae651202ac0ad7 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Feb 2012 17:07:27 -0600 Subject: [PATCH 049/284] Update the project and checked in the meta data. Hopefully this will make it run more easily in future. --- androidgcs/.classpath | 8 +- androidgcs/.metadata/.lock | 0 androidgcs/.metadata/.log | 83 ++++ .../.metadata/.mylyn/repositories.xml.zip | Bin 0 -> 403 bytes androidgcs/.metadata/.mylyn/tasks.xml.zip | Bin 0 -> 250 bytes .../.plugins/org.eclipse.cdt.core/.log | 1 + .../.root/.indexes/history.version | 1 + .../.root/.indexes/properties.index | Bin 0 -> 57 bytes .../.root/.indexes/properties.version | 1 + .../org.eclipse.core.resources/.root/2.tree | Bin 0 -> 149 bytes .../.safetable/org.eclipse.core.resources | Bin 0 -> 614 bytes .../.settings/org.eclipse.cdt.ui.prefs | 5 + .../org.eclipse.core.resources.prefs | 3 + .../org.eclipse.epp.usagedata.recording.prefs | 3 + .../.settings/org.eclipse.jdt.ui.prefs | 15 + .../org.eclipse.mylyn.context.core.prefs | 3 + .../.settings/org.eclipse.team.cvs.ui.prefs | 3 + .../.settings/org.eclipse.team.ui.prefs | 3 + .../.settings/org.eclipse.ui.editors.prefs | 3 + .../.settings/org.eclipse.ui.ide.prefs | 5 + .../.settings/org.eclipse.ui.prefs | 3 + .../.settings/org.eclipse.ui.workbench.prefs | 3 + .../upload0.csv | 251 +++++++++++++ .../usagedata.csv | 83 ++++ .../org.eclipse.jdt.core/nonChainingJarsCache | Bin 0 -> 4 bytes .../variablesAndContainers.dat | Bin 0 -> 96 bytes .../org.eclipse.jdt.ui/OpenTypeHistory.xml | 2 + .../QualifiedTypeNameHistory.xml | 2 + .../org.eclipse.jdt.ui/dialog_settings.xml | 10 + .../org.eclipse.ui.ide/dialog_settings.xml | 9 + .../org.eclipse.ui.intro/dialog_settings.xml | 4 + .../dialog_settings.xml | 5 + .../org.eclipse.ui.workbench/workbench.xml | 355 ++++++++++++++++++ .../org.eclipse.ui.workbench/workingsets.xml | 4 + androidgcs/.metadata/version.ini | 1 + .../.settings/org.eclipse.jdt.core.prefs | 11 +- androidgcs/lint.xml | 3 + ...{default.properties => project.properties} | 4 +- 38 files changed, 879 insertions(+), 8 deletions(-) create mode 100644 androidgcs/.metadata/.lock create mode 100644 androidgcs/.metadata/.log create mode 100644 androidgcs/.metadata/.mylyn/repositories.xml.zip create mode 100644 androidgcs/.metadata/.mylyn/tasks.xml.zip create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.cdt.core/.log create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/2.tree create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.cdt.ui.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.usagedata.recording.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.cvs.ui.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/upload0.csv create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/usagedata.csv create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml create mode 100644 androidgcs/.metadata/version.ini create mode 100644 androidgcs/lint.xml rename androidgcs/{default.properties => project.properties} (72%) diff --git a/androidgcs/.classpath b/androidgcs/.classpath index 6f3f456df..eb33e4360 100644 --- a/androidgcs/.classpath +++ b/androidgcs/.classpath @@ -1,9 +1,9 @@ + - - - - + + + diff --git a/androidgcs/.metadata/.lock b/androidgcs/.metadata/.lock new file mode 100644 index 000000000..e69de29bb diff --git a/androidgcs/.metadata/.log b/androidgcs/.metadata/.log new file mode 100644 index 000000000..8955f7bbc --- /dev/null +++ b/androidgcs/.metadata/.log @@ -0,0 +1,83 @@ +!SESSION 2012-02-04 14:21:36.086 ----------------------------------------------- +eclipse.buildId=unknown +java.version=1.6.0_29 +java.vendor=Apple Inc. +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -keyring /Users/jcotton81/.eclipse_keyring -showlocation +Command-line arguments: -os macosx -ws cocoa -arch x86_64 -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -data /Users/jcotton81/Documents/Programming/OpenPilot/androidgcs -product org.eclipse.epp.package.cpp.product -keyring /Users/jcotton81/.eclipse_keyring -showlocation + +!ENTRY org.eclipse.core.net 1 0 2012-02-04 14:21:41.864 +!MESSAGE System property http.nonProxyHosts has been set to local|*.local|169.254/16|*.169.254/16 by an external source. This value will be overwritten using the values from the preferences + +!ENTRY org.eclipse.ui.intro.universal 4 0 2012-02-04 14:21:44.892 +!MESSAGE /Users/jcotton81/Documents/Programming/eclipse/Eclipse.app/Contents/MacOS/introData.xml (No such file or directory) +!STACK 0 +java.io.FileNotFoundException: /Users/jcotton81/Documents/Programming/eclipse/Eclipse.app/Contents/MacOS/introData.xml (No such file or directory) + at java.io.FileInputStream.open(Native Method) + at java.io.FileInputStream.(FileInputStream.java:120) + at java.io.FileInputStream.(FileInputStream.java:79) + at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:70) + at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:161) + at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:653) + at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:186) + at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:772) + at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) + at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119) + at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:235) + at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:284) + at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:180) + at org.eclipse.ui.internal.intro.universal.IntroData.parse(IntroData.java:159) + at org.eclipse.ui.internal.intro.universal.IntroData.initialize(IntroData.java:63) + at org.eclipse.ui.internal.intro.universal.IntroData.(IntroData.java:47) + at org.eclipse.ui.internal.intro.universal.CustomizationContentsArea.loadData(CustomizationContentsArea.java:624) + at org.eclipse.ui.internal.intro.universal.CustomizationContentsArea.addPages(CustomizationContentsArea.java:489) + at org.eclipse.ui.internal.intro.universal.CustomizationContentsArea.createContents(CustomizationContentsArea.java:453) + at org.eclipse.ui.internal.intro.universal.CustomizationDialog.createDialogArea(CustomizationDialog.java:44) + at org.eclipse.jface.dialogs.Dialog.createContents(Dialog.java:760) + at org.eclipse.jface.window.Window.create(Window.java:431) + at org.eclipse.jface.dialogs.Dialog.create(Dialog.java:1089) + at org.eclipse.jface.window.Window.open(Window.java:790) + at org.eclipse.ui.internal.intro.universal.CustomizeAction.run(CustomizeAction.java:35) + at org.eclipse.ui.internal.intro.universal.CustomizeAction.run(CustomizeAction.java:29) + at org.eclipse.jface.action.Action.runWithEvent(Action.java:498) + at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:584) + at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:501) + at org.eclipse.jface.action.ActionContributionItem$6.handleEvent(ActionContributionItem.java:452) + at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) + at org.eclipse.swt.widgets.Display.sendEvent(Display.java:3543) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1250) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1273) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258) + at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1079) + at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3441) + at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3100) + at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2405) + at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2369) + at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2221) + at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:500) + at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) + at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:493) + at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) + at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113) + at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:194) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:368) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) + at java.lang.reflect.Method.invoke(Method.java:597) + at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:559) + at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514) + at org.eclipse.equinox.launcher.Main.run(Main.java:1311) +!SESSION 2012-02-04 15:23:30.048 ----------------------------------------------- +eclipse.buildId=unknown +java.version=1.6.0_29 +java.vendor=Apple Inc. +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -keyring /Users/jcotton81/.eclipse_keyring -showlocation +Command-line arguments: -os macosx -ws cocoa -arch x86_64 -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -data /Users/jcotton81/Documents/Programming/OpenPilot/androidgcs -product org.eclipse.epp.package.cpp.product -keyring /Users/jcotton81/.eclipse_keyring -showlocation + +!ENTRY org.eclipse.core.net 1 0 2012-02-04 15:23:34.575 +!MESSAGE System property http.nonProxyHosts has been set to local|*.local|169.254/16|*.169.254/16 by an external source. This value will be overwritten using the values from the preferences diff --git a/androidgcs/.metadata/.mylyn/repositories.xml.zip b/androidgcs/.metadata/.mylyn/repositories.xml.zip new file mode 100644 index 0000000000000000000000000000000000000000..e4df3bd3582f499f1a60b5def214b8ff52af6617 GIT binary patch literal 403 zcmWIWW@Zs#-~hsBMJ^5uNI(F{E=n!PFU~Bdj(; zVVO}bA}k9RU9H|_{jM!-va0dQyZ@?^bz^fywc_@+7(B7PS7R*c8`dl8&6Bbx*kFpf z!UfTNChLMenCzB(Vj$U{HcO2EMwQWWeBm$C<8L3AOn9FDyjhXMjCb8$XV&SwY{4(ytny2L z>Zr1KZsz5i=REypu2G!!Fu39-+x}N6Dmous-A{8_xY)$`S9N}$_2O##r|q}OnXHQb zs!#4`+gH4ys;~2NX}{PedAH=+g>TFBZddPTZ;$@K|4-sWx%33i%5DEskL3q=vvV9^ w68pi($iR@z%)k)f&B!FefCxZjIZyzi0`%Yv@MdKLsbB;`J0NWjG?jq?0GoN09smFU literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.mylyn/tasks.xml.zip b/androidgcs/.metadata/.mylyn/tasks.xml.zip new file mode 100644 index 0000000000000000000000000000000000000000..2c8620af394508c77be5ef0f6f867a56804938c0 GIT binary patch literal 250 zcmWIWW@Zs#-~dAIY8M9vB)|h?mn0Tv=VTU_=vCzAY~Hy3#MwX%Z(Xf(XU=a9HM(LP z5ae;z`<(yDGv3=nxp)gNZw(02(DOXw?RnEr%s1&+P<07Q|H{blRA2V9L+CH zm|nGXSgTK4vh2Bds8$6-=~ITSEzeY)TZ~o*1y2$ABUEh2^7U=bm&CMNj0^$Z>>R?m rvc?5KcT54|0B=Sn5e9@?k>x;cMFq$%5AbGX1IaQ1p%su`1y%|G7vM-E literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.cdt.core/.log b/androidgcs/.metadata/.plugins/org.eclipse.cdt.core/.log new file mode 100644 index 000000000..bce672614 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.cdt.core/.log @@ -0,0 +1 @@ +*** SESSION Feb 04, 2012 14:21:39.72 ------------------------------------------- diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version b/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version new file mode 100644 index 000000000..25cb955ba --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index b/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..9c245ea2cfab3511d0f8b7802966a5b2bb67b287 GIT binary patch literal 57 zcmZQ%U|?WmVAN+|WMUA>FG|--P0q4Yy oITE#s5Hp-2#a#t%!FeA{J(nSSiHf?N|MotxHB4MgVOxlqE}m~5?f?J) literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources b/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources new file mode 100644 index 0000000000000000000000000000000000000000..f783b188fb03e942944121a16ffc8983afa430df GIT binary patch literal 614 zcmZ?R*xjhShe1S2b=vdAllRFf=Oz}Hq!uZZBqrsgaw!KVmMFNTCMg)0C>WYr8JPf) zf^%?)f{}rt5m$0fYGRQ~YEDUFe11{7UTShqWs%=_gPH`$%3P^!# zML}j!Vo7Fx9*WW|m{LPyBMW0o12Z!d14Bc+THvNbwU}6#8UwZ9a0}c5h+A-|%B{?) w%+o7LEY2?0E6s$uTVJoFC^gmAi0eSa@6X^M3jEwty}SIF!)TDD>X8;?0Hs9PH2?qr literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.cdt.ui.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.cdt.ui.prefs new file mode 100644 index 000000000..3f144b036 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.cdt.ui.prefs @@ -0,0 +1,5 @@ +#Sat Feb 04 15:21:25 CST 2012 +spelling_locale_initialized=true +useAnnotationsPrefPage=true +eclipse.preferences.version=1 +useQuickDiffPrefPage=true diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..360fc96b9 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 15:21:25 CST 2012 +version=1 +eclipse.preferences.version=1 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.usagedata.recording.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.usagedata.recording.prefs new file mode 100644 index 000000000..87706c344 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.usagedata.recording.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 14:21:44 CST 2012 +org.eclipse.epp.usagedata.recording.last-upload=1328386904231 +eclipse.preferences.version=1 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..bdcfb11b5 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,15 @@ +#Sat Feb 04 15:21:25 CST 2012 +useQuickDiffPrefPage=true +proposalOrderMigrated=true +tabWidthPropagated=true +content_assist_proposals_background=255,255,255 +org.eclipse.jdt.ui.javadoclocations.migrated=true +useAnnotationsPrefPage=true +org.eclipse.jface.textfont=1|Monaco|11.0|0|COCOA|1|; +org.eclipse.jdt.internal.ui.navigator.layout=2 +org.eclipse.jdt.ui.editor.tab.width= +org.eclipse.jdt.ui.formatterprofiles.version=11 +spelling_locale_initialized=true +eclipse.preferences.version=1 +content_assist_proposals_foreground=0,0,0 +fontPropagated=true diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs new file mode 100644 index 000000000..7ea301b2d --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 14:21:42 CST 2012 +eclipse.preferences.version=1 +mylyn.attention.migrated=true diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.cvs.ui.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.cvs.ui.prefs new file mode 100644 index 000000000..62dee9f90 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.cvs.ui.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 15:21:25 CST 2012 +pref_first_startup=false +eclipse.preferences.version=1 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs new file mode 100644 index 000000000..06b301613 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 15:21:25 CST 2012 +eclipse.preferences.version=1 +org.eclipse.team.ui.first_time=false diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs new file mode 100644 index 000000000..90e1e2da9 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 15:21:25 CST 2012 +eclipse.preferences.version=1 +overviewRuler_migration=migrated_3.1 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs new file mode 100644 index 000000000..b945f2889 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs @@ -0,0 +1,5 @@ +#Sat Feb 04 15:21:25 CST 2012 +eclipse.preferences.version=1 +tipsAndTricks=true +platformState=1328386704250 +PROBLEMS_FILTERS_MIGRATE=true diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs new file mode 100644 index 000000000..a97c1c1ab --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 15:21:25 CST 2012 +eclipse.preferences.version=1 +showIntro=false diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs new file mode 100644 index 000000000..005c5e9bc --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 14:21:42 CST 2012 +eclipse.preferences.version=1 +ENABLED_DECORATORS=com.android.ide.eclipse.adt.project.FolderDecorator\:true,org.eclipse.cdt.ui.indexedFiles\:false,org.eclipse.jdt.ui.override.decorator\:true,org.eclipse.jdt.ui.interface.decorator\:false,org.eclipse.jdt.ui.buildpath.decorator\:true,org.eclipse.mylyn.context.ui.decorator.interest\:true,org.eclipse.mylyn.tasks.ui.decorators.task\:true,org.eclipse.mylyn.team.ui.changeset.decorator\:true,org.eclipse.team.cvs.ui.decorator\:true,org.eclipse.ui.LinkedResourceDecorator\:true,org.eclipse.ui.ContentTypeDecorator\:true, diff --git a/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/upload0.csv b/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/upload0.csv new file mode 100644 index 000000000..bc6540615 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/upload0.csv @@ -0,0 +1,251 @@ +what,kind,bundleId,bundleVersion,description,time +activated,perspective,org.eclipse.cdt.ui,,"org.eclipse.cdt.ui.CPerspective",1328386903139 +started,bundle,org.eclipse.osgi,3.5.2.R35x_v20100126,"org.eclipse.osgi",1328386903141 +started,bundle,org.eclipse.equinox.simpleconfigurator,1.0.101.R35x_v20090807-1100,"org.eclipse.equinox.simpleconfigurator",1328386903142 +started,bundle,com.ibm.icu,4.0.1.v20090822,"com.ibm.icu",1328386903143 +started,bundle,org.eclipse.cdt.core,5.1.2.201002161416,"org.eclipse.cdt.core",1328386903143 +started,bundle,org.eclipse.cdt.make.ui,6.0.1.201002161416,"org.eclipse.cdt.make.ui",1328386903144 +started,bundle,org.eclipse.cdt.ui,5.1.2.201002161416,"org.eclipse.cdt.ui",1328386903147 +started,bundle,org.eclipse.core.contenttype,3.4.1.R35x_v20090826-0451,"org.eclipse.core.contenttype",1328386903148 +started,bundle,org.eclipse.core.databinding.observable,1.2.0.M20090902-0800,"org.eclipse.core.databinding.observable",1328386903148 +started,bundle,org.eclipse.core.expressions,3.4.101.R35x_v20100209,"org.eclipse.core.expressions",1328386903149 +started,bundle,org.eclipse.core.filebuffers,3.5.0.v20090526-2000,"org.eclipse.core.filebuffers",1328386903149 +started,bundle,org.eclipse.core.filesystem,1.2.1.R35x_v20091203-1235,"org.eclipse.core.filesystem",1328386903150 +started,bundle,org.eclipse.core.jobs,3.4.100.v20090429-1800,"org.eclipse.core.jobs",1328386903151 +started,bundle,org.eclipse.core.net,1.2.1.r35x_20090812-1200,"org.eclipse.core.net",1328386903152 +started,bundle,org.eclipse.core.resources,3.5.2.R35x_v20091203-1235,"org.eclipse.core.resources",1328386903153 +started,bundle,org.eclipse.core.runtime,3.5.0.v20090525,"org.eclipse.core.runtime",1328386903153 +started,bundle,org.eclipse.core.runtime.compatibility,3.2.0.v20090413,"org.eclipse.core.runtime.compatibility",1328386903154 +started,bundle,org.eclipse.core.runtime.compatibility.auth,3.2.100.v20090413,"org.eclipse.core.runtime.compatibility.auth",1328386903154 +started,bundle,org.eclipse.ecf,3.0.0.v20090831-1906,"org.eclipse.ecf",1328386903155 +started,bundle,org.eclipse.ecf.filetransfer,3.0.0.v20090831-1906,"org.eclipse.ecf.filetransfer",1328386903155 +started,bundle,org.eclipse.ecf.identity,3.0.0.v20090831-1906,"org.eclipse.ecf.identity",1328386903156 +started,bundle,org.eclipse.ecf.provider.filetransfer,3.0.1.v20090831-1906,"org.eclipse.ecf.provider.filetransfer",1328386903157 +started,bundle,org.eclipse.ecf.provider.filetransfer.httpclient,3.0.1.v20090831-1906,"org.eclipse.ecf.provider.filetransfer.httpclient",1328386903158 +started,bundle,org.eclipse.epp.usagedata.gathering,1.1.1.R201001291118,"org.eclipse.epp.usagedata.gathering",1328386903159 +started,bundle,org.eclipse.epp.usagedata.recording,1.1.1.R201001291118,"org.eclipse.epp.usagedata.recording",1328386903161 +started,bundle,org.eclipse.equinox.app,1.2.1.R35x_v20091203,"org.eclipse.equinox.app",1328386903164 +started,bundle,org.eclipse.equinox.common,3.5.1.R35x_v20090807-1100,"org.eclipse.equinox.common",1328386903165 +started,bundle,org.eclipse.equinox.ds,1.1.1.R35x_v20090806,"org.eclipse.equinox.ds",1328386903166 +started,bundle,org.eclipse.equinox.frameworkadmin,1.0.100.v20090520-1905,"org.eclipse.equinox.frameworkadmin",1328386903166 +started,bundle,org.eclipse.equinox.frameworkadmin.equinox,1.0.101.R35x_v20091214,"org.eclipse.equinox.frameworkadmin.equinox",1328386903166 +started,bundle,org.eclipse.equinox.p2.core,1.0.101.R35x_v20090819,"org.eclipse.equinox.p2.core",1328386903167 +started,bundle,org.eclipse.equinox.p2.director,1.0.101.R35x_v20100112,"org.eclipse.equinox.p2.director",1328386903168 +started,bundle,org.eclipse.equinox.p2.directorywatcher,1.0.100.v20090525,"org.eclipse.equinox.p2.directorywatcher",1328386903168 +started,bundle,org.eclipse.equinox.p2.engine,1.0.102.R35x_v20091117,"org.eclipse.equinox.p2.engine",1328386903169 +started,bundle,org.eclipse.equinox.p2.exemplarysetup,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.exemplarysetup",1328386903169 +started,bundle,org.eclipse.equinox.p2.garbagecollector,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.garbagecollector",1328386903170 +started,bundle,org.eclipse.equinox.p2.metadata,1.0.101.R35x_v20100112,"org.eclipse.equinox.p2.metadata",1328386903170 +started,bundle,org.eclipse.equinox.p2.metadata.repository,1.0.101.R35x_v20090812,"org.eclipse.equinox.p2.metadata.repository",1328386903171 +started,bundle,org.eclipse.equinox.p2.reconciler.dropins,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.reconciler.dropins",1328386903171 +started,bundle,org.eclipse.equinox.p2.repository,1.0.1.R35x_v20100105,"org.eclipse.equinox.p2.repository",1328386903172 +started,bundle,org.eclipse.equinox.p2.ui.sdk.scheduler,1.0.0.v20090520-1905,"org.eclipse.equinox.p2.ui.sdk.scheduler",1328386903172 +started,bundle,org.eclipse.equinox.p2.updatechecker,1.1.0.v20090520-1905,"org.eclipse.equinox.p2.updatechecker",1328386903172 +started,bundle,org.eclipse.equinox.preferences,3.2.301.R35x_v20091117,"org.eclipse.equinox.preferences",1328386903175 +started,bundle,org.eclipse.equinox.registry,3.4.100.v20090520-1800,"org.eclipse.equinox.registry",1328386903176 +started,bundle,org.eclipse.equinox.security,1.0.100.v20090520-1800,"org.eclipse.equinox.security",1328386903177 +started,bundle,org.eclipse.equinox.simpleconfigurator.manipulator,1.0.101.R35x_v20100209,"org.eclipse.equinox.simpleconfigurator.manipulator",1328386903177 +started,bundle,org.eclipse.equinox.util,1.0.100.v20090520-1800,"org.eclipse.equinox.util",1328386903178 +started,bundle,org.eclipse.help,3.4.1.v20090805_35x,"org.eclipse.help",1328386903179 +started,bundle,org.eclipse.jface,3.5.2.M20100120-0800,"org.eclipse.jface",1328386903179 +started,bundle,org.eclipse.jsch.core,1.1.100.I20090430-0408,"org.eclipse.jsch.core",1328386903180 +started,bundle,org.eclipse.ltk.core.refactoring,3.5.0.v20090513-2000,"org.eclipse.ltk.core.refactoring",1328386903180 +started,bundle,org.eclipse.mylyn.bugzilla.core,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.core",1328386903181 +started,bundle,org.eclipse.mylyn.bugzilla.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.ui",1328386903181 +started,bundle,org.eclipse.mylyn.commons.net,3.2.0.v20090617-0100-e3x,"org.eclipse.mylyn.commons.net",1328386903182 +started,bundle,org.eclipse.mylyn.commons.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.commons.ui",1328386903183 +started,bundle,org.eclipse.mylyn.context.core,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.core",1328386903183 +started,bundle,org.eclipse.mylyn.context.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.ui",1328386903184 +started,bundle,org.eclipse.mylyn.monitor.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.monitor.ui",1328386903185 +started,bundle,org.eclipse.mylyn.tasks.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.tasks.ui",1328386903186 +started,bundle,org.eclipse.mylyn.team.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.team.ui",1328386903186 +started,bundle,org.eclipse.team.core,3.5.1.r35x_20100113-0800,"org.eclipse.team.core",1328386903187 +started,bundle,org.eclipse.team.cvs.core,3.3.200.I20090430-0408,"org.eclipse.team.cvs.core",1328386903188 +started,bundle,org.eclipse.team.cvs.ui,3.3.202.r35x_20090930-0800,"org.eclipse.team.cvs.ui",1328386903189 +started,bundle,org.eclipse.team.ui,3.5.0.I20090430-0408,"org.eclipse.team.ui",1328386903189 +started,bundle,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui",1328386903191 +started,bundle,org.eclipse.ui.console,3.4.0.v20090513,"org.eclipse.ui.console",1328386903191 +started,bundle,org.eclipse.ui.editors,3.5.0.v20090527-2000,"org.eclipse.ui.editors",1328386903195 +started,bundle,org.eclipse.ui.forms,3.4.1.v20090714_35x,"org.eclipse.ui.forms",1328386903196 +started,bundle,org.eclipse.ui.ide,3.5.2.M20100113-0800,"org.eclipse.ui.ide",1328386903198 +started,bundle,org.eclipse.ui.intro,3.3.2.v20100111_35x,"org.eclipse.ui.intro",1328386903198 +started,bundle,org.eclipse.ui.intro.universal,3.2.300.v20090526,"org.eclipse.ui.intro.universal",1328386903198 +started,bundle,org.eclipse.ui.navigator,3.4.2.M20100120-0800,"org.eclipse.ui.navigator",1328386903199 +started,bundle,org.eclipse.ui.navigator.resources,3.4.1.M20090826-0800,"org.eclipse.ui.navigator.resources",1328386903200 +started,bundle,org.eclipse.ui.net,1.2.1.r35x_20090812-1200,"org.eclipse.ui.net",1328386903200 +started,bundle,org.eclipse.ui.views,3.4.1.M20090826-0800,"org.eclipse.ui.views",1328386903201 +started,bundle,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"org.eclipse.ui.workbench",1328386903202 +started,bundle,org.eclipse.ui.workbench.texteditor,3.5.1.r352_v20100105,"org.eclipse.ui.workbench.texteditor",1328386903203 +started,bundle,org.eclipse.update.configurator,3.3.0.v20090312,"org.eclipse.update.configurator",1328386903207 +started,bundle,org.eclipse.update.core,3.2.300.v20090525,"org.eclipse.update.core",1328386903209 +started,bundle,org.eclipse.update.scheduler,3.2.200.v20081127,"org.eclipse.update.scheduler",1328386903210 +started,bundle,org.eclipse.jdt.core,3.5.2.v_981_R35x,"org.eclipse.jdt.core",1328386903211 +started,bundle,org.eclipse.jdt.core.manipulation,1.3.0.v20090603,"org.eclipse.jdt.core.manipulation",1328386903212 +started,bundle,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui",1328386903218 +os,sysinfo,,,"macosx",1328386903226 +arch,sysinfo,,,"x86_64",1328386903226 +ws,sysinfo,,,"cocoa",1328386903226 +locale,sysinfo,,,"en_US",1328386903226 +processors,sysinfo,,,"4",1328386903226 +java.runtime.name,sysinfo,,,"Java(TM) SE Runtime Environment",1328386903226 +java.runtime.version,sysinfo,,,"1.6.0_29-b11-402-11M3527",1328386903227 +java.specification.name,sysinfo,,,"Java Platform API Specification",1328386903227 +java.specification.vendor,sysinfo,,,"Sun Microsystems Inc.",1328386903227 +java.specification.version,sysinfo,,,"1.6",1328386903227 +java.vendor,sysinfo,,,"Apple Inc.",1328386903227 +java.version,sysinfo,,,"1.6.0_29",1328386903227 +java.vm.info,sysinfo,,,"mixed mode",1328386903227 +java.vm.name,sysinfo,,,"Java HotSpot(TM) 64-Bit Server VM",1328386903227 +java.vm.specification.name,sysinfo,,,"Java Virtual Machine Specification",1328386903227 +java.vm.specification.vendor,sysinfo,,,"Sun Microsystems Inc.",1328386903227 +java.vm.specification.version,sysinfo,,,"1.0",1328386903227 +java.vm.vendor,sysinfo,,,"Apple Inc.",1328386903227 +java.vm.version,sysinfo,,,"20.4-b02-402",1328386903227 +started,bundle,org.eclipse.equinox.p2.extensionlocation,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.extensionlocation",1328386903389 +started,bundle,org.eclipse.equinox.p2.artifact.repository,1.0.101.R35x_v20090721,"org.eclipse.equinox.p2.artifact.repository",1328386903414 +started,bundle,org.eclipse.equinox.p2.publisher,1.0.1.R35x_20100105,"org.eclipse.equinox.p2.publisher",1328386903450 +started,bundle,org.eclipse.equinox.p2.touchpoint.eclipse,1.0.101.R35x_20090820-1821,"org.eclipse.equinox.p2.touchpoint.eclipse",1328386903464 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328386903480 +activated,view,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui.internal.introview",1328386903487 +error,log,,,"/Users/jcotton81/Documents/Programming/eclipse/Eclipse.app/Contents/MacOS/introData.xml (No such file or directory)",1328386904897 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328386905209 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328386906797 +started,bundle,org.eclipse.equinox.p2.updatesite,1.0.101.R35x_20100105,"org.eclipse.equinox.p2.updatesite",1328386912464 +activated,view,org.eclipse.ui.navigator.resources,3.4.1.M20090826-0800,"org.eclipse.ui.navigator.ProjectExplorer",1328386912583 +activated,view,org.eclipse.ui.navigator.resources,3.4.1.M20090826-0800,"org.eclipse.ui.navigator.ProjectExplorer",1328386912596 +closed,view,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui.internal.introview",1328386912607 +started,bundle,org.eclipse.equinox.p2.ui,1.0.101.R35x_v20090819,"org.eclipse.equinox.p2.ui",1328386912856 +started,bundle,org.eclipse.equinox.p2.ui.sdk,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.ui.sdk",1328386912895 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328386920116 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328387108087 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328387114332 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328387670491 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328387680147 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328389984496 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328389985341 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390196855 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390210754 +started,bundle,com.android.ide.eclipse.ddms,10.0.1.v201103111512-110841,"com.android.ide.eclipse.ddms",1328390214192 +started,bundle,org.eclipse.wst.sse.core,1.1.402.v201001251516,"org.eclipse.wst.sse.core",1328390214246 +started,bundle,com.android.ide.eclipse.adt,10.0.1.v201103111512-110841,"com.android.ide.eclipse.adt",1328390214248 +started,bundle,org.eclipse.ltk.ui.refactoring,3.4.101.r352_v20100209,"org.eclipse.ltk.ui.refactoring",1328390214467 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390455517 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390462855 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390470613 +opened,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.PackageExplorer",1328390470944 +started,bundle,org.eclipse.search,3.5.1.r351_v20090708-0800,"org.eclipse.search",1328390471037 +opened,view,org.eclipse.mylyn.tasks.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.tasks.ui.views.tasks",1328390471127 +activated,perspective,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.JavaPerspective",1328390471151 +activated,view,org.eclipse.ui.ide,3.5.2.M20100113-0800,"org.eclipse.ui.views.ProblemView",1328390471175 +executed,command,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui.perspectives.showPerspective",1328390471213 +executed,command,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui.perspectives.showPerspective",1328390471213 +opened,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.JavadocView",1328390474490 +activated,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.JavadocView",1328390474500 +opened,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.SourceView",1328390475141 +activated,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.SourceView",1328390475161 +activated,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.JavadocView",1328390475451 +activated,view,org.eclipse.ui.ide,3.5.2.M20100113-0800,"org.eclipse.ui.views.ProblemView",1328390475842 +closed,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390485206 +stopped,bundle,org.eclipse.cdt.debug.mi.ui,6.0.0.201002161416,"org.eclipse.cdt.debug.mi.ui",1328390485703 +stopped,bundle,org.eclipse.cdt.debug.gdbjtag.ui,5.0.100.201002161416,"org.eclipse.cdt.debug.gdbjtag.ui",1328390485704 +stopped,bundle,org.eclipse.cdt.debug.gdbjtag.core,5.0.100.201002161416,"org.eclipse.cdt.debug.gdbjtag.core",1328390485704 +stopped,bundle,org.eclipse.cdt.debug.mi.core,6.0.0.201002161416,"org.eclipse.cdt.debug.mi.core",1328390485705 +stopped,bundle,org.eclipse.cdt.dsf.gdb.ui,2.0.0.201002161416,"org.eclipse.cdt.dsf.gdb.ui",1328390485706 +stopped,bundle,org.eclipse.cdt.dsf.ui,2.0.1.201002161416,"org.eclipse.cdt.dsf.ui",1328390485707 +stopped,bundle,org.eclipse.cdt.launch,6.0.0.201002161416,"org.eclipse.cdt.launch",1328390485707 +stopped,bundle,org.eclipse.cdt.debug.ui,6.0.0.201002161416,"org.eclipse.cdt.debug.ui",1328390485708 +stopped,bundle,org.eclipse.cdt.dsf.gdb,2.0.0.201002161416,"org.eclipse.cdt.dsf.gdb",1328390485709 +stopped,bundle,org.eclipse.cdt.dsf,2.0.0.201002161416,"org.eclipse.cdt.dsf",1328390485709 +stopped,bundle,org.eclipse.cdt.debug.core,6.0.0.201002161416,"org.eclipse.cdt.debug.core",1328390485710 +stopped,bundle,org.eclipse.cdt.managedbuilder.ui,5.1.0.201002161416,"org.eclipse.cdt.managedbuilder.ui",1328390485710 +stopped,bundle,org.eclipse.cdt.make.ui,6.0.1.201002161416,"org.eclipse.cdt.make.ui",1328390485711 +stopped,bundle,org.eclipse.cdt.managedbuilder.gnu.ui,5.0.100.201002161416,"org.eclipse.cdt.managedbuilder.gnu.ui",1328390485711 +stopped,bundle,org.eclipse.cdt.managedbuilder.core,6.0.0.201002161416,"org.eclipse.cdt.managedbuilder.core",1328390485712 +stopped,bundle,org.eclipse.cdt.make.core,6.0.0.201002161416,"org.eclipse.cdt.make.core",1328390485713 +stopped,bundle,org.eclipse.cdt.mylyn.ui,1.0.100.201002161416,"org.eclipse.cdt.mylyn.ui",1328390485713 +stopped,bundle,org.eclipse.cdt.ui,5.1.2.201002161416,"org.eclipse.cdt.ui",1328390485713 +stopped,bundle,org.eclipse.cdt.core,5.1.2.201002161416,"org.eclipse.cdt.core",1328390485714 +stopped,bundle,org.eclipse.mylyn.bugzilla.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.ui",1328390485714 +stopped,bundle,org.eclipse.mylyn.ide.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.ide.ui",1328390485714 +stopped,bundle,org.eclipse.mylyn.team.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.team.ui",1328390485715 +stopped,bundle,org.eclipse.mylyn.resources.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.resources.ui",1328390485715 +stopped,bundle,org.eclipse.mylyn.wikitext.tasks.ui,1.1.3.v20100217-0100-e3x,"org.eclipse.mylyn.wikitext.tasks.ui",1328390485716 +stopped,bundle,org.eclipse.mylyn.context.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.ui",1328390485716 +stopped,bundle,org.eclipse.mylyn.help.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.help.ui",1328390485716 +stopped,bundle,org.eclipse.mylyn.tasks.bugs,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.tasks.bugs",1328390485717 +stopped,bundle,org.eclipse.mylyn.tasks.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.tasks.ui",1328390485719 +stopped,bundle,org.eclipse.ant.ui,3.4.2.v20091204_r352,"org.eclipse.ant.ui",1328390485719 +stopped,bundle,com.android.ide.eclipse.adt,10.0.1.v201103111512-110841,"com.android.ide.eclipse.adt",1328390485719 +stopped,bundle,org.eclipse.jdt.junit,3.5.2.r352_v20100113-0800,"org.eclipse.jdt.junit",1328390485720 +stopped,bundle,org.eclipse.jdt.debug.ui,3.4.1.v20090811_r351,"org.eclipse.jdt.debug.ui",1328390485721 +stopped,bundle,org.eclipse.jdt.apt.ui,3.3.200.v20090930-2100_R35x,"org.eclipse.jdt.apt.ui",1328390485722 +stopped,bundle,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui",1328390485726 +stopped,bundle,org.eclipse.wst.dtd.ui,1.0.400.v200904300717,"org.eclipse.wst.dtd.ui",1328390485730 +stopped,bundle,org.eclipse.wst.xsd.ui,1.2.204.v200909021537,"org.eclipse.wst.xsd.ui",1328390485747 +stopped,bundle,org.eclipse.wst.xml.ui,1.1.2.v201001222130,"org.eclipse.wst.xml.ui",1328390485747 +stopped,bundle,org.eclipse.wst.common.ui,1.1.402.v200901262305,"org.eclipse.wst.common.ui",1328390485748 +stopped,bundle,org.eclipse.wst.sse.ui,1.1.102.v200910200227,"org.eclipse.wst.sse.ui",1328390485749 +stopped,bundle,org.eclipse.search,3.5.1.r351_v20090708-0800,"org.eclipse.search",1328390485750 +stopped,bundle,org.eclipse.ltk.ui.refactoring,3.4.101.r352_v20100209,"org.eclipse.ltk.ui.refactoring",1328390485750 +stopped,bundle,org.eclipse.team.cvs.ui,3.3.202.r35x_20090930-0800,"org.eclipse.team.cvs.ui",1328390485751 +stopped,bundle,org.eclipse.team.ui,3.5.0.I20090430-0408,"org.eclipse.team.ui",1328390485751 +stopped,bundle,org.eclipse.compare,3.5.2.r35x_20100113-0800,"org.eclipse.compare",1328390485752 +stopped,bundle,org.eclipse.ui.externaltools,3.2.0.v20090504,"org.eclipse.ui.externaltools",1328390485753 +stopped,bundle,org.eclipse.debug.ui,3.5.2.v20091028_r352,"org.eclipse.debug.ui",1328390485756 +stopped,bundle,org.eclipse.mylyn.wikitext.ui,1.1.3.v20100217-0100-e3x,"org.eclipse.mylyn.wikitext.ui",1328390485757 +stopped,bundle,com.android.ide.eclipse.hierarchyviewer,10.0.1.v201103111512-110841,"com.android.ide.eclipse.hierarchyviewer",1328390485757 +stopped,bundle,com.android.ide.eclipse.ddms,10.0.1.v201103111512-110841,"com.android.ide.eclipse.ddms",1328390485757 +stopped,bundle,org.eclipse.ui.console,3.4.0.v20090513,"org.eclipse.ui.console",1328390485757 +stopped,bundle,org.eclipse.mylyn.commons.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.commons.ui",1328390485757 +stopped,bundle,org.eclipse.ui.editors,3.5.0.v20090527-2000,"org.eclipse.ui.editors",1328390485758 +stopped,bundle,org.eclipse.ui.navigator.resources,3.4.1.M20090826-0800,"org.eclipse.ui.navigator.resources",1328390485758 +activated,perspective,org.eclipse.jdt.ui,,"org.eclipse.jdt.ui.JavaPerspective",1328390616647 +started,bundle,org.eclipse.osgi,3.5.2.R35x_v20100126,"org.eclipse.osgi",1328390616648 +started,bundle,org.eclipse.equinox.simpleconfigurator,1.0.101.R35x_v20090807-1100,"org.eclipse.equinox.simpleconfigurator",1328390616653 +started,bundle,com.ibm.icu,4.0.1.v20090822,"com.ibm.icu",1328390616654 +started,bundle,org.eclipse.core.contenttype,3.4.1.R35x_v20090826-0451,"org.eclipse.core.contenttype",1328390616654 +started,bundle,org.eclipse.core.databinding.observable,1.2.0.M20090902-0800,"org.eclipse.core.databinding.observable",1328390616655 +started,bundle,org.eclipse.core.expressions,3.4.101.R35x_v20100209,"org.eclipse.core.expressions",1328390616656 +started,bundle,org.eclipse.core.filebuffers,3.5.0.v20090526-2000,"org.eclipse.core.filebuffers",1328390616656 +started,bundle,org.eclipse.core.jobs,3.4.100.v20090429-1800,"org.eclipse.core.jobs",1328390616656 +started,bundle,org.eclipse.core.net,1.2.1.r35x_20090812-1200,"org.eclipse.core.net",1328390616657 +started,bundle,org.eclipse.core.resources,3.5.2.R35x_v20091203-1235,"org.eclipse.core.resources",1328390616658 +started,bundle,org.eclipse.core.runtime,3.5.0.v20090525,"org.eclipse.core.runtime",1328390616659 +started,bundle,org.eclipse.core.runtime.compatibility,3.2.0.v20090413,"org.eclipse.core.runtime.compatibility",1328390616659 +started,bundle,org.eclipse.core.runtime.compatibility.auth,3.2.100.v20090413,"org.eclipse.core.runtime.compatibility.auth",1328390616660 +started,bundle,org.eclipse.ecf,3.0.0.v20090831-1906,"org.eclipse.ecf",1328390616660 +started,bundle,org.eclipse.ecf.filetransfer,3.0.0.v20090831-1906,"org.eclipse.ecf.filetransfer",1328390616661 +started,bundle,org.eclipse.ecf.identity,3.0.0.v20090831-1906,"org.eclipse.ecf.identity",1328390616662 +started,bundle,org.eclipse.ecf.provider.filetransfer,3.0.1.v20090831-1906,"org.eclipse.ecf.provider.filetransfer",1328390616663 +started,bundle,org.eclipse.ecf.provider.filetransfer.httpclient,3.0.1.v20090831-1906,"org.eclipse.ecf.provider.filetransfer.httpclient",1328390616663 +started,bundle,org.eclipse.epp.usagedata.gathering,1.1.1.R201001291118,"org.eclipse.epp.usagedata.gathering",1328390616664 +started,bundle,org.eclipse.epp.usagedata.recording,1.1.1.R201001291118,"org.eclipse.epp.usagedata.recording",1328390616668 +started,bundle,org.eclipse.equinox.app,1.2.1.R35x_v20091203,"org.eclipse.equinox.app",1328390616676 +started,bundle,org.eclipse.equinox.common,3.5.1.R35x_v20090807-1100,"org.eclipse.equinox.common",1328390616676 +started,bundle,org.eclipse.equinox.ds,1.1.1.R35x_v20090806,"org.eclipse.equinox.ds",1328390616677 +started,bundle,org.eclipse.equinox.frameworkadmin,1.0.100.v20090520-1905,"org.eclipse.equinox.frameworkadmin",1328390616679 +started,bundle,org.eclipse.equinox.frameworkadmin.equinox,1.0.101.R35x_v20091214,"org.eclipse.equinox.frameworkadmin.equinox",1328390616680 +started,bundle,org.eclipse.equinox.p2.core,1.0.101.R35x_v20090819,"org.eclipse.equinox.p2.core",1328390616681 +started,bundle,org.eclipse.equinox.p2.director,1.0.101.R35x_v20100112,"org.eclipse.equinox.p2.director",1328390616682 +started,bundle,org.eclipse.equinox.p2.directorywatcher,1.0.100.v20090525,"org.eclipse.equinox.p2.directorywatcher",1328390616688 +started,bundle,org.eclipse.equinox.p2.engine,1.0.102.R35x_v20091117,"org.eclipse.equinox.p2.engine",1328390616689 +started,bundle,org.eclipse.equinox.p2.exemplarysetup,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.exemplarysetup",1328390616690 +started,bundle,org.eclipse.equinox.p2.garbagecollector,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.garbagecollector",1328390616691 +started,bundle,org.eclipse.equinox.p2.metadata,1.0.101.R35x_v20100112,"org.eclipse.equinox.p2.metadata",1328390616692 +started,bundle,org.eclipse.equinox.p2.metadata.repository,1.0.101.R35x_v20090812,"org.eclipse.equinox.p2.metadata.repository",1328390616692 +started,bundle,org.eclipse.equinox.p2.reconciler.dropins,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.reconciler.dropins",1328390616693 +started,bundle,org.eclipse.equinox.p2.repository,1.0.1.R35x_v20100105,"org.eclipse.equinox.p2.repository",1328390616693 +started,bundle,org.eclipse.equinox.p2.ui.sdk.scheduler,1.0.0.v20090520-1905,"org.eclipse.equinox.p2.ui.sdk.scheduler",1328390616694 +started,bundle,org.eclipse.equinox.p2.updatechecker,1.1.0.v20090520-1905,"org.eclipse.equinox.p2.updatechecker",1328390616695 +started,bundle,org.eclipse.equinox.preferences,3.2.301.R35x_v20091117,"org.eclipse.equinox.preferences",1328390616695 +started,bundle,org.eclipse.equinox.registry,3.4.100.v20090520-1800,"org.eclipse.equinox.registry",1328390616696 +started,bundle,org.eclipse.equinox.security,1.0.100.v20090520-1800,"org.eclipse.equinox.security",1328390616697 +started,bundle,org.eclipse.equinox.simpleconfigurator.manipulator,1.0.101.R35x_v20100209,"org.eclipse.equinox.simpleconfigurator.manipulator",1328390616697 +started,bundle,org.eclipse.equinox.util,1.0.100.v20090520-1800,"org.eclipse.equinox.util",1328390616698 +started,bundle,org.eclipse.help,3.4.1.v20090805_35x,"org.eclipse.help",1328390616698 +started,bundle,org.eclipse.jface,3.5.2.M20100120-0800,"org.eclipse.jface",1328390616699 +started,bundle,org.eclipse.jsch.core,1.1.100.I20090430-0408,"org.eclipse.jsch.core",1328390616705 +started,bundle,org.eclipse.mylyn.bugzilla.core,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.core",1328390616705 +started,bundle,org.eclipse.mylyn.bugzilla.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.ui",1328390616706 +started,bundle,org.eclipse.mylyn.commons.net,3.2.0.v20090617-0100-e3x,"org.eclipse.mylyn.commons.net",1328390616706 +started,bundle,org.eclipse.mylyn.commons.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.commons.ui",1328390616707 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/usagedata.csv b/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/usagedata.csv new file mode 100644 index 000000000..510c72478 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/usagedata.csv @@ -0,0 +1,83 @@ +what,kind,bundleId,bundleVersion,description,time +started,bundle,org.eclipse.mylyn.context.core,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.core",1328390616707 +started,bundle,org.eclipse.mylyn.context.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.ui",1328390616708 +started,bundle,org.eclipse.mylyn.monitor.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.monitor.ui",1328390616708 +started,bundle,org.eclipse.mylyn.tasks.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.tasks.ui",1328390616709 +started,bundle,org.eclipse.mylyn.team.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.team.ui",1328390616710 +started,bundle,org.eclipse.search,3.5.1.r351_v20090708-0800,"org.eclipse.search",1328390616711 +started,bundle,org.eclipse.team.core,3.5.1.r35x_20100113-0800,"org.eclipse.team.core",1328390616712 +started,bundle,org.eclipse.team.cvs.core,3.3.200.I20090430-0408,"org.eclipse.team.cvs.core",1328390616712 +started,bundle,org.eclipse.team.cvs.ui,3.3.202.r35x_20090930-0800,"org.eclipse.team.cvs.ui",1328390616713 +started,bundle,org.eclipse.team.ui,3.5.0.I20090430-0408,"org.eclipse.team.ui",1328390616714 +started,bundle,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui",1328390616715 +started,bundle,org.eclipse.ui.console,3.4.0.v20090513,"org.eclipse.ui.console",1328390616716 +started,bundle,org.eclipse.ui.editors,3.5.0.v20090527-2000,"org.eclipse.ui.editors",1328390616717 +started,bundle,org.eclipse.ui.forms,3.4.1.v20090714_35x,"org.eclipse.ui.forms",1328390616717 +started,bundle,org.eclipse.ui.ide,3.5.2.M20100113-0800,"org.eclipse.ui.ide",1328390616718 +started,bundle,org.eclipse.ui.net,1.2.1.r35x_20090812-1200,"org.eclipse.ui.net",1328390616719 +started,bundle,org.eclipse.ui.views,3.4.1.M20090826-0800,"org.eclipse.ui.views",1328390616720 +started,bundle,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"org.eclipse.ui.workbench",1328390616720 +started,bundle,org.eclipse.ui.workbench.texteditor,3.5.1.r352_v20100105,"org.eclipse.ui.workbench.texteditor",1328390616721 +started,bundle,org.eclipse.update.configurator,3.3.0.v20090312,"org.eclipse.update.configurator",1328390616722 +started,bundle,org.eclipse.update.core,3.2.300.v20090525,"org.eclipse.update.core",1328390616722 +started,bundle,org.eclipse.update.scheduler,3.2.200.v20081127,"org.eclipse.update.scheduler",1328390616723 +started,bundle,org.eclipse.jdt.core,3.5.2.v_981_R35x,"org.eclipse.jdt.core",1328390616724 +started,bundle,org.eclipse.jdt.core.manipulation,1.3.0.v20090603,"org.eclipse.jdt.core.manipulation",1328390616725 +started,bundle,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui",1328390616730 +os,sysinfo,,,"macosx",1328390616740 +arch,sysinfo,,,"x86_64",1328390616740 +ws,sysinfo,,,"cocoa",1328390616740 +locale,sysinfo,,,"en_US",1328390616740 +processors,sysinfo,,,"4",1328390616740 +java.runtime.name,sysinfo,,,"Java(TM) SE Runtime Environment",1328390616740 +java.runtime.version,sysinfo,,,"1.6.0_29-b11-402-11M3527",1328390616740 +java.specification.name,sysinfo,,,"Java Platform API Specification",1328390616740 +java.specification.vendor,sysinfo,,,"Sun Microsystems Inc.",1328390616740 +java.specification.version,sysinfo,,,"1.6",1328390616740 +java.vendor,sysinfo,,,"Apple Inc.",1328390616740 +java.version,sysinfo,,,"1.6.0_29",1328390616740 +java.vm.info,sysinfo,,,"mixed mode",1328390616740 +java.vm.name,sysinfo,,,"Java HotSpot(TM) 64-Bit Server VM",1328390616740 +java.vm.specification.name,sysinfo,,,"Java Virtual Machine Specification",1328390616740 +java.vm.specification.vendor,sysinfo,,,"Sun Microsystems Inc.",1328390616740 +java.vm.specification.version,sysinfo,,,"1.0",1328390616740 +java.vm.vendor,sysinfo,,,"Apple Inc.",1328390616740 +java.vm.version,sysinfo,,,"20.4-b02-402",1328390616740 +started,bundle,org.eclipse.equinox.p2.extensionlocation,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.extensionlocation",1328390616768 +started,bundle,org.eclipse.equinox.p2.artifact.repository,1.0.101.R35x_v20090721,"org.eclipse.equinox.p2.artifact.repository",1328390616783 +started,bundle,org.eclipse.equinox.p2.publisher,1.0.1.R35x_20100105,"org.eclipse.equinox.p2.publisher",1328390616808 +started,bundle,org.eclipse.equinox.p2.touchpoint.eclipse,1.0.101.R35x_20090820-1821,"org.eclipse.equinox.p2.touchpoint.eclipse",1328390616820 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390619481 +started,bundle,org.eclipse.equinox.p2.updatesite,1.0.101.R35x_20100105,"org.eclipse.equinox.p2.updatesite",1328390623001 +started,bundle,org.eclipse.equinox.p2.ui,1.0.101.R35x_v20090819,"org.eclipse.equinox.p2.ui",1328390623371 +started,bundle,org.eclipse.equinox.p2.ui.sdk,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.ui.sdk",1328390623409 +started,bundle,org.eclipse.core.filesystem,1.2.1.R35x_v20091203-1235,"org.eclipse.core.filesystem",1328390630622 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390659248 +executed,command,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui.file.import",1328390659277 +closed,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390663881 +stopped,bundle,org.eclipse.cdt.debug.mi.ui,6.0.0.201002161416,"org.eclipse.cdt.debug.mi.ui",1328390664441 +stopped,bundle,org.eclipse.cdt.debug.gdbjtag.ui,5.0.100.201002161416,"org.eclipse.cdt.debug.gdbjtag.ui",1328390664442 +stopped,bundle,org.eclipse.cdt.debug.gdbjtag.core,5.0.100.201002161416,"org.eclipse.cdt.debug.gdbjtag.core",1328390664442 +stopped,bundle,org.eclipse.cdt.debug.mi.core,6.0.0.201002161416,"org.eclipse.cdt.debug.mi.core",1328390664443 +stopped,bundle,org.eclipse.cdt.dsf.gdb.ui,2.0.0.201002161416,"org.eclipse.cdt.dsf.gdb.ui",1328390664443 +stopped,bundle,org.eclipse.cdt.dsf.ui,2.0.1.201002161416,"org.eclipse.cdt.dsf.ui",1328390664444 +stopped,bundle,org.eclipse.cdt.launch,6.0.0.201002161416,"org.eclipse.cdt.launch",1328390664445 +stopped,bundle,org.eclipse.cdt.debug.ui,6.0.0.201002161416,"org.eclipse.cdt.debug.ui",1328390664446 +stopped,bundle,org.eclipse.cdt.dsf.gdb,2.0.0.201002161416,"org.eclipse.cdt.dsf.gdb",1328390664446 +stopped,bundle,org.eclipse.cdt.dsf,2.0.0.201002161416,"org.eclipse.cdt.dsf",1328390664447 +stopped,bundle,org.eclipse.cdt.debug.core,6.0.0.201002161416,"org.eclipse.cdt.debug.core",1328390664448 +stopped,bundle,org.eclipse.cdt.managedbuilder.ui,5.1.0.201002161416,"org.eclipse.cdt.managedbuilder.ui",1328390664449 +stopped,bundle,org.eclipse.cdt.make.ui,6.0.1.201002161416,"org.eclipse.cdt.make.ui",1328390664452 +stopped,bundle,org.eclipse.cdt.managedbuilder.gnu.ui,5.0.100.201002161416,"org.eclipse.cdt.managedbuilder.gnu.ui",1328390664453 +stopped,bundle,org.eclipse.cdt.managedbuilder.core,6.0.0.201002161416,"org.eclipse.cdt.managedbuilder.core",1328390664454 +stopped,bundle,org.eclipse.cdt.make.core,6.0.0.201002161416,"org.eclipse.cdt.make.core",1328390664455 +stopped,bundle,org.eclipse.cdt.mylyn.ui,1.0.100.201002161416,"org.eclipse.cdt.mylyn.ui",1328390664455 +stopped,bundle,org.eclipse.cdt.ui,5.1.2.201002161416,"org.eclipse.cdt.ui",1328390664458 +stopped,bundle,org.eclipse.cdt.core,5.1.2.201002161416,"org.eclipse.cdt.core",1328390664459 +stopped,bundle,org.eclipse.mylyn.bugzilla.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.ui",1328390664460 +stopped,bundle,org.eclipse.mylyn.ide.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.ide.ui",1328390664460 +stopped,bundle,org.eclipse.mylyn.team.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.team.ui",1328390664460 +stopped,bundle,org.eclipse.mylyn.resources.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.resources.ui",1328390664461 +stopped,bundle,org.eclipse.mylyn.wikitext.tasks.ui,1.1.3.v20100217-0100-e3x,"org.eclipse.mylyn.wikitext.tasks.ui",1328390664461 +stopped,bundle,org.eclipse.mylyn.context.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.ui",1328390664462 +stopped,bundle,org.eclipse.mylyn.help.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.help.ui",1328390664462 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache b/androidgcs/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache new file mode 100644 index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4 GIT binary patch literal 4 LcmZQzU|;|M00aO5 literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat b/androidgcs/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat new file mode 100644 index 0000000000000000000000000000000000000000..3aea61cb8e5c86745251f85e5305774c8841c019 GIT binary patch literal 96 zcmZQzU|?c^09G)??iJ)39~|V&2;?y`aCwFLd4|M$`1`to1eh4Oq0&MA{vjX{W(KeZ SA5SL`kA;B`q5)_CL=yl}T@PLW literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml new file mode 100644 index 000000000..a4ee3cbc9 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml @@ -0,0 +1,2 @@ + + diff --git a/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml new file mode 100644 index 000000000..9e390f501 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml @@ -0,0 +1,2 @@ + + diff --git a/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml new file mode 100644 index 000000000..8bc608925 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml @@ -0,0 +1,10 @@ + +
+
+ + + + + +
+
diff --git a/androidgcs/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml b/androidgcs/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml new file mode 100644 index 000000000..ab9bf177c --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml @@ -0,0 +1,9 @@ + +
+
+ + +
+
+
+
diff --git a/androidgcs/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml b/androidgcs/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml new file mode 100644 index 000000000..f118f0213 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml @@ -0,0 +1,4 @@ + +
+ +
diff --git a/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml new file mode 100644 index 000000000..5b583c4be --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml @@ -0,0 +1,5 @@ + +
+
+
+
diff --git a/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml new file mode 100644 index 000000000..931fd0157 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml new file mode 100644 index 000000000..8daaf65a1 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/androidgcs/.metadata/version.ini b/androidgcs/.metadata/version.ini new file mode 100644 index 000000000..c51ff745b --- /dev/null +++ b/androidgcs/.metadata/version.ini @@ -0,0 +1 @@ +org.eclipse.core.runtime=1 \ No newline at end of file diff --git a/androidgcs/.settings/org.eclipse.jdt.core.prefs b/androidgcs/.settings/org.eclipse.jdt.core.prefs index f3fe4d6d6..a149e8e84 100644 --- a/androidgcs/.settings/org.eclipse.jdt.core.prefs +++ b/androidgcs/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,12 @@ -#Tue Mar 01 01:16:25 CST 2011 +#Sat Feb 04 16:05:48 CST 2012 eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.source=1.5 diff --git a/androidgcs/lint.xml b/androidgcs/lint.xml new file mode 100644 index 000000000..ee0eead5b --- /dev/null +++ b/androidgcs/lint.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/androidgcs/default.properties b/androidgcs/project.properties similarity index 72% rename from androidgcs/default.properties rename to androidgcs/project.properties index fd1cedd24..5d85d779c 100644 --- a/androidgcs/default.properties +++ b/androidgcs/project.properties @@ -4,8 +4,8 @@ # This file must be checked in Version Control Systems. # # To customize properties used by the Ant build system use, -# "build.properties", and override values to adapt the script to your +# "ant.properties", and override values to adapt the script to your # project structure. # Project target. -target=Google Inc.:Google APIs:10 +target=Google Inc.:Google APIs:13 From 739dc0f9841c8afb737d892e025956ecd7cfb3de Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Feb 2012 18:30:04 -0600 Subject: [PATCH 050/284] Update the UAVObjects to the version on next. At some point a make script should generate these and copy from build/uavobjects-synth/java to this directory automatically. Also make sure java objects use CamelCase --- .../uavtalk/uavobjects/AHRSCalibration.java | 51 +- .../uavtalk/uavobjects/AHRSSettings.java | 32 +- .../uavtalk/uavobjects/AccessoryDesired.java | 139 +++++ .../uavtalk/uavobjects/ActuatorCommand.java | 12 +- .../uavtalk/uavobjects/ActuatorDesired.java | 2 +- .../uavtalk/uavobjects/ActuatorSettings.java | 496 ++++++++++-------- .../uavtalk/uavobjects/AhrsStatus.java | 10 +- .../uavtalk/uavobjects/AttitudeActual.java | 4 +- .../uavtalk/uavobjects/AttitudeRaw.java | 24 +- .../uavtalk/uavobjects/AttitudeSettings.java | 68 ++- .../uavtalk/uavobjects/BaroAltitude.java | 2 +- .../uavtalk/uavobjects/CameraDesired.java | 147 ++++++ .../uavobjects/CameraStabSettings.java | 205 ++++++++ ...emetrySettings.java => FaultSettings.java} | 45 +- .../uavtalk/uavobjects/FirmwareIAPObj.java | 97 +--- .../uavobjects/FlightBatterySettings.java | 177 +++++++ .../uavobjects/FlightBatteryState.java | 2 +- .../uavtalk/uavobjects/FlightPlanControl.java | 2 +- .../uavobjects/FlightPlanSettings.java | 2 +- .../uavtalk/uavobjects/FlightPlanStatus.java | 35 +- .../uavtalk/uavobjects/FlightStatus.java | 155 ++++++ .../uavobjects/FlightTelemetryStats.java | 20 +- .../uavtalk/uavobjects/GCSReceiver.java | 144 +++++ .../uavtalk/uavobjects/GCSTelemetryStats.java | 20 +- .../uavtalk/uavobjects/GPSPosition.java | 28 +- .../uavtalk/uavobjects/GPSSatellites.java | 48 +- .../openpilot/uavtalk/uavobjects/GPSTime.java | 10 +- .../uavtalk/uavobjects/GuidanceSettings.java | 76 +-- .../uavtalk/uavobjects/HomeLocation.java | 23 +- .../uavtalk/uavobjects/HwSettings.java | 291 ++++++++++ .../uavtalk/uavobjects/I2CStats.java | 34 +- .../uavobjects/ManualControlCommand.java | 55 +- .../uavobjects/ManualControlSettings.java | 313 +++++------ .../uavtalk/uavobjects/MixerSettings.java | 161 +++++- .../uavtalk/uavobjects/MixerStatus.java | 2 +- .../uavtalk/uavobjects/NedAccel.java | 2 +- .../uavtalk/uavobjects/ObjectPersistence.java | 23 +- .../uavtalk/uavobjects/PositionActual.java | 2 +- .../uavtalk/uavobjects/PositionDesired.java | 2 +- .../uavtalk/uavobjects/RateDesired.java | 2 +- ...erySettings.java => ReceiverActivity.java} | 74 ++- .../uavtalk/uavobjects/SonarAltitude.java | 2 +- .../uavobjects/StabilizationDesired.java | 4 +- .../uavobjects/StabilizationSettings.java | 119 +++-- .../uavtalk/uavobjects/SystemAlarms.java | 8 +- .../uavtalk/uavobjects/SystemSettings.java | 9 +- .../uavtalk/uavobjects/SystemStats.java | 6 +- .../uavtalk/uavobjects/TaskInfo.java | 24 +- .../uavobjects/UAVObjectsInitialize.java | 13 +- .../uavtalk/uavobjects/VelocityActual.java | 2 +- .../uavtalk/uavobjects/VelocityDesired.java | 2 +- .../uavtalk/uavobjects/WatchdogStatus.java | 2 +- .../java/uavobjectgeneratorjava.cpp | 2 +- 53 files changed, 2363 insertions(+), 867 deletions(-) create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java rename androidgcs/src/org/openpilot/uavtalk/uavobjects/{TelemetrySettings.java => FaultSettings.java} (74%) create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java rename androidgcs/src/org/openpilot/uavtalk/uavobjects/{BatterySettings.java => ReceiverActivity.java} (61%) diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java index 922582398..47d42991e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java @@ -51,30 +51,29 @@ public class AHRSCalibration extends UAVDataObject { List fields = new ArrayList(); - List measure_varElemNames = new ArrayList(); - measure_varElemNames.add("0"); - List measure_varEnumOptions = new ArrayList(); - measure_varEnumOptions.add("SET"); - measure_varEnumOptions.add("MEASURE"); - fields.add( new UAVObjectField("measure_var", "", UAVObjectField.FieldType.ENUM, measure_varElemNames, measure_varEnumOptions) ); - List accel_biasElemNames = new ArrayList(); accel_biasElemNames.add("X"); accel_biasElemNames.add("Y"); accel_biasElemNames.add("Z"); - fields.add( new UAVObjectField("accel_bias", "m/s^2", UAVObjectField.FieldType.FLOAT32, accel_biasElemNames, null) ); + fields.add( new UAVObjectField("accel_bias", "m/s", UAVObjectField.FieldType.FLOAT32, accel_biasElemNames, null) ); List accel_scaleElemNames = new ArrayList(); accel_scaleElemNames.add("X"); accel_scaleElemNames.add("Y"); accel_scaleElemNames.add("Z"); - fields.add( new UAVObjectField("accel_scale", "(m/s^2)/lsb", UAVObjectField.FieldType.FLOAT32, accel_scaleElemNames, null) ); + fields.add( new UAVObjectField("accel_scale", "(m/s)/lsb", UAVObjectField.FieldType.FLOAT32, accel_scaleElemNames, null) ); + + List accel_orthoElemNames = new ArrayList(); + accel_orthoElemNames.add("XY"); + accel_orthoElemNames.add("XZ"); + accel_orthoElemNames.add("YZ"); + fields.add( new UAVObjectField("accel_ortho", "scale", UAVObjectField.FieldType.FLOAT32, accel_orthoElemNames, null) ); List accel_varElemNames = new ArrayList(); accel_varElemNames.add("X"); accel_varElemNames.add("Y"); accel_varElemNames.add("Z"); - fields.add( new UAVObjectField("accel_var", "(m/s^2)^2", UAVObjectField.FieldType.FLOAT32, accel_varElemNames, null) ); + fields.add( new UAVObjectField("accel_var", "(m/s)^2", UAVObjectField.FieldType.FLOAT32, accel_varElemNames, null) ); List gyro_biasElemNames = new ArrayList(); gyro_biasElemNames.add("X"); @@ -126,6 +125,13 @@ public class AHRSCalibration extends UAVDataObject { pos_varElemNames.add("0"); fields.add( new UAVObjectField("pos_var", "m^2", UAVObjectField.FieldType.FLOAT32, pos_varElemNames, null) ); + List measure_varElemNames = new ArrayList(); + measure_varElemNames.add("0"); + List measure_varEnumOptions = new ArrayList(); + measure_varEnumOptions.add("SET"); + measure_varEnumOptions.add("MEASURE"); + fields.add( new UAVObjectField("measure_var", "", UAVObjectField.FieldType.ENUM, measure_varElemNames, measure_varEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -171,19 +177,21 @@ public class AHRSCalibration extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("measure_var").setValue("SET"); getField("accel_bias").setValue(-73.5,0); getField("accel_bias").setValue(-73.5,1); getField("accel_bias").setValue(73.5,2); getField("accel_scale").setValue(0.0359,0); getField("accel_scale").setValue(0.0359,1); - getField("accel_scale").setValue(-0.0359,2); + getField("accel_scale").setValue(0.0359,2); + getField("accel_ortho").setValue(0,0); + getField("accel_ortho").setValue(0,1); + getField("accel_ortho").setValue(0,2); getField("accel_var").setValue(0.0005,0); getField("accel_var").setValue(0.0005,1); getField("accel_var").setValue(0.0005,2); - getField("gyro_bias").setValue(23,0); - getField("gyro_bias").setValue(-23,1); - getField("gyro_bias").setValue(23,2); + getField("gyro_bias").setValue(28,0); + getField("gyro_bias").setValue(-28,1); + getField("gyro_bias").setValue(28,2); getField("gyro_scale").setValue(-0.017,0); getField("gyro_scale").setValue(0.017,1); getField("gyro_scale").setValue(-0.017,2); @@ -196,14 +204,15 @@ public class AHRSCalibration extends UAVDataObject { getField("mag_bias").setValue(0,0); getField("mag_bias").setValue(0,1); getField("mag_bias").setValue(0,2); - getField("mag_scale").setValue(-2,0); - getField("mag_scale").setValue(-2,1); - getField("mag_scale").setValue(-2,2); + getField("mag_scale").setValue(1,0); + getField("mag_scale").setValue(1,1); + getField("mag_scale").setValue(1,2); getField("mag_var").setValue(50,0); getField("mag_var").setValue(50,1); getField("mag_var").setValue(50,2); - getField("vel_var").setValue(0.4); - getField("pos_var").setValue(0.4); + getField("vel_var").setValue(10); + getField("pos_var").setValue(0.04); + getField("measure_var").setValue("SET"); } @@ -232,7 +241,7 @@ public class AHRSCalibration extends UAVDataObject { } // Constants - protected static final int OBJID = 0x30101BB2; + protected static final int OBJID = 0xFD0EDFC4; protected static final String NAME = "AHRSCalibration"; protected static String DESCRIPTION = "Contains the calibration settings for the @ref AHRSCommsModule"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java index c49c04778..032dae775 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java @@ -51,6 +51,18 @@ public class AHRSSettings extends UAVDataObject { List fields = new ArrayList(); + List YawBiasElemNames = new ArrayList(); + YawBiasElemNames.add("0"); + fields.add( new UAVObjectField("YawBias", "", UAVObjectField.FieldType.FLOAT32, YawBiasElemNames, null) ); + + List PitchBiasElemNames = new ArrayList(); + PitchBiasElemNames.add("0"); + fields.add( new UAVObjectField("PitchBias", "", UAVObjectField.FieldType.FLOAT32, PitchBiasElemNames, null) ); + + List RollBiasElemNames = new ArrayList(); + RollBiasElemNames.add("0"); + fields.add( new UAVObjectField("RollBias", "", UAVObjectField.FieldType.FLOAT32, RollBiasElemNames, null) ); + List AlgorithmElemNames = new ArrayList(); AlgorithmElemNames.add("0"); List AlgorithmEnumOptions = new ArrayList(); @@ -75,18 +87,6 @@ public class AHRSSettings extends UAVDataObject { BiasCorrectedRawEnumOptions.add("FALSE"); fields.add( new UAVObjectField("BiasCorrectedRaw", "", UAVObjectField.FieldType.ENUM, BiasCorrectedRawElemNames, BiasCorrectedRawEnumOptions) ); - List YawBiasElemNames = new ArrayList(); - YawBiasElemNames.add("0"); - fields.add( new UAVObjectField("YawBias", "", UAVObjectField.FieldType.FLOAT32, YawBiasElemNames, null) ); - - List PitchBiasElemNames = new ArrayList(); - PitchBiasElemNames.add("0"); - fields.add( new UAVObjectField("PitchBias", "", UAVObjectField.FieldType.FLOAT32, PitchBiasElemNames, null) ); - - List RollBiasElemNames = new ArrayList(); - RollBiasElemNames.add("0"); - fields.add( new UAVObjectField("RollBias", "", UAVObjectField.FieldType.FLOAT32, RollBiasElemNames, null) ); - // Compute the number of bytes for this object int numBytes = 0; @@ -132,13 +132,13 @@ public class AHRSSettings extends UAVDataObject { */ public void setDefaultFieldValues() { + getField("YawBias").setValue(0); + getField("PitchBias").setValue(0); + getField("RollBias").setValue(0); getField("Algorithm").setValue("INSGPS_INDOOR_NOMAG"); getField("Downsampling").setValue(20); getField("UpdatePeriod").setValue(1); getField("BiasCorrectedRaw").setValue("TRUE"); - getField("YawBias").setValue(0); - getField("PitchBias").setValue(0); - getField("RollBias").setValue(0); } @@ -167,7 +167,7 @@ public class AHRSSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0xDEFC5548; + protected static final int OBJID = 0xF8591ED8; protected static final String NAME = "AHRSSettings"; protected static String DESCRIPTION = "Settings for the @ref AHRSCommsModule to control the algorithm and what is updated"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java new file mode 100644 index 000000000..13c63dfdd --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java @@ -0,0 +1,139 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Desired Auxillary actuator settings. Comes from @ref ManualControlModule. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Desired Auxillary actuator settings. Comes from @ref ManualControlModule. + +generated from accessorydesired.xml + **/ +public class AccessoryDesired extends UAVDataObject { + + public AccessoryDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AccessoryValElemNames = new ArrayList(); + AccessoryValElemNames.add("0"); + fields.add( new UAVObjectField("AccessoryVal", "", UAVObjectField.FieldType.FLOAT32, AccessoryValElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AccessoryDesired obj = new AccessoryDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AccessoryDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (AccessoryDesired)(objMngr.getObject(AccessoryDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xC409985A; + protected static final String NAME = "AccessoryDesired"; + protected static String DESCRIPTION = "Desired Auxillary actuator settings. Comes from @ref ManualControlModule."; + protected static final boolean ISSINGLEINST = 0 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java index a5d6230ac..08f2ebefe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java @@ -60,16 +60,18 @@ public class ActuatorCommand extends UAVDataObject { ChannelElemNames.add("5"); ChannelElemNames.add("6"); ChannelElemNames.add("7"); + ChannelElemNames.add("8"); + ChannelElemNames.add("9"); fields.add( new UAVObjectField("Channel", "us", UAVObjectField.FieldType.INT16, ChannelElemNames, null) ); - List UpdateTimeElemNames = new ArrayList(); - UpdateTimeElemNames.add("0"); - fields.add( new UAVObjectField("UpdateTime", "ms", UAVObjectField.FieldType.UINT8, UpdateTimeElemNames, null) ); - List MaxUpdateTimeElemNames = new ArrayList(); MaxUpdateTimeElemNames.add("0"); fields.add( new UAVObjectField("MaxUpdateTime", "ms", UAVObjectField.FieldType.UINT16, MaxUpdateTimeElemNames, null) ); + List UpdateTimeElemNames = new ArrayList(); + UpdateTimeElemNames.add("0"); + fields.add( new UAVObjectField("UpdateTime", "ms", UAVObjectField.FieldType.UINT8, UpdateTimeElemNames, null) ); + List NumFailedUpdatesElemNames = new ArrayList(); NumFailedUpdatesElemNames.add("0"); fields.add( new UAVObjectField("NumFailedUpdates", "", UAVObjectField.FieldType.UINT8, NumFailedUpdatesElemNames, null) ); @@ -147,7 +149,7 @@ public class ActuatorCommand extends UAVDataObject { } // Constants - protected static final int OBJID = 0xE8E077D8; + protected static final int OBJID = 0x5324CB8; protected static final String NAME = "ActuatorCommand"; protected static String DESCRIPTION = "Contains the pulse duration sent to each of the channels. Set by @ref ActuatorModule"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java index b81ca29da..03ff1985c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java @@ -148,7 +148,7 @@ public class ActuatorDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0xD4516782; + protected static final int OBJID = 0xCA4BC4A4; protected static final String NAME = "ActuatorDesired"; protected static String DESCRIPTION = "Desired raw, pitch and yaw actuator settings. Comes from either @ref StabilizationModule or @ref ManualControlModule depending on FlightMode."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java index 542b433d1..71b0bb49f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java @@ -51,202 +51,6 @@ public class ActuatorSettings extends UAVDataObject { List fields = new ArrayList(); - List FixedWingRoll1ElemNames = new ArrayList(); - FixedWingRoll1ElemNames.add("0"); - List FixedWingRoll1EnumOptions = new ArrayList(); - FixedWingRoll1EnumOptions.add("Channel1"); - FixedWingRoll1EnumOptions.add("Channel2"); - FixedWingRoll1EnumOptions.add("Channel3"); - FixedWingRoll1EnumOptions.add("Channel4"); - FixedWingRoll1EnumOptions.add("Channel5"); - FixedWingRoll1EnumOptions.add("Channel6"); - FixedWingRoll1EnumOptions.add("Channel7"); - FixedWingRoll1EnumOptions.add("Channel8"); - FixedWingRoll1EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingRoll1", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll1ElemNames, FixedWingRoll1EnumOptions) ); - - List FixedWingRoll2ElemNames = new ArrayList(); - FixedWingRoll2ElemNames.add("0"); - List FixedWingRoll2EnumOptions = new ArrayList(); - FixedWingRoll2EnumOptions.add("Channel1"); - FixedWingRoll2EnumOptions.add("Channel2"); - FixedWingRoll2EnumOptions.add("Channel3"); - FixedWingRoll2EnumOptions.add("Channel4"); - FixedWingRoll2EnumOptions.add("Channel5"); - FixedWingRoll2EnumOptions.add("Channel6"); - FixedWingRoll2EnumOptions.add("Channel7"); - FixedWingRoll2EnumOptions.add("Channel8"); - FixedWingRoll2EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingRoll2", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll2ElemNames, FixedWingRoll2EnumOptions) ); - - List FixedWingPitch1ElemNames = new ArrayList(); - FixedWingPitch1ElemNames.add("0"); - List FixedWingPitch1EnumOptions = new ArrayList(); - FixedWingPitch1EnumOptions.add("Channel1"); - FixedWingPitch1EnumOptions.add("Channel2"); - FixedWingPitch1EnumOptions.add("Channel3"); - FixedWingPitch1EnumOptions.add("Channel4"); - FixedWingPitch1EnumOptions.add("Channel5"); - FixedWingPitch1EnumOptions.add("Channel6"); - FixedWingPitch1EnumOptions.add("Channel7"); - FixedWingPitch1EnumOptions.add("Channel8"); - FixedWingPitch1EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingPitch1", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch1ElemNames, FixedWingPitch1EnumOptions) ); - - List FixedWingPitch2ElemNames = new ArrayList(); - FixedWingPitch2ElemNames.add("0"); - List FixedWingPitch2EnumOptions = new ArrayList(); - FixedWingPitch2EnumOptions.add("Channel1"); - FixedWingPitch2EnumOptions.add("Channel2"); - FixedWingPitch2EnumOptions.add("Channel3"); - FixedWingPitch2EnumOptions.add("Channel4"); - FixedWingPitch2EnumOptions.add("Channel5"); - FixedWingPitch2EnumOptions.add("Channel6"); - FixedWingPitch2EnumOptions.add("Channel7"); - FixedWingPitch2EnumOptions.add("Channel8"); - FixedWingPitch2EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingPitch2", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch2ElemNames, FixedWingPitch2EnumOptions) ); - - List FixedWingYawElemNames = new ArrayList(); - FixedWingYawElemNames.add("0"); - List FixedWingYawEnumOptions = new ArrayList(); - FixedWingYawEnumOptions.add("Channel1"); - FixedWingYawEnumOptions.add("Channel2"); - FixedWingYawEnumOptions.add("Channel3"); - FixedWingYawEnumOptions.add("Channel4"); - FixedWingYawEnumOptions.add("Channel5"); - FixedWingYawEnumOptions.add("Channel6"); - FixedWingYawEnumOptions.add("Channel7"); - FixedWingYawEnumOptions.add("Channel8"); - FixedWingYawEnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingYaw", "channel", UAVObjectField.FieldType.ENUM, FixedWingYawElemNames, FixedWingYawEnumOptions) ); - - List FixedWingThrottleElemNames = new ArrayList(); - FixedWingThrottleElemNames.add("0"); - List FixedWingThrottleEnumOptions = new ArrayList(); - FixedWingThrottleEnumOptions.add("Channel1"); - FixedWingThrottleEnumOptions.add("Channel2"); - FixedWingThrottleEnumOptions.add("Channel3"); - FixedWingThrottleEnumOptions.add("Channel4"); - FixedWingThrottleEnumOptions.add("Channel5"); - FixedWingThrottleEnumOptions.add("Channel6"); - FixedWingThrottleEnumOptions.add("Channel7"); - FixedWingThrottleEnumOptions.add("Channel8"); - FixedWingThrottleEnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingThrottle", "channel", UAVObjectField.FieldType.ENUM, FixedWingThrottleElemNames, FixedWingThrottleEnumOptions) ); - - List VTOLMotorNElemNames = new ArrayList(); - VTOLMotorNElemNames.add("0"); - List VTOLMotorNEnumOptions = new ArrayList(); - VTOLMotorNEnumOptions.add("Channel1"); - VTOLMotorNEnumOptions.add("Channel2"); - VTOLMotorNEnumOptions.add("Channel3"); - VTOLMotorNEnumOptions.add("Channel4"); - VTOLMotorNEnumOptions.add("Channel5"); - VTOLMotorNEnumOptions.add("Channel6"); - VTOLMotorNEnumOptions.add("Channel7"); - VTOLMotorNEnumOptions.add("Channel8"); - VTOLMotorNEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorN", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNElemNames, VTOLMotorNEnumOptions) ); - - List VTOLMotorNEElemNames = new ArrayList(); - VTOLMotorNEElemNames.add("0"); - List VTOLMotorNEEnumOptions = new ArrayList(); - VTOLMotorNEEnumOptions.add("Channel1"); - VTOLMotorNEEnumOptions.add("Channel2"); - VTOLMotorNEEnumOptions.add("Channel3"); - VTOLMotorNEEnumOptions.add("Channel4"); - VTOLMotorNEEnumOptions.add("Channel5"); - VTOLMotorNEEnumOptions.add("Channel6"); - VTOLMotorNEEnumOptions.add("Channel7"); - VTOLMotorNEEnumOptions.add("Channel8"); - VTOLMotorNEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorNE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNEElemNames, VTOLMotorNEEnumOptions) ); - - List VTOLMotorEElemNames = new ArrayList(); - VTOLMotorEElemNames.add("0"); - List VTOLMotorEEnumOptions = new ArrayList(); - VTOLMotorEEnumOptions.add("Channel1"); - VTOLMotorEEnumOptions.add("Channel2"); - VTOLMotorEEnumOptions.add("Channel3"); - VTOLMotorEEnumOptions.add("Channel4"); - VTOLMotorEEnumOptions.add("Channel5"); - VTOLMotorEEnumOptions.add("Channel6"); - VTOLMotorEEnumOptions.add("Channel7"); - VTOLMotorEEnumOptions.add("Channel8"); - VTOLMotorEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorEElemNames, VTOLMotorEEnumOptions) ); - - List VTOLMotorSEElemNames = new ArrayList(); - VTOLMotorSEElemNames.add("0"); - List VTOLMotorSEEnumOptions = new ArrayList(); - VTOLMotorSEEnumOptions.add("Channel1"); - VTOLMotorSEEnumOptions.add("Channel2"); - VTOLMotorSEEnumOptions.add("Channel3"); - VTOLMotorSEEnumOptions.add("Channel4"); - VTOLMotorSEEnumOptions.add("Channel5"); - VTOLMotorSEEnumOptions.add("Channel6"); - VTOLMotorSEEnumOptions.add("Channel7"); - VTOLMotorSEEnumOptions.add("Channel8"); - VTOLMotorSEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorSE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSEElemNames, VTOLMotorSEEnumOptions) ); - - List VTOLMotorSElemNames = new ArrayList(); - VTOLMotorSElemNames.add("0"); - List VTOLMotorSEnumOptions = new ArrayList(); - VTOLMotorSEnumOptions.add("Channel1"); - VTOLMotorSEnumOptions.add("Channel2"); - VTOLMotorSEnumOptions.add("Channel3"); - VTOLMotorSEnumOptions.add("Channel4"); - VTOLMotorSEnumOptions.add("Channel5"); - VTOLMotorSEnumOptions.add("Channel6"); - VTOLMotorSEnumOptions.add("Channel7"); - VTOLMotorSEnumOptions.add("Channel8"); - VTOLMotorSEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorS", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSElemNames, VTOLMotorSEnumOptions) ); - - List VTOLMotorSWElemNames = new ArrayList(); - VTOLMotorSWElemNames.add("0"); - List VTOLMotorSWEnumOptions = new ArrayList(); - VTOLMotorSWEnumOptions.add("Channel1"); - VTOLMotorSWEnumOptions.add("Channel2"); - VTOLMotorSWEnumOptions.add("Channel3"); - VTOLMotorSWEnumOptions.add("Channel4"); - VTOLMotorSWEnumOptions.add("Channel5"); - VTOLMotorSWEnumOptions.add("Channel6"); - VTOLMotorSWEnumOptions.add("Channel7"); - VTOLMotorSWEnumOptions.add("Channel8"); - VTOLMotorSWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorSW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSWElemNames, VTOLMotorSWEnumOptions) ); - - List VTOLMotorWElemNames = new ArrayList(); - VTOLMotorWElemNames.add("0"); - List VTOLMotorWEnumOptions = new ArrayList(); - VTOLMotorWEnumOptions.add("Channel1"); - VTOLMotorWEnumOptions.add("Channel2"); - VTOLMotorWEnumOptions.add("Channel3"); - VTOLMotorWEnumOptions.add("Channel4"); - VTOLMotorWEnumOptions.add("Channel5"); - VTOLMotorWEnumOptions.add("Channel6"); - VTOLMotorWEnumOptions.add("Channel7"); - VTOLMotorWEnumOptions.add("Channel8"); - VTOLMotorWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorWElemNames, VTOLMotorWEnumOptions) ); - - List VTOLMotorNWElemNames = new ArrayList(); - VTOLMotorNWElemNames.add("0"); - List VTOLMotorNWEnumOptions = new ArrayList(); - VTOLMotorNWEnumOptions.add("Channel1"); - VTOLMotorNWEnumOptions.add("Channel2"); - VTOLMotorNWEnumOptions.add("Channel3"); - VTOLMotorNWEnumOptions.add("Channel4"); - VTOLMotorNWEnumOptions.add("Channel5"); - VTOLMotorNWEnumOptions.add("Channel6"); - VTOLMotorNWEnumOptions.add("Channel7"); - VTOLMotorNWEnumOptions.add("Channel8"); - VTOLMotorNWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorNW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNWElemNames, VTOLMotorNWEnumOptions) ); - List ChannelUpdateFreqElemNames = new ArrayList(); ChannelUpdateFreqElemNames.add("0"); ChannelUpdateFreqElemNames.add("1"); @@ -263,6 +67,8 @@ public class ActuatorSettings extends UAVDataObject { ChannelMaxElemNames.add("5"); ChannelMaxElemNames.add("6"); ChannelMaxElemNames.add("7"); + ChannelMaxElemNames.add("8"); + ChannelMaxElemNames.add("9"); fields.add( new UAVObjectField("ChannelMax", "us", UAVObjectField.FieldType.INT16, ChannelMaxElemNames, null) ); List ChannelNeutralElemNames = new ArrayList(); @@ -274,6 +80,8 @@ public class ActuatorSettings extends UAVDataObject { ChannelNeutralElemNames.add("5"); ChannelNeutralElemNames.add("6"); ChannelNeutralElemNames.add("7"); + ChannelNeutralElemNames.add("8"); + ChannelNeutralElemNames.add("9"); fields.add( new UAVObjectField("ChannelNeutral", "us", UAVObjectField.FieldType.INT16, ChannelNeutralElemNames, null) ); List ChannelMinElemNames = new ArrayList(); @@ -285,8 +93,250 @@ public class ActuatorSettings extends UAVDataObject { ChannelMinElemNames.add("5"); ChannelMinElemNames.add("6"); ChannelMinElemNames.add("7"); + ChannelMinElemNames.add("8"); + ChannelMinElemNames.add("9"); fields.add( new UAVObjectField("ChannelMin", "us", UAVObjectField.FieldType.INT16, ChannelMinElemNames, null) ); + List FixedWingRoll1ElemNames = new ArrayList(); + FixedWingRoll1ElemNames.add("0"); + List FixedWingRoll1EnumOptions = new ArrayList(); + FixedWingRoll1EnumOptions.add("Channel1"); + FixedWingRoll1EnumOptions.add("Channel2"); + FixedWingRoll1EnumOptions.add("Channel3"); + FixedWingRoll1EnumOptions.add("Channel4"); + FixedWingRoll1EnumOptions.add("Channel5"); + FixedWingRoll1EnumOptions.add("Channel6"); + FixedWingRoll1EnumOptions.add("Channel7"); + FixedWingRoll1EnumOptions.add("Channel8"); + FixedWingRoll1EnumOptions.add("Channel9"); + FixedWingRoll1EnumOptions.add("Channel10"); + FixedWingRoll1EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingRoll1", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll1ElemNames, FixedWingRoll1EnumOptions) ); + + List FixedWingRoll2ElemNames = new ArrayList(); + FixedWingRoll2ElemNames.add("0"); + List FixedWingRoll2EnumOptions = new ArrayList(); + FixedWingRoll2EnumOptions.add("Channel1"); + FixedWingRoll2EnumOptions.add("Channel2"); + FixedWingRoll2EnumOptions.add("Channel3"); + FixedWingRoll2EnumOptions.add("Channel4"); + FixedWingRoll2EnumOptions.add("Channel5"); + FixedWingRoll2EnumOptions.add("Channel6"); + FixedWingRoll2EnumOptions.add("Channel7"); + FixedWingRoll2EnumOptions.add("Channel8"); + FixedWingRoll2EnumOptions.add("Channel9"); + FixedWingRoll2EnumOptions.add("Channel10"); + FixedWingRoll2EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingRoll2", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll2ElemNames, FixedWingRoll2EnumOptions) ); + + List FixedWingPitch1ElemNames = new ArrayList(); + FixedWingPitch1ElemNames.add("0"); + List FixedWingPitch1EnumOptions = new ArrayList(); + FixedWingPitch1EnumOptions.add("Channel1"); + FixedWingPitch1EnumOptions.add("Channel2"); + FixedWingPitch1EnumOptions.add("Channel3"); + FixedWingPitch1EnumOptions.add("Channel4"); + FixedWingPitch1EnumOptions.add("Channel5"); + FixedWingPitch1EnumOptions.add("Channel6"); + FixedWingPitch1EnumOptions.add("Channel7"); + FixedWingPitch1EnumOptions.add("Channel8"); + FixedWingPitch1EnumOptions.add("Channel9"); + FixedWingPitch1EnumOptions.add("Channel10"); + FixedWingPitch1EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingPitch1", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch1ElemNames, FixedWingPitch1EnumOptions) ); + + List FixedWingPitch2ElemNames = new ArrayList(); + FixedWingPitch2ElemNames.add("0"); + List FixedWingPitch2EnumOptions = new ArrayList(); + FixedWingPitch2EnumOptions.add("Channel1"); + FixedWingPitch2EnumOptions.add("Channel2"); + FixedWingPitch2EnumOptions.add("Channel3"); + FixedWingPitch2EnumOptions.add("Channel4"); + FixedWingPitch2EnumOptions.add("Channel5"); + FixedWingPitch2EnumOptions.add("Channel6"); + FixedWingPitch2EnumOptions.add("Channel7"); + FixedWingPitch2EnumOptions.add("Channel8"); + FixedWingPitch2EnumOptions.add("Channel9"); + FixedWingPitch2EnumOptions.add("Channel10"); + FixedWingPitch2EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingPitch2", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch2ElemNames, FixedWingPitch2EnumOptions) ); + + List FixedWingYaw1ElemNames = new ArrayList(); + FixedWingYaw1ElemNames.add("0"); + List FixedWingYaw1EnumOptions = new ArrayList(); + FixedWingYaw1EnumOptions.add("Channel1"); + FixedWingYaw1EnumOptions.add("Channel2"); + FixedWingYaw1EnumOptions.add("Channel3"); + FixedWingYaw1EnumOptions.add("Channel4"); + FixedWingYaw1EnumOptions.add("Channel5"); + FixedWingYaw1EnumOptions.add("Channel6"); + FixedWingYaw1EnumOptions.add("Channel7"); + FixedWingYaw1EnumOptions.add("Channel8"); + FixedWingYaw1EnumOptions.add("Channel9"); + FixedWingYaw1EnumOptions.add("Channel10"); + FixedWingYaw1EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingYaw1", "channel", UAVObjectField.FieldType.ENUM, FixedWingYaw1ElemNames, FixedWingYaw1EnumOptions) ); + + List FixedWingYaw2ElemNames = new ArrayList(); + FixedWingYaw2ElemNames.add("0"); + List FixedWingYaw2EnumOptions = new ArrayList(); + FixedWingYaw2EnumOptions.add("Channel1"); + FixedWingYaw2EnumOptions.add("Channel2"); + FixedWingYaw2EnumOptions.add("Channel3"); + FixedWingYaw2EnumOptions.add("Channel4"); + FixedWingYaw2EnumOptions.add("Channel5"); + FixedWingYaw2EnumOptions.add("Channel6"); + FixedWingYaw2EnumOptions.add("Channel7"); + FixedWingYaw2EnumOptions.add("Channel8"); + FixedWingYaw2EnumOptions.add("Channel9"); + FixedWingYaw2EnumOptions.add("Channel10"); + FixedWingYaw2EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingYaw2", "channel", UAVObjectField.FieldType.ENUM, FixedWingYaw2ElemNames, FixedWingYaw2EnumOptions) ); + + List FixedWingThrottleElemNames = new ArrayList(); + FixedWingThrottleElemNames.add("0"); + List FixedWingThrottleEnumOptions = new ArrayList(); + FixedWingThrottleEnumOptions.add("Channel1"); + FixedWingThrottleEnumOptions.add("Channel2"); + FixedWingThrottleEnumOptions.add("Channel3"); + FixedWingThrottleEnumOptions.add("Channel4"); + FixedWingThrottleEnumOptions.add("Channel5"); + FixedWingThrottleEnumOptions.add("Channel6"); + FixedWingThrottleEnumOptions.add("Channel7"); + FixedWingThrottleEnumOptions.add("Channel8"); + FixedWingThrottleEnumOptions.add("Channel9"); + FixedWingThrottleEnumOptions.add("Channel10"); + FixedWingThrottleEnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingThrottle", "channel", UAVObjectField.FieldType.ENUM, FixedWingThrottleElemNames, FixedWingThrottleEnumOptions) ); + + List VTOLMotorNElemNames = new ArrayList(); + VTOLMotorNElemNames.add("0"); + List VTOLMotorNEnumOptions = new ArrayList(); + VTOLMotorNEnumOptions.add("Channel1"); + VTOLMotorNEnumOptions.add("Channel2"); + VTOLMotorNEnumOptions.add("Channel3"); + VTOLMotorNEnumOptions.add("Channel4"); + VTOLMotorNEnumOptions.add("Channel5"); + VTOLMotorNEnumOptions.add("Channel6"); + VTOLMotorNEnumOptions.add("Channel7"); + VTOLMotorNEnumOptions.add("Channel8"); + VTOLMotorNEnumOptions.add("Channel9"); + VTOLMotorNEnumOptions.add("Channel10"); + VTOLMotorNEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorN", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNElemNames, VTOLMotorNEnumOptions) ); + + List VTOLMotorNEElemNames = new ArrayList(); + VTOLMotorNEElemNames.add("0"); + List VTOLMotorNEEnumOptions = new ArrayList(); + VTOLMotorNEEnumOptions.add("Channel1"); + VTOLMotorNEEnumOptions.add("Channel2"); + VTOLMotorNEEnumOptions.add("Channel3"); + VTOLMotorNEEnumOptions.add("Channel4"); + VTOLMotorNEEnumOptions.add("Channel5"); + VTOLMotorNEEnumOptions.add("Channel6"); + VTOLMotorNEEnumOptions.add("Channel7"); + VTOLMotorNEEnumOptions.add("Channel8"); + VTOLMotorNEEnumOptions.add("Channel9"); + VTOLMotorNEEnumOptions.add("Channel10"); + VTOLMotorNEEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorNE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNEElemNames, VTOLMotorNEEnumOptions) ); + + List VTOLMotorEElemNames = new ArrayList(); + VTOLMotorEElemNames.add("0"); + List VTOLMotorEEnumOptions = new ArrayList(); + VTOLMotorEEnumOptions.add("Channel1"); + VTOLMotorEEnumOptions.add("Channel2"); + VTOLMotorEEnumOptions.add("Channel3"); + VTOLMotorEEnumOptions.add("Channel4"); + VTOLMotorEEnumOptions.add("Channel5"); + VTOLMotorEEnumOptions.add("Channel6"); + VTOLMotorEEnumOptions.add("Channel7"); + VTOLMotorEEnumOptions.add("Channel8"); + VTOLMotorEEnumOptions.add("Channel9"); + VTOLMotorEEnumOptions.add("Channel10"); + VTOLMotorEEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorEElemNames, VTOLMotorEEnumOptions) ); + + List VTOLMotorSEElemNames = new ArrayList(); + VTOLMotorSEElemNames.add("0"); + List VTOLMotorSEEnumOptions = new ArrayList(); + VTOLMotorSEEnumOptions.add("Channel1"); + VTOLMotorSEEnumOptions.add("Channel2"); + VTOLMotorSEEnumOptions.add("Channel3"); + VTOLMotorSEEnumOptions.add("Channel4"); + VTOLMotorSEEnumOptions.add("Channel5"); + VTOLMotorSEEnumOptions.add("Channel6"); + VTOLMotorSEEnumOptions.add("Channel7"); + VTOLMotorSEEnumOptions.add("Channel8"); + VTOLMotorSEEnumOptions.add("Channel9"); + VTOLMotorSEEnumOptions.add("Channel10"); + VTOLMotorSEEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorSE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSEElemNames, VTOLMotorSEEnumOptions) ); + + List VTOLMotorSElemNames = new ArrayList(); + VTOLMotorSElemNames.add("0"); + List VTOLMotorSEnumOptions = new ArrayList(); + VTOLMotorSEnumOptions.add("Channel1"); + VTOLMotorSEnumOptions.add("Channel2"); + VTOLMotorSEnumOptions.add("Channel3"); + VTOLMotorSEnumOptions.add("Channel4"); + VTOLMotorSEnumOptions.add("Channel5"); + VTOLMotorSEnumOptions.add("Channel6"); + VTOLMotorSEnumOptions.add("Channel7"); + VTOLMotorSEnumOptions.add("Channel8"); + VTOLMotorSEnumOptions.add("Channel9"); + VTOLMotorSEnumOptions.add("Channel10"); + VTOLMotorSEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorS", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSElemNames, VTOLMotorSEnumOptions) ); + + List VTOLMotorSWElemNames = new ArrayList(); + VTOLMotorSWElemNames.add("0"); + List VTOLMotorSWEnumOptions = new ArrayList(); + VTOLMotorSWEnumOptions.add("Channel1"); + VTOLMotorSWEnumOptions.add("Channel2"); + VTOLMotorSWEnumOptions.add("Channel3"); + VTOLMotorSWEnumOptions.add("Channel4"); + VTOLMotorSWEnumOptions.add("Channel5"); + VTOLMotorSWEnumOptions.add("Channel6"); + VTOLMotorSWEnumOptions.add("Channel7"); + VTOLMotorSWEnumOptions.add("Channel8"); + VTOLMotorSWEnumOptions.add("Channel9"); + VTOLMotorSWEnumOptions.add("Channel10"); + VTOLMotorSWEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorSW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSWElemNames, VTOLMotorSWEnumOptions) ); + + List VTOLMotorWElemNames = new ArrayList(); + VTOLMotorWElemNames.add("0"); + List VTOLMotorWEnumOptions = new ArrayList(); + VTOLMotorWEnumOptions.add("Channel1"); + VTOLMotorWEnumOptions.add("Channel2"); + VTOLMotorWEnumOptions.add("Channel3"); + VTOLMotorWEnumOptions.add("Channel4"); + VTOLMotorWEnumOptions.add("Channel5"); + VTOLMotorWEnumOptions.add("Channel6"); + VTOLMotorWEnumOptions.add("Channel7"); + VTOLMotorWEnumOptions.add("Channel8"); + VTOLMotorWEnumOptions.add("Channel9"); + VTOLMotorWEnumOptions.add("Channel10"); + VTOLMotorWEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorWElemNames, VTOLMotorWEnumOptions) ); + + List VTOLMotorNWElemNames = new ArrayList(); + VTOLMotorNWElemNames.add("0"); + List VTOLMotorNWEnumOptions = new ArrayList(); + VTOLMotorNWEnumOptions.add("Channel1"); + VTOLMotorNWEnumOptions.add("Channel2"); + VTOLMotorNWEnumOptions.add("Channel3"); + VTOLMotorNWEnumOptions.add("Channel4"); + VTOLMotorNWEnumOptions.add("Channel5"); + VTOLMotorNWEnumOptions.add("Channel6"); + VTOLMotorNWEnumOptions.add("Channel7"); + VTOLMotorNWEnumOptions.add("Channel8"); + VTOLMotorNWEnumOptions.add("Channel9"); + VTOLMotorNWEnumOptions.add("Channel10"); + VTOLMotorNWEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorNW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNWElemNames, VTOLMotorNWEnumOptions) ); + List ChannelTypeElemNames = new ArrayList(); ChannelTypeElemNames.add("0"); ChannelTypeElemNames.add("1"); @@ -296,10 +346,13 @@ public class ActuatorSettings extends UAVDataObject { ChannelTypeElemNames.add("5"); ChannelTypeElemNames.add("6"); ChannelTypeElemNames.add("7"); + ChannelTypeElemNames.add("8"); + ChannelTypeElemNames.add("9"); List ChannelTypeEnumOptions = new ArrayList(); ChannelTypeEnumOptions.add("PWM"); ChannelTypeEnumOptions.add("MK"); ChannelTypeEnumOptions.add("ASTEC4"); + ChannelTypeEnumOptions.add("PWM Alarm Buzzer"); fields.add( new UAVObjectField("ChannelType", "", UAVObjectField.FieldType.ENUM, ChannelTypeElemNames, ChannelTypeEnumOptions) ); List ChannelAddrElemNames = new ArrayList(); @@ -311,8 +364,17 @@ public class ActuatorSettings extends UAVDataObject { ChannelAddrElemNames.add("5"); ChannelAddrElemNames.add("6"); ChannelAddrElemNames.add("7"); + ChannelAddrElemNames.add("8"); + ChannelAddrElemNames.add("9"); fields.add( new UAVObjectField("ChannelAddr", "", UAVObjectField.FieldType.UINT8, ChannelAddrElemNames, null) ); + List MotorsSpinWhileArmedElemNames = new ArrayList(); + MotorsSpinWhileArmedElemNames.add("0"); + List MotorsSpinWhileArmedEnumOptions = new ArrayList(); + MotorsSpinWhileArmedEnumOptions.add("FALSE"); + MotorsSpinWhileArmedEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("MotorsSpinWhileArmed", "", UAVObjectField.FieldType.ENUM, MotorsSpinWhileArmedElemNames, MotorsSpinWhileArmedEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -358,20 +420,6 @@ public class ActuatorSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("FixedWingRoll1").setValue("None"); - getField("FixedWingRoll2").setValue("None"); - getField("FixedWingPitch1").setValue("None"); - getField("FixedWingPitch2").setValue("None"); - getField("FixedWingYaw").setValue("None"); - getField("FixedWingThrottle").setValue("None"); - getField("VTOLMotorN").setValue("None"); - getField("VTOLMotorNE").setValue("None"); - getField("VTOLMotorE").setValue("None"); - getField("VTOLMotorSE").setValue("None"); - getField("VTOLMotorS").setValue("None"); - getField("VTOLMotorSW").setValue("None"); - getField("VTOLMotorW").setValue("None"); - getField("VTOLMotorNW").setValue("None"); getField("ChannelUpdateFreq").setValue(50,0); getField("ChannelUpdateFreq").setValue(50,1); getField("ChannelUpdateFreq").setValue(50,2); @@ -384,6 +432,8 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelMax").setValue(1000,5); getField("ChannelMax").setValue(1000,6); getField("ChannelMax").setValue(1000,7); + getField("ChannelMax").setValue(1000,8); + getField("ChannelMax").setValue(1000,9); getField("ChannelNeutral").setValue(1000,0); getField("ChannelNeutral").setValue(1000,1); getField("ChannelNeutral").setValue(1000,2); @@ -392,6 +442,8 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelNeutral").setValue(1000,5); getField("ChannelNeutral").setValue(1000,6); getField("ChannelNeutral").setValue(1000,7); + getField("ChannelNeutral").setValue(1000,8); + getField("ChannelNeutral").setValue(1000,9); getField("ChannelMin").setValue(1000,0); getField("ChannelMin").setValue(1000,1); getField("ChannelMin").setValue(1000,2); @@ -400,6 +452,23 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelMin").setValue(1000,5); getField("ChannelMin").setValue(1000,6); getField("ChannelMin").setValue(1000,7); + getField("ChannelMin").setValue(1000,8); + getField("ChannelMin").setValue(1000,9); + getField("FixedWingRoll1").setValue("None"); + getField("FixedWingRoll2").setValue("None"); + getField("FixedWingPitch1").setValue("None"); + getField("FixedWingPitch2").setValue("None"); + getField("FixedWingYaw1").setValue("None"); + getField("FixedWingYaw2").setValue("None"); + getField("FixedWingThrottle").setValue("None"); + getField("VTOLMotorN").setValue("None"); + getField("VTOLMotorNE").setValue("None"); + getField("VTOLMotorE").setValue("None"); + getField("VTOLMotorSE").setValue("None"); + getField("VTOLMotorS").setValue("None"); + getField("VTOLMotorSW").setValue("None"); + getField("VTOLMotorW").setValue("None"); + getField("VTOLMotorNW").setValue("None"); getField("ChannelType").setValue("PWM",0); getField("ChannelType").setValue("PWM",1); getField("ChannelType").setValue("PWM",2); @@ -408,6 +477,8 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelType").setValue("PWM",5); getField("ChannelType").setValue("PWM",6); getField("ChannelType").setValue("PWM",7); + getField("ChannelType").setValue("PWM",8); + getField("ChannelType").setValue("PWM",9); getField("ChannelAddr").setValue(0,0); getField("ChannelAddr").setValue(1,1); getField("ChannelAddr").setValue(2,2); @@ -416,6 +487,9 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelAddr").setValue(5,5); getField("ChannelAddr").setValue(6,6); getField("ChannelAddr").setValue(7,7); + getField("ChannelAddr").setValue(8,8); + getField("ChannelAddr").setValue(9,9); + getField("MotorsSpinWhileArmed").setValue("FALSE"); } @@ -444,7 +518,7 @@ public class ActuatorSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x1BF864C2; + protected static final int OBJID = 0xF2875746; protected static final String NAME = "ActuatorSettings"; protected static String DESCRIPTION = "Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java index 3ee8304ae..82e447a70 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java @@ -51,6 +51,10 @@ public class AhrsStatus extends UAVDataObject { List fields = new ArrayList(); + List RunningTimeElemNames = new ArrayList(); + RunningTimeElemNames.add("0"); + fields.add( new UAVObjectField("RunningTime", "ms", UAVObjectField.FieldType.UINT32, RunningTimeElemNames, null) ); + List SerialNumberElemNames = new ArrayList(); SerialNumberElemNames.add("0"); SerialNumberElemNames.add("1"); @@ -66,10 +70,6 @@ public class AhrsStatus extends UAVDataObject { CPULoadElemNames.add("0"); fields.add( new UAVObjectField("CPULoad", "count", UAVObjectField.FieldType.UINT8, CPULoadElemNames, null) ); - List RunningTimeElemNames = new ArrayList(); - RunningTimeElemNames.add("0"); - fields.add( new UAVObjectField("RunningTime", "ms", UAVObjectField.FieldType.UINT32, RunningTimeElemNames, null) ); - List IdleTimePerCyleElemNames = new ArrayList(); IdleTimePerCyleElemNames.add("0"); fields.add( new UAVObjectField("IdleTimePerCyle", "10x ms", UAVObjectField.FieldType.UINT8, IdleTimePerCyleElemNames, null) ); @@ -190,7 +190,7 @@ public class AhrsStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0x37A5F7A2; + protected static final int OBJID = 0x706D1AB8; protected static final String NAME = "AhrsStatus"; protected static String DESCRIPTION = "Status for the @ref AHRSCommsModule, including communication errors"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java index 714c18571..7c9272cad 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java @@ -110,7 +110,7 @@ public class AttitudeActual extends UAVDataObject { metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 500; + metadata.flightTelemetryUpdatePeriod = 100; metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; metadata.loggingUpdatePeriod = 0; @@ -152,7 +152,7 @@ public class AttitudeActual extends UAVDataObject { } // Constants - protected static final int OBJID = 0xFC5B8CF4; + protected static final int OBJID = 0x33DAD5E6; protected static final String NAME = "AttitudeActual"; protected static String DESCRIPTION = "The updated Attitude estimation from @ref AHRSCommsModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java index d28302b6a..b8c3aacb4 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java @@ -51,29 +51,29 @@ public class AttitudeRaw extends UAVDataObject { List fields = new ArrayList(); - List magnetometersElemNames = new ArrayList(); - magnetometersElemNames.add("X"); - magnetometersElemNames.add("Y"); - magnetometersElemNames.add("Z"); - fields.add( new UAVObjectField("magnetometers", "mGa", UAVObjectField.FieldType.INT16, magnetometersElemNames, null) ); - List gyrosElemNames = new ArrayList(); gyrosElemNames.add("X"); gyrosElemNames.add("Y"); gyrosElemNames.add("Z"); fields.add( new UAVObjectField("gyros", "deg/s", UAVObjectField.FieldType.FLOAT32, gyrosElemNames, null) ); - List gyrotempElemNames = new ArrayList(); - gyrotempElemNames.add("XY"); - gyrotempElemNames.add("Z"); - fields.add( new UAVObjectField("gyrotemp", "raw", UAVObjectField.FieldType.UINT16, gyrotempElemNames, null) ); - List accelsElemNames = new ArrayList(); accelsElemNames.add("X"); accelsElemNames.add("Y"); accelsElemNames.add("Z"); fields.add( new UAVObjectField("accels", "m/s^2", UAVObjectField.FieldType.FLOAT32, accelsElemNames, null) ); + List magnetometersElemNames = new ArrayList(); + magnetometersElemNames.add("X"); + magnetometersElemNames.add("Y"); + magnetometersElemNames.add("Z"); + fields.add( new UAVObjectField("magnetometers", "mGa", UAVObjectField.FieldType.INT16, magnetometersElemNames, null) ); + + List gyrotempElemNames = new ArrayList(); + gyrotempElemNames.add("XY"); + gyrotempElemNames.add("Z"); + fields.add( new UAVObjectField("gyrotemp", "raw", UAVObjectField.FieldType.UINT16, gyrotempElemNames, null) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -147,7 +147,7 @@ public class AttitudeRaw extends UAVDataObject { } // Constants - protected static final int OBJID = 0x37747DE6; + protected static final int OBJID = 0xDB722974; protected static final String NAME = "AttitudeRaw"; protected static String DESCRIPTION = "The raw attitude sensor data from @ref AHRSCommsModule. Not always updated."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java index 482fc12ce..3034a99ad 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java @@ -51,12 +51,6 @@ public class AttitudeSettings extends UAVDataObject { List fields = new ArrayList(); - List AccelBiasElemNames = new ArrayList(); - AccelBiasElemNames.add("X"); - AccelBiasElemNames.add("Y"); - AccelBiasElemNames.add("Z"); - fields.add( new UAVObjectField("AccelBias", "lsb", UAVObjectField.FieldType.INT16, AccelBiasElemNames, null) ); - List GyroGainElemNames = new ArrayList(); GyroGainElemNames.add("0"); fields.add( new UAVObjectField("GyroGain", "(rad/s)/lsb", UAVObjectField.FieldType.FLOAT32, GyroGainElemNames, null) ); @@ -69,6 +63,50 @@ public class AttitudeSettings extends UAVDataObject { AccelKiElemNames.add("0"); fields.add( new UAVObjectField("AccelKi", "channel", UAVObjectField.FieldType.FLOAT32, AccelKiElemNames, null) ); + List YawBiasRateElemNames = new ArrayList(); + YawBiasRateElemNames.add("0"); + fields.add( new UAVObjectField("YawBiasRate", "channel", UAVObjectField.FieldType.FLOAT32, YawBiasRateElemNames, null) ); + + List AccelBiasElemNames = new ArrayList(); + AccelBiasElemNames.add("X"); + AccelBiasElemNames.add("Y"); + AccelBiasElemNames.add("Z"); + fields.add( new UAVObjectField("AccelBias", "lsb", UAVObjectField.FieldType.INT16, AccelBiasElemNames, null) ); + + List GyroBiasElemNames = new ArrayList(); + GyroBiasElemNames.add("X"); + GyroBiasElemNames.add("Y"); + GyroBiasElemNames.add("Z"); + fields.add( new UAVObjectField("GyroBias", "deg/s * 100", UAVObjectField.FieldType.INT16, GyroBiasElemNames, null) ); + + List BoardRotationElemNames = new ArrayList(); + BoardRotationElemNames.add("Roll"); + BoardRotationElemNames.add("Pitch"); + BoardRotationElemNames.add("Yaw"); + fields.add( new UAVObjectField("BoardRotation", "deg", UAVObjectField.FieldType.INT16, BoardRotationElemNames, null) ); + + List ZeroDuringArmingElemNames = new ArrayList(); + ZeroDuringArmingElemNames.add("0"); + List ZeroDuringArmingEnumOptions = new ArrayList(); + ZeroDuringArmingEnumOptions.add("FALSE"); + ZeroDuringArmingEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("ZeroDuringArming", "channel", UAVObjectField.FieldType.ENUM, ZeroDuringArmingElemNames, ZeroDuringArmingEnumOptions) ); + + List BiasCorrectGyroElemNames = new ArrayList(); + BiasCorrectGyroElemNames.add("0"); + List BiasCorrectGyroEnumOptions = new ArrayList(); + BiasCorrectGyroEnumOptions.add("FALSE"); + BiasCorrectGyroEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("BiasCorrectGyro", "channel", UAVObjectField.FieldType.ENUM, BiasCorrectGyroElemNames, BiasCorrectGyroEnumOptions) ); + + List TrimFlightElemNames = new ArrayList(); + TrimFlightElemNames.add("0"); + List TrimFlightEnumOptions = new ArrayList(); + TrimFlightEnumOptions.add("NORMAL"); + TrimFlightEnumOptions.add("START"); + TrimFlightEnumOptions.add("LOAD"); + fields.add( new UAVObjectField("TrimFlight", "channel", UAVObjectField.FieldType.ENUM, TrimFlightElemNames, TrimFlightEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -114,12 +152,22 @@ public class AttitudeSettings extends UAVDataObject { */ public void setDefaultFieldValues() { + getField("GyroGain").setValue(0.42); + getField("AccelKp").setValue(0.05); + getField("AccelKi").setValue(0.0001); + getField("YawBiasRate").setValue(1e-06); getField("AccelBias").setValue(0,0); getField("AccelBias").setValue(0,1); getField("AccelBias").setValue(0,2); - getField("GyroGain").setValue(0.42); - getField("AccelKp").setValue(0.01); - getField("AccelKi").setValue(0.0001); + getField("GyroBias").setValue(0,0); + getField("GyroBias").setValue(0,1); + getField("GyroBias").setValue(0,2); + getField("BoardRotation").setValue(0,0); + getField("BoardRotation").setValue(0,1); + getField("BoardRotation").setValue(0,2); + getField("ZeroDuringArming").setValue("TRUE"); + getField("BiasCorrectGyro").setValue("TRUE"); + getField("TrimFlight").setValue("NORMAL"); } @@ -148,7 +196,7 @@ public class AttitudeSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x327BF29A; + protected static final int OBJID = 0xC307BC4A; protected static final String NAME = "AttitudeSettings"; protected static String DESCRIPTION = "Settings for the @ref Attitude module used on CopterControl"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java index a2c2c7e3d..ecde53985 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java @@ -136,7 +136,7 @@ public class BaroAltitude extends UAVDataObject { } // Constants - protected static final int OBJID = 0xED4424F6; + protected static final int OBJID = 0x99622E6A; protected static final String NAME = "BaroAltitude"; protected static String DESCRIPTION = "The raw data from the barometric sensor with pressure, temperature and altitude estimate."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java new file mode 100644 index 000000000..7a36ec1ea --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java @@ -0,0 +1,147 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Desired camera outputs. Comes from @ref CameraStabilization module. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Desired camera outputs. Comes from @ref CameraStabilization module. + +generated from cameradesired.xml + **/ +public class CameraDesired extends UAVDataObject { + + public CameraDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + CameraDesired obj = new CameraDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public CameraDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (CameraDesired)(objMngr.getObject(CameraDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x531F544E; + protected static final String NAME = "CameraDesired"; + protected static String DESCRIPTION = "Desired camera outputs. Comes from @ref CameraStabilization module."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java new file mode 100644 index 000000000..a8e03df32 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java @@ -0,0 +1,205 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref CameraStab mmodule + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref CameraStab mmodule + +generated from camerastabsettings.xml + **/ +public class CameraStabSettings extends UAVDataObject { + + public CameraStabSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List MaxAxisLockRateElemNames = new ArrayList(); + MaxAxisLockRateElemNames.add("0"); + fields.add( new UAVObjectField("MaxAxisLockRate", "deg/s", UAVObjectField.FieldType.FLOAT32, MaxAxisLockRateElemNames, null) ); + + List ResponseTimeElemNames = new ArrayList(); + ResponseTimeElemNames.add("Roll"); + ResponseTimeElemNames.add("Pitch"); + ResponseTimeElemNames.add("Yaw"); + fields.add( new UAVObjectField("ResponseTime", "ms", UAVObjectField.FieldType.UINT16, ResponseTimeElemNames, null) ); + + List InputElemNames = new ArrayList(); + InputElemNames.add("Roll"); + InputElemNames.add("Pitch"); + InputElemNames.add("Yaw"); + List InputEnumOptions = new ArrayList(); + InputEnumOptions.add("Accessory0"); + InputEnumOptions.add("Accessory1"); + InputEnumOptions.add("Accessory2"); + InputEnumOptions.add("Accessory3"); + InputEnumOptions.add("Accessory4"); + InputEnumOptions.add("Accessory5"); + InputEnumOptions.add("None"); + fields.add( new UAVObjectField("Input", "channel", UAVObjectField.FieldType.ENUM, InputElemNames, InputEnumOptions) ); + + List InputRangeElemNames = new ArrayList(); + InputRangeElemNames.add("Roll"); + InputRangeElemNames.add("Pitch"); + InputRangeElemNames.add("Yaw"); + fields.add( new UAVObjectField("InputRange", "deg", UAVObjectField.FieldType.UINT8, InputRangeElemNames, null) ); + + List InputRateElemNames = new ArrayList(); + InputRateElemNames.add("Roll"); + InputRateElemNames.add("Pitch"); + InputRateElemNames.add("Yaw"); + fields.add( new UAVObjectField("InputRate", "deg/s", UAVObjectField.FieldType.UINT8, InputRateElemNames, null) ); + + List StabilizationModeElemNames = new ArrayList(); + StabilizationModeElemNames.add("Roll"); + StabilizationModeElemNames.add("Pitch"); + StabilizationModeElemNames.add("Yaw"); + List StabilizationModeEnumOptions = new ArrayList(); + StabilizationModeEnumOptions.add("Attitude"); + StabilizationModeEnumOptions.add("AxisLock"); + fields.add( new UAVObjectField("StabilizationMode", "", UAVObjectField.FieldType.ENUM, StabilizationModeElemNames, StabilizationModeEnumOptions) ); + + List OutputRangeElemNames = new ArrayList(); + OutputRangeElemNames.add("Roll"); + OutputRangeElemNames.add("Pitch"); + OutputRangeElemNames.add("Yaw"); + fields.add( new UAVObjectField("OutputRange", "deg", UAVObjectField.FieldType.UINT8, OutputRangeElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("MaxAxisLockRate").setValue(1); + getField("ResponseTime").setValue(150,0); + getField("ResponseTime").setValue(150,1); + getField("ResponseTime").setValue(150,2); + getField("Input").setValue("None",0); + getField("Input").setValue("None",1); + getField("Input").setValue("None",2); + getField("InputRange").setValue(20,0); + getField("InputRange").setValue(20,1); + getField("InputRange").setValue(20,2); + getField("InputRate").setValue(50,0); + getField("InputRate").setValue(50,1); + getField("InputRate").setValue(50,2); + getField("StabilizationMode").setValue("Attitude",0); + getField("StabilizationMode").setValue("Attitude",1); + getField("StabilizationMode").setValue("Attitude",2); + getField("OutputRange").setValue(20,0); + getField("OutputRange").setValue(20,1); + getField("OutputRange").setValue(20,2); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + CameraStabSettings obj = new CameraStabSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public CameraStabSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (CameraStabSettings)(objMngr.getObject(CameraStabSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x3B95DDBA; + protected static final String NAME = "CameraStabSettings"; + protected static String DESCRIPTION = "Settings for the @ref CameraStab mmodule"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java similarity index 74% rename from androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java rename to androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java index 675f9b592..b22b8185e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java @@ -5,7 +5,7 @@ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief Template for an uavobject in java * This is a autogenerated file!! Do not modify and expect a result. - * Select baud rate of telemetry. Warning - this must match your modem. + * Allows testers to simulate various fault scenarios. * * @see The GNU Public License (GPL) Version 3 * @@ -39,29 +39,28 @@ import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObjectField; /** -Select baud rate of telemetry. Warning - this must match your modem. +Allows testers to simulate various fault scenarios. -generated from telemetrysettings.xml +generated from faultsettings.xml **/ -public class TelemetrySettings extends UAVDataObject { +public class FaultSettings extends UAVDataObject { - public TelemetrySettings() { + public FaultSettings() { super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); List fields = new ArrayList(); - List SpeedElemNames = new ArrayList(); - SpeedElemNames.add("0"); - List SpeedEnumOptions = new ArrayList(); - SpeedEnumOptions.add("2400"); - SpeedEnumOptions.add("4800"); - SpeedEnumOptions.add("9600"); - SpeedEnumOptions.add("19200"); - SpeedEnumOptions.add("38400"); - SpeedEnumOptions.add("57600"); - SpeedEnumOptions.add("115200"); - fields.add( new UAVObjectField("Speed", "", UAVObjectField.FieldType.ENUM, SpeedElemNames, SpeedEnumOptions) ); + List ActivateFaultElemNames = new ArrayList(); + ActivateFaultElemNames.add("0"); + List ActivateFaultEnumOptions = new ArrayList(); + ActivateFaultEnumOptions.add("NoFault"); + ActivateFaultEnumOptions.add("ModuleInitAssert"); + ActivateFaultEnumOptions.add("InitOutOfMemory"); + ActivateFaultEnumOptions.add("InitBusError"); + ActivateFaultEnumOptions.add("RunawayTask"); + ActivateFaultEnumOptions.add("TaskOutOfMemory"); + fields.add( new UAVObjectField("ActivateFault", "fault", UAVObjectField.FieldType.ENUM, ActivateFaultElemNames, ActivateFaultEnumOptions) ); // Compute the number of bytes for this object @@ -108,7 +107,7 @@ public class TelemetrySettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("Speed").setValue("57600"); + getField("ActivateFault").setValue("NoFault"); } @@ -120,7 +119,7 @@ public class TelemetrySettings extends UAVDataObject { public UAVDataObject clone(int instID) { // TODO: Need to get specific instance to clone try { - TelemetrySettings obj = new TelemetrySettings(); + FaultSettings obj = new FaultSettings(); obj.initialize(instID, this.getMetaObject()); return obj; } catch (Exception e) { @@ -131,15 +130,15 @@ public class TelemetrySettings extends UAVDataObject { /** * Static function to retrieve an instance of the object. */ - public TelemetrySettings GetInstance(UAVObjectManager objMngr, int instID) + public FaultSettings GetInstance(UAVObjectManager objMngr, int instID) { - return (TelemetrySettings)(objMngr.getObject(TelemetrySettings.OBJID, instID)); + return (FaultSettings)(objMngr.getObject(FaultSettings.OBJID, instID)); } // Constants - protected static final int OBJID = 0xA608C526; - protected static final String NAME = "TelemetrySettings"; - protected static String DESCRIPTION = "Select baud rate of telemetry. Warning - this must match your modem."; + protected static final int OBJID = 0x2778BA3C; + protected static final String NAME = "FaultSettings"; + protected static String DESCRIPTION = "Allows testers to simulate various fault scenarios."; protected static final boolean ISSINGLEINST = 1 == 1; protected static final boolean ISSETTINGS = 1 == 1; protected static int NUMBYTES = 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java index 493d6cd64..71c681bd2 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java @@ -5,7 +5,7 @@ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief Template for an uavobject in java * This is a autogenerated file!! Do not modify and expect a result. - * Firmware IAP + * Queries board for SN, model, revision, and sends reset command * * @see The GNU Public License (GPL) Version 3 * @@ -39,7 +39,7 @@ import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObjectField; /** -Firmware IAP +Queries board for SN, model, revision, and sends reset command generated from firmwareiapobj.xml **/ @@ -51,10 +51,18 @@ public class FirmwareIAPObj extends UAVDataObject { List fields = new ArrayList(); + List crcElemNames = new ArrayList(); + crcElemNames.add("0"); + fields.add( new UAVObjectField("crc", "", UAVObjectField.FieldType.UINT32, crcElemNames, null) ); + List CommandElemNames = new ArrayList(); CommandElemNames.add("0"); fields.add( new UAVObjectField("Command", "", UAVObjectField.FieldType.UINT16, CommandElemNames, null) ); + List BoardRevisionElemNames = new ArrayList(); + BoardRevisionElemNames.add("0"); + fields.add( new UAVObjectField("BoardRevision", "", UAVObjectField.FieldType.UINT16, BoardRevisionElemNames, null) ); + List DescriptionElemNames = new ArrayList(); DescriptionElemNames.add("0"); DescriptionElemNames.add("1"); @@ -96,71 +104,22 @@ public class FirmwareIAPObj extends UAVDataObject { DescriptionElemNames.add("37"); DescriptionElemNames.add("38"); DescriptionElemNames.add("39"); - DescriptionElemNames.add("40"); - DescriptionElemNames.add("41"); - DescriptionElemNames.add("42"); - DescriptionElemNames.add("43"); - DescriptionElemNames.add("44"); - DescriptionElemNames.add("45"); - DescriptionElemNames.add("46"); - DescriptionElemNames.add("47"); - DescriptionElemNames.add("48"); - DescriptionElemNames.add("49"); - DescriptionElemNames.add("50"); - DescriptionElemNames.add("51"); - DescriptionElemNames.add("52"); - DescriptionElemNames.add("53"); - DescriptionElemNames.add("54"); - DescriptionElemNames.add("55"); - DescriptionElemNames.add("56"); - DescriptionElemNames.add("57"); - DescriptionElemNames.add("58"); - DescriptionElemNames.add("59"); - DescriptionElemNames.add("60"); - DescriptionElemNames.add("61"); - DescriptionElemNames.add("62"); - DescriptionElemNames.add("63"); - DescriptionElemNames.add("64"); - DescriptionElemNames.add("65"); - DescriptionElemNames.add("66"); - DescriptionElemNames.add("67"); - DescriptionElemNames.add("68"); - DescriptionElemNames.add("69"); - DescriptionElemNames.add("70"); - DescriptionElemNames.add("71"); - DescriptionElemNames.add("72"); - DescriptionElemNames.add("73"); - DescriptionElemNames.add("74"); - DescriptionElemNames.add("75"); - DescriptionElemNames.add("76"); - DescriptionElemNames.add("77"); - DescriptionElemNames.add("78"); - DescriptionElemNames.add("79"); - DescriptionElemNames.add("80"); - DescriptionElemNames.add("81"); - DescriptionElemNames.add("82"); - DescriptionElemNames.add("83"); - DescriptionElemNames.add("84"); - DescriptionElemNames.add("85"); - DescriptionElemNames.add("86"); - DescriptionElemNames.add("87"); - DescriptionElemNames.add("88"); - DescriptionElemNames.add("89"); - DescriptionElemNames.add("90"); - DescriptionElemNames.add("91"); - DescriptionElemNames.add("92"); - DescriptionElemNames.add("93"); - DescriptionElemNames.add("94"); - DescriptionElemNames.add("95"); - DescriptionElemNames.add("96"); - DescriptionElemNames.add("97"); - DescriptionElemNames.add("98"); - DescriptionElemNames.add("99"); fields.add( new UAVObjectField("Description", "", UAVObjectField.FieldType.UINT8, DescriptionElemNames, null) ); - List BoardRevisionElemNames = new ArrayList(); - BoardRevisionElemNames.add("0"); - fields.add( new UAVObjectField("BoardRevision", "", UAVObjectField.FieldType.UINT16, BoardRevisionElemNames, null) ); + List CPUSerialElemNames = new ArrayList(); + CPUSerialElemNames.add("0"); + CPUSerialElemNames.add("1"); + CPUSerialElemNames.add("2"); + CPUSerialElemNames.add("3"); + CPUSerialElemNames.add("4"); + CPUSerialElemNames.add("5"); + CPUSerialElemNames.add("6"); + CPUSerialElemNames.add("7"); + CPUSerialElemNames.add("8"); + CPUSerialElemNames.add("9"); + CPUSerialElemNames.add("10"); + CPUSerialElemNames.add("11"); + fields.add( new UAVObjectField("CPUSerial", "", UAVObjectField.FieldType.UINT8, CPUSerialElemNames, null) ); List BoardTypeElemNames = new ArrayList(); BoardTypeElemNames.add("0"); @@ -170,10 +129,6 @@ public class FirmwareIAPObj extends UAVDataObject { ArmResetElemNames.add("0"); fields.add( new UAVObjectField("ArmReset", "", UAVObjectField.FieldType.UINT8, ArmResetElemNames, null) ); - List crcElemNames = new ArrayList(); - crcElemNames.add("0"); - fields.add( new UAVObjectField("crc", "", UAVObjectField.FieldType.UINT32, crcElemNames, null) ); - // Compute the number of bytes for this object int numBytes = 0; @@ -247,9 +202,9 @@ public class FirmwareIAPObj extends UAVDataObject { } // Constants - protected static final int OBJID = 0x1A8ECC2; + protected static final int OBJID = 0x3CCDFB68; protected static final String NAME = "FirmwareIAPObj"; - protected static String DESCRIPTION = "Firmware IAP"; + protected static String DESCRIPTION = "Queries board for SN, model, revision, and sends reset command"; protected static final boolean ISSINGLEINST = 1 == 1; protected static final boolean ISSETTINGS = 0 == 1; protected static int NUMBYTES = 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java new file mode 100644 index 000000000..a3bc23eb3 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java @@ -0,0 +1,177 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Flight Battery configuration. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Flight Battery configuration. + +generated from flightbatterysettings.xml + **/ +public class FlightBatterySettings extends UAVDataObject { + + public FlightBatterySettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List CapacityElemNames = new ArrayList(); + CapacityElemNames.add("0"); + fields.add( new UAVObjectField("Capacity", "mAh", UAVObjectField.FieldType.UINT32, CapacityElemNames, null) ); + + List VoltageThresholdsElemNames = new ArrayList(); + VoltageThresholdsElemNames.add("Warning"); + VoltageThresholdsElemNames.add("Alarm"); + fields.add( new UAVObjectField("VoltageThresholds", "V", UAVObjectField.FieldType.FLOAT32, VoltageThresholdsElemNames, null) ); + + List SensorCalibrationsElemNames = new ArrayList(); + SensorCalibrationsElemNames.add("VoltageFactor"); + SensorCalibrationsElemNames.add("CurrentFactor"); + fields.add( new UAVObjectField("SensorCalibrations", "", UAVObjectField.FieldType.FLOAT32, SensorCalibrationsElemNames, null) ); + + List TypeElemNames = new ArrayList(); + TypeElemNames.add("0"); + List TypeEnumOptions = new ArrayList(); + TypeEnumOptions.add("LiPo"); + TypeEnumOptions.add("A123"); + TypeEnumOptions.add("LiCo"); + TypeEnumOptions.add("LiFeSO4"); + TypeEnumOptions.add("None"); + fields.add( new UAVObjectField("Type", "", UAVObjectField.FieldType.ENUM, TypeElemNames, TypeEnumOptions) ); + + List NbCellsElemNames = new ArrayList(); + NbCellsElemNames.add("0"); + fields.add( new UAVObjectField("NbCells", "", UAVObjectField.FieldType.UINT8, NbCellsElemNames, null) ); + + List SensorTypeElemNames = new ArrayList(); + SensorTypeElemNames.add("0"); + List SensorTypeEnumOptions = new ArrayList(); + SensorTypeEnumOptions.add("None"); + fields.add( new UAVObjectField("SensorType", "", UAVObjectField.FieldType.ENUM, SensorTypeElemNames, SensorTypeEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Capacity").setValue(2200); + getField("VoltageThresholds").setValue(9.8,0); + getField("VoltageThresholds").setValue(9.2,1); + getField("SensorCalibrations").setValue(1,0); + getField("SensorCalibrations").setValue(1,1); + getField("Type").setValue("LiPo"); + getField("NbCells").setValue(3); + getField("SensorType").setValue("None"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FlightBatterySettings obj = new FlightBatterySettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FlightBatterySettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (FlightBatterySettings)(objMngr.getObject(FlightBatterySettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xF172BB18; + protected static final String NAME = "FlightBatterySettings"; + protected static String DESCRIPTION = "Flight Battery configuration."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java index d9fba1de5..82fcfae47 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java @@ -154,7 +154,7 @@ public class FlightBatteryState extends UAVDataObject { } // Constants - protected static final int OBJID = 0x791A50E; + protected static final int OBJID = 0x8C0D756; protected static final String NAME = "FlightBatteryState"; protected static String DESCRIPTION = "Battery status information."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java index fdc5bfcb0..dbe959f96 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java @@ -133,7 +133,7 @@ public class FlightPlanControl extends UAVDataObject { } // Constants - protected static final int OBJID = 0x6B4FE6DA; + protected static final int OBJID = 0x53E3F180; protected static final String NAME = "FlightPlanControl"; protected static String DESCRIPTION = "Control the flight plan script"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java index 383e4aff0..6fc39a26e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java @@ -129,7 +129,7 @@ public class FlightPlanSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x85368422; + protected static final int OBJID = 0x92E9FF76; protected static final String NAME = "FlightPlanSettings"; protected static String DESCRIPTION = "Settings for the flight plan module, control the execution of the script"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java index 2303514c0..7b78bce71 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java @@ -51,6 +51,19 @@ public class FlightPlanStatus extends UAVDataObject { List fields = new ArrayList(); + List ErrorFileIDElemNames = new ArrayList(); + ErrorFileIDElemNames.add("0"); + fields.add( new UAVObjectField("ErrorFileID", "", UAVObjectField.FieldType.UINT32, ErrorFileIDElemNames, null) ); + + List ErrorLineNumElemNames = new ArrayList(); + ErrorLineNumElemNames.add("0"); + fields.add( new UAVObjectField("ErrorLineNum", "", UAVObjectField.FieldType.UINT32, ErrorLineNumElemNames, null) ); + + List DebugElemNames = new ArrayList(); + DebugElemNames.add("0"); + DebugElemNames.add("1"); + fields.add( new UAVObjectField("Debug", "", UAVObjectField.FieldType.FLOAT32, DebugElemNames, null) ); + List StatusElemNames = new ArrayList(); StatusElemNames.add("0"); List StatusEnumOptions = new ArrayList(); @@ -83,22 +96,6 @@ public class FlightPlanStatus extends UAVDataObject { ErrorTypeEnumOptions.add("UnknownError"); fields.add( new UAVObjectField("ErrorType", "", UAVObjectField.FieldType.ENUM, ErrorTypeElemNames, ErrorTypeEnumOptions) ); - List ErrorFileIDElemNames = new ArrayList(); - ErrorFileIDElemNames.add("0"); - fields.add( new UAVObjectField("ErrorFileID", "", UAVObjectField.FieldType.UINT32, ErrorFileIDElemNames, null) ); - - List ErrorLineNumElemNames = new ArrayList(); - ErrorLineNumElemNames.add("0"); - fields.add( new UAVObjectField("ErrorLineNum", "", UAVObjectField.FieldType.UINT32, ErrorLineNumElemNames, null) ); - - List Debug1ElemNames = new ArrayList(); - Debug1ElemNames.add("0"); - fields.add( new UAVObjectField("Debug1", "", UAVObjectField.FieldType.FLOAT32, Debug1ElemNames, null) ); - - List Debug2ElemNames = new ArrayList(); - Debug2ElemNames.add("0"); - fields.add( new UAVObjectField("Debug2", "", UAVObjectField.FieldType.FLOAT32, Debug2ElemNames, null) ); - // Compute the number of bytes for this object int numBytes = 0; @@ -144,10 +141,10 @@ public class FlightPlanStatus extends UAVDataObject { */ public void setDefaultFieldValues() { + getField("Debug").setValue(0,0); + getField("Debug").setValue(0,1); getField("Status").setValue("Stopped"); getField("ErrorType").setValue("None"); - getField("Debug1").setValue(0); - getField("Debug2").setValue(0); } @@ -176,7 +173,7 @@ public class FlightPlanStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0x9FC14812; + protected static final int OBJID = 0x2206EE46; protected static final String NAME = "FlightPlanStatus"; protected static String DESCRIPTION = "Status of the flight plan script"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java new file mode 100644 index 000000000..d775b21e7 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java @@ -0,0 +1,155 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Contains major flight status information for other modules. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Contains major flight status information for other modules. + +generated from flightstatus.xml + **/ +public class FlightStatus extends UAVDataObject { + + public FlightStatus() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List ArmedElemNames = new ArrayList(); + ArmedElemNames.add("0"); + List ArmedEnumOptions = new ArrayList(); + ArmedEnumOptions.add("Disarmed"); + ArmedEnumOptions.add("Arming"); + ArmedEnumOptions.add("Armed"); + fields.add( new UAVObjectField("Armed", "", UAVObjectField.FieldType.ENUM, ArmedElemNames, ArmedEnumOptions) ); + + List FlightModeElemNames = new ArrayList(); + FlightModeElemNames.add("0"); + List FlightModeEnumOptions = new ArrayList(); + FlightModeEnumOptions.add("Manual"); + FlightModeEnumOptions.add("Stabilized1"); + FlightModeEnumOptions.add("Stabilized2"); + FlightModeEnumOptions.add("Stabilized3"); + FlightModeEnumOptions.add("VelocityControl"); + FlightModeEnumOptions.add("PositionHold"); + fields.add( new UAVObjectField("FlightMode", "", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 5000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Armed").setValue("Disarmed"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FlightStatus obj = new FlightStatus(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FlightStatus GetInstance(UAVObjectManager objMngr, int instID) + { + return (FlightStatus)(objMngr.getObject(FlightStatus.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x743DB13C; + protected static final String NAME = "FlightStatus"; + protected static String DESCRIPTION = "Contains major flight status information for other modules."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java index b58fe6d46..403ea1d5e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java @@ -51,15 +51,6 @@ public class FlightTelemetryStats extends UAVDataObject { List fields = new ArrayList(); - List StatusElemNames = new ArrayList(); - StatusElemNames.add("0"); - List StatusEnumOptions = new ArrayList(); - StatusEnumOptions.add("Disconnected"); - StatusEnumOptions.add("HandshakeReq"); - StatusEnumOptions.add("HandshakeAck"); - StatusEnumOptions.add("Connected"); - fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); - List TxDataRateElemNames = new ArrayList(); TxDataRateElemNames.add("0"); fields.add( new UAVObjectField("TxDataRate", "bytes/sec", UAVObjectField.FieldType.FLOAT32, TxDataRateElemNames, null) ); @@ -80,6 +71,15 @@ public class FlightTelemetryStats extends UAVDataObject { TxRetriesElemNames.add("0"); fields.add( new UAVObjectField("TxRetries", "count", UAVObjectField.FieldType.UINT32, TxRetriesElemNames, null) ); + List StatusElemNames = new ArrayList(); + StatusElemNames.add("0"); + List StatusEnumOptions = new ArrayList(); + StatusEnumOptions.add("Disconnected"); + StatusEnumOptions.add("HandshakeReq"); + StatusEnumOptions.add("HandshakeAck"); + StatusEnumOptions.add("Connected"); + fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -153,7 +153,7 @@ public class FlightTelemetryStats extends UAVDataObject { } // Constants - protected static final int OBJID = 0x660C265E; + protected static final int OBJID = 0x2F7E2902; protected static final String NAME = "FlightTelemetryStats"; protected static String DESCRIPTION = "Maintains the telemetry statistics from the OpenPilot flight computer."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java new file mode 100644 index 000000000..3cb3811ae --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java @@ -0,0 +1,144 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * A receiver channel group carried over the telemetry link. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +A receiver channel group carried over the telemetry link. + +generated from gcsreceiver.xml + **/ +public class GCSReceiver extends UAVDataObject { + + public GCSReceiver() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List ChannelElemNames = new ArrayList(); + ChannelElemNames.add("0"); + ChannelElemNames.add("1"); + ChannelElemNames.add("2"); + ChannelElemNames.add("3"); + ChannelElemNames.add("4"); + ChannelElemNames.add("5"); + fields.add( new UAVObjectField("Channel", "us", UAVObjectField.FieldType.UINT16, ChannelElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READONLY; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GCSReceiver obj = new GCSReceiver(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GCSReceiver GetInstance(UAVObjectManager objMngr, int instID) + { + return (GCSReceiver)(objMngr.getObject(GCSReceiver.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xCC7E2BBC; + protected static final String NAME = "GCSReceiver"; + protected static String DESCRIPTION = "A receiver channel group carried over the telemetry link."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java index 0f304d45d..b32f551ce 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java @@ -51,15 +51,6 @@ public class GCSTelemetryStats extends UAVDataObject { List fields = new ArrayList(); - List StatusElemNames = new ArrayList(); - StatusElemNames.add("0"); - List StatusEnumOptions = new ArrayList(); - StatusEnumOptions.add("Disconnected"); - StatusEnumOptions.add("HandshakeReq"); - StatusEnumOptions.add("HandshakeAck"); - StatusEnumOptions.add("Connected"); - fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); - List TxDataRateElemNames = new ArrayList(); TxDataRateElemNames.add("0"); fields.add( new UAVObjectField("TxDataRate", "bytes/sec", UAVObjectField.FieldType.FLOAT32, TxDataRateElemNames, null) ); @@ -80,6 +71,15 @@ public class GCSTelemetryStats extends UAVDataObject { TxRetriesElemNames.add("0"); fields.add( new UAVObjectField("TxRetries", "count", UAVObjectField.FieldType.UINT32, TxRetriesElemNames, null) ); + List StatusElemNames = new ArrayList(); + StatusElemNames.add("0"); + List StatusEnumOptions = new ArrayList(); + StatusEnumOptions.add("Disconnected"); + StatusEnumOptions.add("HandshakeReq"); + StatusEnumOptions.add("HandshakeAck"); + StatusEnumOptions.add("Connected"); + fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -153,7 +153,7 @@ public class GCSTelemetryStats extends UAVDataObject { } // Constants - protected static final int OBJID = 0x771E1046; + protected static final int OBJID = 0xABC72744; protected static final String NAME = "GCSTelemetryStats"; protected static String DESCRIPTION = "The telemetry statistics from the ground computer"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java index 889091e0e..5f4e20b46 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java @@ -51,15 +51,6 @@ public class GPSPosition extends UAVDataObject { List fields = new ArrayList(); - List StatusElemNames = new ArrayList(); - StatusElemNames.add("0"); - List StatusEnumOptions = new ArrayList(); - StatusEnumOptions.add("NoGPS"); - StatusEnumOptions.add("NoFix"); - StatusEnumOptions.add("Fix2D"); - StatusEnumOptions.add("Fix3D"); - fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); - List LatitudeElemNames = new ArrayList(); LatitudeElemNames.add("0"); fields.add( new UAVObjectField("Latitude", "degrees x 10^-7", UAVObjectField.FieldType.INT32, LatitudeElemNames, null) ); @@ -84,10 +75,6 @@ public class GPSPosition extends UAVDataObject { GroundspeedElemNames.add("0"); fields.add( new UAVObjectField("Groundspeed", "m/s", UAVObjectField.FieldType.FLOAT32, GroundspeedElemNames, null) ); - List SatellitesElemNames = new ArrayList(); - SatellitesElemNames.add("0"); - fields.add( new UAVObjectField("Satellites", "", UAVObjectField.FieldType.INT8, SatellitesElemNames, null) ); - List PDOPElemNames = new ArrayList(); PDOPElemNames.add("0"); fields.add( new UAVObjectField("PDOP", "", UAVObjectField.FieldType.FLOAT32, PDOPElemNames, null) ); @@ -100,6 +87,19 @@ public class GPSPosition extends UAVDataObject { VDOPElemNames.add("0"); fields.add( new UAVObjectField("VDOP", "", UAVObjectField.FieldType.FLOAT32, VDOPElemNames, null) ); + List StatusElemNames = new ArrayList(); + StatusElemNames.add("0"); + List StatusEnumOptions = new ArrayList(); + StatusEnumOptions.add("NoGPS"); + StatusEnumOptions.add("NoFix"); + StatusEnumOptions.add("Fix2D"); + StatusEnumOptions.add("Fix3D"); + fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); + + List SatellitesElemNames = new ArrayList(); + SatellitesElemNames.add("0"); + fields.add( new UAVObjectField("Satellites", "", UAVObjectField.FieldType.INT8, SatellitesElemNames, null) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -173,7 +173,7 @@ public class GPSPosition extends UAVDataObject { } // Constants - protected static final int OBJID = 0xB5495042; + protected static final int OBJID = 0xE2A323B6; protected static final String NAME = "GPSPosition"; protected static String DESCRIPTION = "Raw GPS data from @ref GPSModule. Should only be used by @ref AHRSCommsModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java index fa1100207..bb331132d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java @@ -51,29 +51,6 @@ public class GPSSatellites extends UAVDataObject { List fields = new ArrayList(); - List SatsInViewElemNames = new ArrayList(); - SatsInViewElemNames.add("0"); - fields.add( new UAVObjectField("SatsInView", "", UAVObjectField.FieldType.INT8, SatsInViewElemNames, null) ); - - List PRNElemNames = new ArrayList(); - PRNElemNames.add("0"); - PRNElemNames.add("1"); - PRNElemNames.add("2"); - PRNElemNames.add("3"); - PRNElemNames.add("4"); - PRNElemNames.add("5"); - PRNElemNames.add("6"); - PRNElemNames.add("7"); - PRNElemNames.add("8"); - PRNElemNames.add("9"); - PRNElemNames.add("10"); - PRNElemNames.add("11"); - PRNElemNames.add("12"); - PRNElemNames.add("13"); - PRNElemNames.add("14"); - PRNElemNames.add("15"); - fields.add( new UAVObjectField("PRN", "", UAVObjectField.FieldType.INT8, PRNElemNames, null) ); - List ElevationElemNames = new ArrayList(); ElevationElemNames.add("0"); ElevationElemNames.add("1"); @@ -112,6 +89,29 @@ public class GPSSatellites extends UAVDataObject { AzimuthElemNames.add("15"); fields.add( new UAVObjectField("Azimuth", "degrees", UAVObjectField.FieldType.FLOAT32, AzimuthElemNames, null) ); + List SatsInViewElemNames = new ArrayList(); + SatsInViewElemNames.add("0"); + fields.add( new UAVObjectField("SatsInView", "", UAVObjectField.FieldType.INT8, SatsInViewElemNames, null) ); + + List PRNElemNames = new ArrayList(); + PRNElemNames.add("0"); + PRNElemNames.add("1"); + PRNElemNames.add("2"); + PRNElemNames.add("3"); + PRNElemNames.add("4"); + PRNElemNames.add("5"); + PRNElemNames.add("6"); + PRNElemNames.add("7"); + PRNElemNames.add("8"); + PRNElemNames.add("9"); + PRNElemNames.add("10"); + PRNElemNames.add("11"); + PRNElemNames.add("12"); + PRNElemNames.add("13"); + PRNElemNames.add("14"); + PRNElemNames.add("15"); + fields.add( new UAVObjectField("PRN", "", UAVObjectField.FieldType.INT8, PRNElemNames, null) ); + List SNRElemNames = new ArrayList(); SNRElemNames.add("0"); SNRElemNames.add("1"); @@ -204,7 +204,7 @@ public class GPSSatellites extends UAVDataObject { } // Constants - protected static final int OBJID = 0xD62FA3AE; + protected static final int OBJID = 0x920D998; protected static final String NAME = "GPSSatellites"; protected static String DESCRIPTION = "Contains information about the GPS satellites in view from @ref GPSModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java index 5ff55cc2e..5aa4df7bf 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java @@ -51,6 +51,10 @@ public class GPSTime extends UAVDataObject { List fields = new ArrayList(); + List YearElemNames = new ArrayList(); + YearElemNames.add("0"); + fields.add( new UAVObjectField("Year", "", UAVObjectField.FieldType.INT16, YearElemNames, null) ); + List MonthElemNames = new ArrayList(); MonthElemNames.add("0"); fields.add( new UAVObjectField("Month", "", UAVObjectField.FieldType.INT8, MonthElemNames, null) ); @@ -59,10 +63,6 @@ public class GPSTime extends UAVDataObject { DayElemNames.add("0"); fields.add( new UAVObjectField("Day", "", UAVObjectField.FieldType.INT8, DayElemNames, null) ); - List YearElemNames = new ArrayList(); - YearElemNames.add("0"); - fields.add( new UAVObjectField("Year", "", UAVObjectField.FieldType.INT16, YearElemNames, null) ); - List HourElemNames = new ArrayList(); HourElemNames.add("0"); fields.add( new UAVObjectField("Hour", "", UAVObjectField.FieldType.INT8, HourElemNames, null) ); @@ -148,7 +148,7 @@ public class GPSTime extends UAVDataObject { } // Constants - protected static final int OBJID = 0x56FFF0A2; + protected static final int OBJID = 0xD4478084; protected static final String NAME = "GPSTime"; protected static String DESCRIPTION = "Contains the GPS time from @ref GPSModule. Required to compute the world magnetic model correctly when setting the home location."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java index 2fe8bb437..205384efe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java @@ -51,29 +51,24 @@ public class GuidanceSettings extends UAVDataObject { List fields = new ArrayList(); - List GuidanceModeElemNames = new ArrayList(); - GuidanceModeElemNames.add("0"); - List GuidanceModeEnumOptions = new ArrayList(); - GuidanceModeEnumOptions.add("DUAL_LOOP"); - GuidanceModeEnumOptions.add("VELOCITY_CONTROL"); - fields.add( new UAVObjectField("GuidanceMode", "", UAVObjectField.FieldType.ENUM, GuidanceModeElemNames, GuidanceModeEnumOptions) ); - - List HorizontalPElemNames = new ArrayList(); - HorizontalPElemNames.add("Kp"); - HorizontalPElemNames.add("Max"); - fields.add( new UAVObjectField("HorizontalP", "", UAVObjectField.FieldType.FLOAT32, HorizontalPElemNames, null) ); + List HorizontalPosPIElemNames = new ArrayList(); + HorizontalPosPIElemNames.add("Kp"); + HorizontalPosPIElemNames.add("Ki"); + HorizontalPosPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("HorizontalPosPI", "(cm/s)/cm", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) ); List HorizontalVelPIDElemNames = new ArrayList(); HorizontalVelPIDElemNames.add("Kp"); HorizontalVelPIDElemNames.add("Ki"); HorizontalVelPIDElemNames.add("Kd"); HorizontalVelPIDElemNames.add("ILimit"); - fields.add( new UAVObjectField("HorizontalVelPID", "", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); + fields.add( new UAVObjectField("HorizontalVelPID", "deg/(cm/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); - List VerticalPElemNames = new ArrayList(); - VerticalPElemNames.add("Kp"); - VerticalPElemNames.add("Max"); - fields.add( new UAVObjectField("VerticalP", "", UAVObjectField.FieldType.FLOAT32, VerticalPElemNames, null) ); + List VerticalPosPIElemNames = new ArrayList(); + VerticalPosPIElemNames.add("Kp"); + VerticalPosPIElemNames.add("Ki"); + VerticalPosPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("VerticalPosPI", "", UAVObjectField.FieldType.FLOAT32, VerticalPosPIElemNames, null) ); List VerticalVelPIDElemNames = new ArrayList(); VerticalVelPIDElemNames.add("Kp"); @@ -82,13 +77,6 @@ public class GuidanceSettings extends UAVDataObject { VerticalVelPIDElemNames.add("ILimit"); fields.add( new UAVObjectField("VerticalVelPID", "", UAVObjectField.FieldType.FLOAT32, VerticalVelPIDElemNames, null) ); - List ThrottleControlElemNames = new ArrayList(); - ThrottleControlElemNames.add("0"); - List ThrottleControlEnumOptions = new ArrayList(); - ThrottleControlEnumOptions.add("FALSE"); - ThrottleControlEnumOptions.add("TRUE"); - fields.add( new UAVObjectField("ThrottleControl", "", UAVObjectField.FieldType.ENUM, ThrottleControlElemNames, ThrottleControlEnumOptions) ); - List MaxRollPitchElemNames = new ArrayList(); MaxRollPitchElemNames.add("0"); fields.add( new UAVObjectField("MaxRollPitch", "deg", UAVObjectField.FieldType.FLOAT32, MaxRollPitchElemNames, null) ); @@ -97,6 +85,28 @@ public class GuidanceSettings extends UAVDataObject { UpdatePeriodElemNames.add("0"); fields.add( new UAVObjectField("UpdatePeriod", "", UAVObjectField.FieldType.INT32, UpdatePeriodElemNames, null) ); + List HorizontalVelMaxElemNames = new ArrayList(); + HorizontalVelMaxElemNames.add("0"); + fields.add( new UAVObjectField("HorizontalVelMax", "cm/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) ); + + List VerticalVelMaxElemNames = new ArrayList(); + VerticalVelMaxElemNames.add("0"); + fields.add( new UAVObjectField("VerticalVelMax", "cm/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) ); + + List GuidanceModeElemNames = new ArrayList(); + GuidanceModeElemNames.add("0"); + List GuidanceModeEnumOptions = new ArrayList(); + GuidanceModeEnumOptions.add("DUAL_LOOP"); + GuidanceModeEnumOptions.add("VELOCITY_CONTROL"); + fields.add( new UAVObjectField("GuidanceMode", "", UAVObjectField.FieldType.ENUM, GuidanceModeElemNames, GuidanceModeEnumOptions) ); + + List ThrottleControlElemNames = new ArrayList(); + ThrottleControlElemNames.add("0"); + List ThrottleControlEnumOptions = new ArrayList(); + ThrottleControlEnumOptions.add("FALSE"); + ThrottleControlEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("ThrottleControl", "", UAVObjectField.FieldType.ENUM, ThrottleControlElemNames, ThrottleControlEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -142,22 +152,26 @@ public class GuidanceSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("GuidanceMode").setValue("DUAL_LOOP"); - getField("HorizontalP").setValue(0.2,0); - getField("HorizontalP").setValue(150,1); - getField("HorizontalVelPID").setValue(0.1,0); + getField("HorizontalPosPI").setValue(0.1,0); + getField("HorizontalPosPI").setValue(0.001,1); + getField("HorizontalPosPI").setValue(300,2); + getField("HorizontalVelPID").setValue(0.05,0); getField("HorizontalVelPID").setValue(0.002,1); getField("HorizontalVelPID").setValue(0,2); getField("HorizontalVelPID").setValue(1000,3); - getField("VerticalP").setValue(0.1,0); - getField("VerticalP").setValue(200,1); + getField("VerticalPosPI").setValue(0.1,0); + getField("VerticalPosPI").setValue(0.001,1); + getField("VerticalPosPI").setValue(200,2); getField("VerticalVelPID").setValue(0.1,0); getField("VerticalVelPID").setValue(0,1); getField("VerticalVelPID").setValue(0,2); getField("VerticalVelPID").setValue(0,3); - getField("ThrottleControl").setValue("FALSE"); getField("MaxRollPitch").setValue(10); getField("UpdatePeriod").setValue(100); + getField("HorizontalVelMax").setValue(300); + getField("VerticalVelMax").setValue(150); + getField("GuidanceMode").setValue("DUAL_LOOP"); + getField("ThrottleControl").setValue("FALSE"); } @@ -186,7 +200,7 @@ public class GuidanceSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x74740AA2; + protected static final int OBJID = 0x6EA79FB4; protected static final String NAME = "GuidanceSettings"; protected static String DESCRIPTION = "Settings for the @ref GuidanceModule"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java index 5941c069c..68abb3633 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java @@ -51,13 +51,6 @@ public class HomeLocation extends UAVDataObject { List fields = new ArrayList(); - List SetElemNames = new ArrayList(); - SetElemNames.add("0"); - List SetEnumOptions = new ArrayList(); - SetEnumOptions.add("FALSE"); - SetEnumOptions.add("TRUE"); - fields.add( new UAVObjectField("Set", "", UAVObjectField.FieldType.ENUM, SetElemNames, SetEnumOptions) ); - List LatitudeElemNames = new ArrayList(); LatitudeElemNames.add("0"); fields.add( new UAVObjectField("Latitude", "deg * 10e6", UAVObjectField.FieldType.INT32, LatitudeElemNames, null) ); @@ -94,6 +87,17 @@ public class HomeLocation extends UAVDataObject { BeElemNames.add("2"); fields.add( new UAVObjectField("Be", "", UAVObjectField.FieldType.FLOAT32, BeElemNames, null) ); + List g_eElemNames = new ArrayList(); + g_eElemNames.add("0"); + fields.add( new UAVObjectField("g_e", "m/s^2", UAVObjectField.FieldType.FLOAT32, g_eElemNames, null) ); + + List SetElemNames = new ArrayList(); + SetElemNames.add("0"); + List SetEnumOptions = new ArrayList(); + SetEnumOptions.add("FALSE"); + SetEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("Set", "", UAVObjectField.FieldType.ENUM, SetElemNames, SetEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -139,7 +143,6 @@ public class HomeLocation extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("Set").setValue("FALSE"); getField("Latitude").setValue(0); getField("Longitude").setValue(0); getField("Altitude").setValue(0); @@ -158,6 +161,8 @@ public class HomeLocation extends UAVDataObject { getField("Be").setValue(0,0); getField("Be").setValue(0,1); getField("Be").setValue(0,2); + getField("g_e").setValue(9.81); + getField("Set").setValue("FALSE"); } @@ -186,7 +191,7 @@ public class HomeLocation extends UAVDataObject { } // Constants - protected static final int OBJID = 0xD6008ED2; + protected static final int OBJID = 0x5BB3AEFC; protected static final String NAME = "HomeLocation"; protected static String DESCRIPTION = "HomeLocation setting which contains the constants to tranlate from longitutde and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java new file mode 100644 index 000000000..83b7ae7b6 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java @@ -0,0 +1,291 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Selection of optional hardware configurations. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Selection of optional hardware configurations. + +generated from hwsettings.xml + **/ +public class HwSettings extends UAVDataObject { + + public HwSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List CC_RcvrPortElemNames = new ArrayList(); + CC_RcvrPortElemNames.add("0"); + List CC_RcvrPortEnumOptions = new ArrayList(); + CC_RcvrPortEnumOptions.add("Disabled"); + CC_RcvrPortEnumOptions.add("PWM"); + CC_RcvrPortEnumOptions.add("PPM"); + CC_RcvrPortEnumOptions.add("PPM+Outputs"); + CC_RcvrPortEnumOptions.add("Outputs"); + fields.add( new UAVObjectField("CC_RcvrPort", "function", UAVObjectField.FieldType.ENUM, CC_RcvrPortElemNames, CC_RcvrPortEnumOptions) ); + + List CC_MainPortElemNames = new ArrayList(); + CC_MainPortElemNames.add("0"); + List CC_MainPortEnumOptions = new ArrayList(); + CC_MainPortEnumOptions.add("Disabled"); + CC_MainPortEnumOptions.add("Telemetry"); + CC_MainPortEnumOptions.add("GPS"); + CC_MainPortEnumOptions.add("S.Bus"); + CC_MainPortEnumOptions.add("DSM2"); + CC_MainPortEnumOptions.add("DSMX (10bit)"); + CC_MainPortEnumOptions.add("DSMX (11bit)"); + CC_MainPortEnumOptions.add("ComAux"); + CC_MainPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("CC_MainPort", "function", UAVObjectField.FieldType.ENUM, CC_MainPortElemNames, CC_MainPortEnumOptions) ); + + List CC_FlexiPortElemNames = new ArrayList(); + CC_FlexiPortElemNames.add("0"); + List CC_FlexiPortEnumOptions = new ArrayList(); + CC_FlexiPortEnumOptions.add("Disabled"); + CC_FlexiPortEnumOptions.add("Telemetry"); + CC_FlexiPortEnumOptions.add("GPS"); + CC_FlexiPortEnumOptions.add("I2C"); + CC_FlexiPortEnumOptions.add("DSM2"); + CC_FlexiPortEnumOptions.add("DSMX (10bit)"); + CC_FlexiPortEnumOptions.add("DSMX (11bit)"); + CC_FlexiPortEnumOptions.add("ComAux"); + CC_FlexiPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("CC_FlexiPort", "function", UAVObjectField.FieldType.ENUM, CC_FlexiPortElemNames, CC_FlexiPortEnumOptions) ); + + List OP_RcvrPortElemNames = new ArrayList(); + OP_RcvrPortElemNames.add("0"); + List OP_RcvrPortEnumOptions = new ArrayList(); + OP_RcvrPortEnumOptions.add("Disabled"); + OP_RcvrPortEnumOptions.add("PWM"); + OP_RcvrPortEnumOptions.add("PPM"); + OP_RcvrPortEnumOptions.add("DSM2"); + OP_RcvrPortEnumOptions.add("DSMX (10bit)"); + OP_RcvrPortEnumOptions.add("DSMX (11bit)"); + OP_RcvrPortEnumOptions.add("Debug"); + fields.add( new UAVObjectField("OP_RcvrPort", "function", UAVObjectField.FieldType.ENUM, OP_RcvrPortElemNames, OP_RcvrPortEnumOptions) ); + + List OP_MainPortElemNames = new ArrayList(); + OP_MainPortElemNames.add("0"); + List OP_MainPortEnumOptions = new ArrayList(); + OP_MainPortEnumOptions.add("Disabled"); + OP_MainPortEnumOptions.add("Telemetry"); + fields.add( new UAVObjectField("OP_MainPort", "function", UAVObjectField.FieldType.ENUM, OP_MainPortElemNames, OP_MainPortEnumOptions) ); + + List OP_FlexiPortElemNames = new ArrayList(); + OP_FlexiPortElemNames.add("0"); + List OP_FlexiPortEnumOptions = new ArrayList(); + OP_FlexiPortEnumOptions.add("Disabled"); + OP_FlexiPortEnumOptions.add("GPS"); + fields.add( new UAVObjectField("OP_FlexiPort", "function", UAVObjectField.FieldType.ENUM, OP_FlexiPortElemNames, OP_FlexiPortEnumOptions) ); + + List TelemetrySpeedElemNames = new ArrayList(); + TelemetrySpeedElemNames.add("0"); + List TelemetrySpeedEnumOptions = new ArrayList(); + TelemetrySpeedEnumOptions.add("2400"); + TelemetrySpeedEnumOptions.add("4800"); + TelemetrySpeedEnumOptions.add("9600"); + TelemetrySpeedEnumOptions.add("19200"); + TelemetrySpeedEnumOptions.add("38400"); + TelemetrySpeedEnumOptions.add("57600"); + TelemetrySpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("TelemetrySpeed", "bps", UAVObjectField.FieldType.ENUM, TelemetrySpeedElemNames, TelemetrySpeedEnumOptions) ); + + List GPSSpeedElemNames = new ArrayList(); + GPSSpeedElemNames.add("0"); + List GPSSpeedEnumOptions = new ArrayList(); + GPSSpeedEnumOptions.add("2400"); + GPSSpeedEnumOptions.add("4800"); + GPSSpeedEnumOptions.add("9600"); + GPSSpeedEnumOptions.add("19200"); + GPSSpeedEnumOptions.add("38400"); + GPSSpeedEnumOptions.add("57600"); + GPSSpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("GPSSpeed", "bps", UAVObjectField.FieldType.ENUM, GPSSpeedElemNames, GPSSpeedEnumOptions) ); + + List ComUsbBridgeSpeedElemNames = new ArrayList(); + ComUsbBridgeSpeedElemNames.add("0"); + List ComUsbBridgeSpeedEnumOptions = new ArrayList(); + ComUsbBridgeSpeedEnumOptions.add("2400"); + ComUsbBridgeSpeedEnumOptions.add("4800"); + ComUsbBridgeSpeedEnumOptions.add("9600"); + ComUsbBridgeSpeedEnumOptions.add("19200"); + ComUsbBridgeSpeedEnumOptions.add("38400"); + ComUsbBridgeSpeedEnumOptions.add("57600"); + ComUsbBridgeSpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("ComUsbBridgeSpeed", "bps", UAVObjectField.FieldType.ENUM, ComUsbBridgeSpeedElemNames, ComUsbBridgeSpeedEnumOptions) ); + + List USB_DeviceTypeElemNames = new ArrayList(); + USB_DeviceTypeElemNames.add("0"); + List USB_DeviceTypeEnumOptions = new ArrayList(); + USB_DeviceTypeEnumOptions.add("HID-only"); + USB_DeviceTypeEnumOptions.add("HID+VCP"); + USB_DeviceTypeEnumOptions.add("VCP-only"); + fields.add( new UAVObjectField("USB_DeviceType", "descriptor", UAVObjectField.FieldType.ENUM, USB_DeviceTypeElemNames, USB_DeviceTypeEnumOptions) ); + + List USB_HIDPortElemNames = new ArrayList(); + USB_HIDPortElemNames.add("0"); + List USB_HIDPortEnumOptions = new ArrayList(); + USB_HIDPortEnumOptions.add("USBTelemetry"); + USB_HIDPortEnumOptions.add("Disabled"); + fields.add( new UAVObjectField("USB_HIDPort", "function", UAVObjectField.FieldType.ENUM, USB_HIDPortElemNames, USB_HIDPortEnumOptions) ); + + List USB_VCPPortElemNames = new ArrayList(); + USB_VCPPortElemNames.add("0"); + List USB_VCPPortEnumOptions = new ArrayList(); + USB_VCPPortEnumOptions.add("USBTelemetry"); + USB_VCPPortEnumOptions.add("ComBridge"); + USB_VCPPortEnumOptions.add("Disabled"); + fields.add( new UAVObjectField("USB_VCPPort", "function", UAVObjectField.FieldType.ENUM, USB_VCPPortElemNames, USB_VCPPortEnumOptions) ); + + List OptionalModulesElemNames = new ArrayList(); + OptionalModulesElemNames.add("CameraStab"); + OptionalModulesElemNames.add("GPS"); + OptionalModulesElemNames.add("ComUsbBridge"); + OptionalModulesElemNames.add("Fault"); + OptionalModulesElemNames.add("Altitude"); + List OptionalModulesEnumOptions = new ArrayList(); + OptionalModulesEnumOptions.add("Disabled"); + OptionalModulesEnumOptions.add("Enabled"); + fields.add( new UAVObjectField("OptionalModules", "", UAVObjectField.FieldType.ENUM, OptionalModulesElemNames, OptionalModulesEnumOptions) ); + + List DSMxBindElemNames = new ArrayList(); + DSMxBindElemNames.add("0"); + fields.add( new UAVObjectField("DSMxBind", "", UAVObjectField.FieldType.UINT8, DSMxBindElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("CC_RcvrPort").setValue("PWM"); + getField("CC_MainPort").setValue("Disabled"); + getField("CC_FlexiPort").setValue("Disabled"); + getField("OP_RcvrPort").setValue("PWM"); + getField("OP_MainPort").setValue("Telemetry"); + getField("OP_FlexiPort").setValue("GPS"); + getField("TelemetrySpeed").setValue("57600"); + getField("GPSSpeed").setValue("57600"); + getField("ComUsbBridgeSpeed").setValue("57600"); + getField("USB_DeviceType").setValue("HID-only"); + getField("USB_HIDPort").setValue("USBTelemetry"); + getField("USB_VCPPort").setValue("Disabled"); + getField("OptionalModules").setValue("Disabled",0); + getField("OptionalModules").setValue("Disabled",1); + getField("OptionalModules").setValue("Disabled",2); + getField("OptionalModules").setValue("Disabled",3); + getField("OptionalModules").setValue("Disabled",4); + getField("DSMxBind").setValue(0); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + HwSettings obj = new HwSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public HwSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (HwSettings)(objMngr.getObject(HwSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x2EE6575A; + protected static final String NAME = "HwSettings"; + protected static String DESCRIPTION = "Selection of optional hardware configurations."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java index fc68e2902..abd8f41f6 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java @@ -51,6 +51,22 @@ public class I2CStats extends UAVDataObject { List fields = new ArrayList(); + List evirq_logElemNames = new ArrayList(); + evirq_logElemNames.add("0"); + evirq_logElemNames.add("1"); + evirq_logElemNames.add("2"); + evirq_logElemNames.add("3"); + evirq_logElemNames.add("4"); + fields.add( new UAVObjectField("evirq_log", "", UAVObjectField.FieldType.UINT32, evirq_logElemNames, null) ); + + List erirq_logElemNames = new ArrayList(); + erirq_logElemNames.add("0"); + erirq_logElemNames.add("1"); + erirq_logElemNames.add("2"); + erirq_logElemNames.add("3"); + erirq_logElemNames.add("4"); + fields.add( new UAVObjectField("erirq_log", "", UAVObjectField.FieldType.UINT32, erirq_logElemNames, null) ); + List event_errorsElemNames = new ArrayList(); event_errorsElemNames.add("0"); fields.add( new UAVObjectField("event_errors", "", UAVObjectField.FieldType.UINT8, event_errorsElemNames, null) ); @@ -79,22 +95,6 @@ public class I2CStats extends UAVDataObject { last_error_typeEnumOptions.add("INTERRUPT"); fields.add( new UAVObjectField("last_error_type", "", UAVObjectField.FieldType.ENUM, last_error_typeElemNames, last_error_typeEnumOptions) ); - List evirq_logElemNames = new ArrayList(); - evirq_logElemNames.add("0"); - evirq_logElemNames.add("1"); - evirq_logElemNames.add("2"); - evirq_logElemNames.add("3"); - evirq_logElemNames.add("4"); - fields.add( new UAVObjectField("evirq_log", "", UAVObjectField.FieldType.UINT32, evirq_logElemNames, null) ); - - List erirq_logElemNames = new ArrayList(); - erirq_logElemNames.add("0"); - erirq_logElemNames.add("1"); - erirq_logElemNames.add("2"); - erirq_logElemNames.add("3"); - erirq_logElemNames.add("4"); - fields.add( new UAVObjectField("erirq_log", "", UAVObjectField.FieldType.UINT32, erirq_logElemNames, null) ); - List event_logElemNames = new ArrayList(); event_logElemNames.add("0"); event_logElemNames.add("1"); @@ -227,7 +227,7 @@ public class I2CStats extends UAVDataObject { } // Constants - protected static final int OBJID = 0x23CE9E9C; + protected static final int OBJID = 0xB714823E; protected static final String NAME = "I2CStats"; protected static String DESCRIPTION = "Tracks statistics on the I2C bus."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java index 636f30946..6ac5a1b2c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java @@ -51,19 +51,9 @@ public class ManualControlCommand extends UAVDataObject { List fields = new ArrayList(); - List ConnectedElemNames = new ArrayList(); - ConnectedElemNames.add("0"); - List ConnectedEnumOptions = new ArrayList(); - ConnectedEnumOptions.add("False"); - ConnectedEnumOptions.add("True"); - fields.add( new UAVObjectField("Connected", "", UAVObjectField.FieldType.ENUM, ConnectedElemNames, ConnectedEnumOptions) ); - - List ArmedElemNames = new ArrayList(); - ArmedElemNames.add("0"); - List ArmedEnumOptions = new ArrayList(); - ArmedEnumOptions.add("False"); - ArmedEnumOptions.add("True"); - fields.add( new UAVObjectField("Armed", "", UAVObjectField.FieldType.ENUM, ArmedElemNames, ArmedEnumOptions) ); + List ThrottleElemNames = new ArrayList(); + ThrottleElemNames.add("0"); + fields.add( new UAVObjectField("Throttle", "%", UAVObjectField.FieldType.FLOAT32, ThrottleElemNames, null) ); List RollElemNames = new ArrayList(); RollElemNames.add("0"); @@ -77,32 +67,9 @@ public class ManualControlCommand extends UAVDataObject { YawElemNames.add("0"); fields.add( new UAVObjectField("Yaw", "%", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); - List ThrottleElemNames = new ArrayList(); - ThrottleElemNames.add("0"); - fields.add( new UAVObjectField("Throttle", "%", UAVObjectField.FieldType.FLOAT32, ThrottleElemNames, null) ); - - List FlightModeElemNames = new ArrayList(); - FlightModeElemNames.add("0"); - List FlightModeEnumOptions = new ArrayList(); - FlightModeEnumOptions.add("Manual"); - FlightModeEnumOptions.add("Stabilized1"); - FlightModeEnumOptions.add("Stabilized2"); - FlightModeEnumOptions.add("Stabilized3"); - FlightModeEnumOptions.add("VelocityControl"); - FlightModeEnumOptions.add("PositionHold"); - fields.add( new UAVObjectField("FlightMode", "", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); - - List Accessory1ElemNames = new ArrayList(); - Accessory1ElemNames.add("0"); - fields.add( new UAVObjectField("Accessory1", "%", UAVObjectField.FieldType.FLOAT32, Accessory1ElemNames, null) ); - - List Accessory2ElemNames = new ArrayList(); - Accessory2ElemNames.add("0"); - fields.add( new UAVObjectField("Accessory2", "%", UAVObjectField.FieldType.FLOAT32, Accessory2ElemNames, null) ); - - List Accessory3ElemNames = new ArrayList(); - Accessory3ElemNames.add("0"); - fields.add( new UAVObjectField("Accessory3", "%", UAVObjectField.FieldType.FLOAT32, Accessory3ElemNames, null) ); + List CollectiveElemNames = new ArrayList(); + CollectiveElemNames.add("0"); + fields.add( new UAVObjectField("Collective", "%", UAVObjectField.FieldType.FLOAT32, CollectiveElemNames, null) ); List ChannelElemNames = new ArrayList(); ChannelElemNames.add("0"); @@ -113,8 +80,16 @@ public class ManualControlCommand extends UAVDataObject { ChannelElemNames.add("5"); ChannelElemNames.add("6"); ChannelElemNames.add("7"); + ChannelElemNames.add("8"); fields.add( new UAVObjectField("Channel", "us", UAVObjectField.FieldType.UINT16, ChannelElemNames, null) ); + List ConnectedElemNames = new ArrayList(); + ConnectedElemNames.add("0"); + List ConnectedEnumOptions = new ArrayList(); + ConnectedEnumOptions.add("False"); + ConnectedEnumOptions.add("True"); + fields.add( new UAVObjectField("Connected", "", UAVObjectField.FieldType.ENUM, ConnectedElemNames, ConnectedEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -188,7 +163,7 @@ public class ManualControlCommand extends UAVDataObject { } // Constants - protected static final int OBJID = 0x926794; + protected static final int OBJID = 0x1E82C2D2; protected static final String NAME = "ManualControlCommand"; protected static String DESCRIPTION = "The output from the @ref ManualControlModule which descodes the receiver inputs. Overriden by GCS for fly-by-wire control."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java index 83697999a..bb846695d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java @@ -51,125 +51,77 @@ public class ManualControlSettings extends UAVDataObject { List fields = new ArrayList(); - List InputModeElemNames = new ArrayList(); - InputModeElemNames.add("0"); - List InputModeEnumOptions = new ArrayList(); - InputModeEnumOptions.add("PWM"); - InputModeEnumOptions.add("PPM"); - InputModeEnumOptions.add("Spektrum"); - fields.add( new UAVObjectField("InputMode", "", UAVObjectField.FieldType.ENUM, InputModeElemNames, InputModeEnumOptions) ); + List ChannelMinElemNames = new ArrayList(); + ChannelMinElemNames.add("Throttle"); + ChannelMinElemNames.add("Roll"); + ChannelMinElemNames.add("Pitch"); + ChannelMinElemNames.add("Yaw"); + ChannelMinElemNames.add("FlightMode"); + ChannelMinElemNames.add("Collective"); + ChannelMinElemNames.add("Accessory0"); + ChannelMinElemNames.add("Accessory1"); + ChannelMinElemNames.add("Accessory2"); + fields.add( new UAVObjectField("ChannelMin", "us", UAVObjectField.FieldType.INT16, ChannelMinElemNames, null) ); - List RollElemNames = new ArrayList(); - RollElemNames.add("0"); - List RollEnumOptions = new ArrayList(); - RollEnumOptions.add("Channel1"); - RollEnumOptions.add("Channel2"); - RollEnumOptions.add("Channel3"); - RollEnumOptions.add("Channel4"); - RollEnumOptions.add("Channel5"); - RollEnumOptions.add("Channel6"); - RollEnumOptions.add("Channel7"); - RollEnumOptions.add("Channel8"); - RollEnumOptions.add("None"); - fields.add( new UAVObjectField("Roll", "channel", UAVObjectField.FieldType.ENUM, RollElemNames, RollEnumOptions) ); + List ChannelNeutralElemNames = new ArrayList(); + ChannelNeutralElemNames.add("Throttle"); + ChannelNeutralElemNames.add("Roll"); + ChannelNeutralElemNames.add("Pitch"); + ChannelNeutralElemNames.add("Yaw"); + ChannelNeutralElemNames.add("FlightMode"); + ChannelNeutralElemNames.add("Collective"); + ChannelNeutralElemNames.add("Accessory0"); + ChannelNeutralElemNames.add("Accessory1"); + ChannelNeutralElemNames.add("Accessory2"); + fields.add( new UAVObjectField("ChannelNeutral", "us", UAVObjectField.FieldType.INT16, ChannelNeutralElemNames, null) ); - List PitchElemNames = new ArrayList(); - PitchElemNames.add("0"); - List PitchEnumOptions = new ArrayList(); - PitchEnumOptions.add("Channel1"); - PitchEnumOptions.add("Channel2"); - PitchEnumOptions.add("Channel3"); - PitchEnumOptions.add("Channel4"); - PitchEnumOptions.add("Channel5"); - PitchEnumOptions.add("Channel6"); - PitchEnumOptions.add("Channel7"); - PitchEnumOptions.add("Channel8"); - PitchEnumOptions.add("None"); - fields.add( new UAVObjectField("Pitch", "channel", UAVObjectField.FieldType.ENUM, PitchElemNames, PitchEnumOptions) ); + List ChannelMaxElemNames = new ArrayList(); + ChannelMaxElemNames.add("Throttle"); + ChannelMaxElemNames.add("Roll"); + ChannelMaxElemNames.add("Pitch"); + ChannelMaxElemNames.add("Yaw"); + ChannelMaxElemNames.add("FlightMode"); + ChannelMaxElemNames.add("Collective"); + ChannelMaxElemNames.add("Accessory0"); + ChannelMaxElemNames.add("Accessory1"); + ChannelMaxElemNames.add("Accessory2"); + fields.add( new UAVObjectField("ChannelMax", "us", UAVObjectField.FieldType.INT16, ChannelMaxElemNames, null) ); - List YawElemNames = new ArrayList(); - YawElemNames.add("0"); - List YawEnumOptions = new ArrayList(); - YawEnumOptions.add("Channel1"); - YawEnumOptions.add("Channel2"); - YawEnumOptions.add("Channel3"); - YawEnumOptions.add("Channel4"); - YawEnumOptions.add("Channel5"); - YawEnumOptions.add("Channel6"); - YawEnumOptions.add("Channel7"); - YawEnumOptions.add("Channel8"); - YawEnumOptions.add("None"); - fields.add( new UAVObjectField("Yaw", "channel", UAVObjectField.FieldType.ENUM, YawElemNames, YawEnumOptions) ); + List ArmedTimeoutElemNames = new ArrayList(); + ArmedTimeoutElemNames.add("0"); + fields.add( new UAVObjectField("ArmedTimeout", "ms", UAVObjectField.FieldType.UINT16, ArmedTimeoutElemNames, null) ); - List ThrottleElemNames = new ArrayList(); - ThrottleElemNames.add("0"); - List ThrottleEnumOptions = new ArrayList(); - ThrottleEnumOptions.add("Channel1"); - ThrottleEnumOptions.add("Channel2"); - ThrottleEnumOptions.add("Channel3"); - ThrottleEnumOptions.add("Channel4"); - ThrottleEnumOptions.add("Channel5"); - ThrottleEnumOptions.add("Channel6"); - ThrottleEnumOptions.add("Channel7"); - ThrottleEnumOptions.add("Channel8"); - ThrottleEnumOptions.add("None"); - fields.add( new UAVObjectField("Throttle", "channel", UAVObjectField.FieldType.ENUM, ThrottleElemNames, ThrottleEnumOptions) ); + List ChannelGroupsElemNames = new ArrayList(); + ChannelGroupsElemNames.add("Throttle"); + ChannelGroupsElemNames.add("Roll"); + ChannelGroupsElemNames.add("Pitch"); + ChannelGroupsElemNames.add("Yaw"); + ChannelGroupsElemNames.add("FlightMode"); + ChannelGroupsElemNames.add("Collective"); + ChannelGroupsElemNames.add("Accessory0"); + ChannelGroupsElemNames.add("Accessory1"); + ChannelGroupsElemNames.add("Accessory2"); + List ChannelGroupsEnumOptions = new ArrayList(); + ChannelGroupsEnumOptions.add("PWM"); + ChannelGroupsEnumOptions.add("PPM"); + ChannelGroupsEnumOptions.add("DSM (MainPort)"); + ChannelGroupsEnumOptions.add("DSM (FlexiPort)"); + ChannelGroupsEnumOptions.add("S.Bus"); + ChannelGroupsEnumOptions.add("GCS"); + ChannelGroupsEnumOptions.add("None"); + fields.add( new UAVObjectField("ChannelGroups", "Channel Group", UAVObjectField.FieldType.ENUM, ChannelGroupsElemNames, ChannelGroupsEnumOptions) ); - List FlightModeElemNames = new ArrayList(); - FlightModeElemNames.add("0"); - List FlightModeEnumOptions = new ArrayList(); - FlightModeEnumOptions.add("Channel1"); - FlightModeEnumOptions.add("Channel2"); - FlightModeEnumOptions.add("Channel3"); - FlightModeEnumOptions.add("Channel4"); - FlightModeEnumOptions.add("Channel5"); - FlightModeEnumOptions.add("Channel6"); - FlightModeEnumOptions.add("Channel7"); - FlightModeEnumOptions.add("Channel8"); - FlightModeEnumOptions.add("None"); - fields.add( new UAVObjectField("FlightMode", "channel", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); - - List Accessory1ElemNames = new ArrayList(); - Accessory1ElemNames.add("0"); - List Accessory1EnumOptions = new ArrayList(); - Accessory1EnumOptions.add("Channel1"); - Accessory1EnumOptions.add("Channel2"); - Accessory1EnumOptions.add("Channel3"); - Accessory1EnumOptions.add("Channel4"); - Accessory1EnumOptions.add("Channel5"); - Accessory1EnumOptions.add("Channel6"); - Accessory1EnumOptions.add("Channel7"); - Accessory1EnumOptions.add("Channel8"); - Accessory1EnumOptions.add("None"); - fields.add( new UAVObjectField("Accessory1", "channel", UAVObjectField.FieldType.ENUM, Accessory1ElemNames, Accessory1EnumOptions) ); - - List Accessory2ElemNames = new ArrayList(); - Accessory2ElemNames.add("0"); - List Accessory2EnumOptions = new ArrayList(); - Accessory2EnumOptions.add("Channel1"); - Accessory2EnumOptions.add("Channel2"); - Accessory2EnumOptions.add("Channel3"); - Accessory2EnumOptions.add("Channel4"); - Accessory2EnumOptions.add("Channel5"); - Accessory2EnumOptions.add("Channel6"); - Accessory2EnumOptions.add("Channel7"); - Accessory2EnumOptions.add("Channel8"); - Accessory2EnumOptions.add("None"); - fields.add( new UAVObjectField("Accessory2", "channel", UAVObjectField.FieldType.ENUM, Accessory2ElemNames, Accessory2EnumOptions) ); - - List Accessory3ElemNames = new ArrayList(); - Accessory3ElemNames.add("0"); - List Accessory3EnumOptions = new ArrayList(); - Accessory3EnumOptions.add("Channel1"); - Accessory3EnumOptions.add("Channel2"); - Accessory3EnumOptions.add("Channel3"); - Accessory3EnumOptions.add("Channel4"); - Accessory3EnumOptions.add("Channel5"); - Accessory3EnumOptions.add("Channel6"); - Accessory3EnumOptions.add("Channel7"); - Accessory3EnumOptions.add("Channel8"); - Accessory3EnumOptions.add("None"); - fields.add( new UAVObjectField("Accessory3", "channel", UAVObjectField.FieldType.ENUM, Accessory3ElemNames, Accessory3EnumOptions) ); + List ChannelNumberElemNames = new ArrayList(); + ChannelNumberElemNames.add("Throttle"); + ChannelNumberElemNames.add("Roll"); + ChannelNumberElemNames.add("Pitch"); + ChannelNumberElemNames.add("Yaw"); + ChannelNumberElemNames.add("FlightMode"); + ChannelNumberElemNames.add("Collective"); + ChannelNumberElemNames.add("Accessory0"); + ChannelNumberElemNames.add("Accessory1"); + ChannelNumberElemNames.add("Accessory2"); + fields.add( new UAVObjectField("ChannelNumber", "channel", UAVObjectField.FieldType.UINT8, ChannelNumberElemNames, null) ); List ArmingElemNames = new ArrayList(); ArmingElemNames.add("0"); @@ -192,6 +144,8 @@ public class ManualControlSettings extends UAVDataObject { Stabilization1SettingsEnumOptions.add("None"); Stabilization1SettingsEnumOptions.add("Rate"); Stabilization1SettingsEnumOptions.add("Attitude"); + Stabilization1SettingsEnumOptions.add("AxisLock"); + Stabilization1SettingsEnumOptions.add("WeakLeveling"); fields.add( new UAVObjectField("Stabilization1Settings", "", UAVObjectField.FieldType.ENUM, Stabilization1SettingsElemNames, Stabilization1SettingsEnumOptions) ); List Stabilization2SettingsElemNames = new ArrayList(); @@ -202,6 +156,8 @@ public class ManualControlSettings extends UAVDataObject { Stabilization2SettingsEnumOptions.add("None"); Stabilization2SettingsEnumOptions.add("Rate"); Stabilization2SettingsEnumOptions.add("Attitude"); + Stabilization2SettingsEnumOptions.add("AxisLock"); + Stabilization2SettingsEnumOptions.add("WeakLeveling"); fields.add( new UAVObjectField("Stabilization2Settings", "", UAVObjectField.FieldType.ENUM, Stabilization2SettingsElemNames, Stabilization2SettingsEnumOptions) ); List Stabilization3SettingsElemNames = new ArrayList(); @@ -212,6 +168,8 @@ public class ManualControlSettings extends UAVDataObject { Stabilization3SettingsEnumOptions.add("None"); Stabilization3SettingsEnumOptions.add("Rate"); Stabilization3SettingsEnumOptions.add("Attitude"); + Stabilization3SettingsEnumOptions.add("AxisLock"); + Stabilization3SettingsEnumOptions.add("WeakLeveling"); fields.add( new UAVObjectField("Stabilization3Settings", "", UAVObjectField.FieldType.ENUM, Stabilization3SettingsElemNames, Stabilization3SettingsEnumOptions) ); List FlightModePositionElemNames = new ArrayList(); @@ -227,43 +185,6 @@ public class ManualControlSettings extends UAVDataObject { FlightModePositionEnumOptions.add("PositionHold"); fields.add( new UAVObjectField("FlightModePosition", "", UAVObjectField.FieldType.ENUM, FlightModePositionElemNames, FlightModePositionEnumOptions) ); - List ChannelMaxElemNames = new ArrayList(); - ChannelMaxElemNames.add("0"); - ChannelMaxElemNames.add("1"); - ChannelMaxElemNames.add("2"); - ChannelMaxElemNames.add("3"); - ChannelMaxElemNames.add("4"); - ChannelMaxElemNames.add("5"); - ChannelMaxElemNames.add("6"); - ChannelMaxElemNames.add("7"); - fields.add( new UAVObjectField("ChannelMax", "us", UAVObjectField.FieldType.INT16, ChannelMaxElemNames, null) ); - - List ChannelNeutralElemNames = new ArrayList(); - ChannelNeutralElemNames.add("0"); - ChannelNeutralElemNames.add("1"); - ChannelNeutralElemNames.add("2"); - ChannelNeutralElemNames.add("3"); - ChannelNeutralElemNames.add("4"); - ChannelNeutralElemNames.add("5"); - ChannelNeutralElemNames.add("6"); - ChannelNeutralElemNames.add("7"); - fields.add( new UAVObjectField("ChannelNeutral", "us", UAVObjectField.FieldType.INT16, ChannelNeutralElemNames, null) ); - - List ChannelMinElemNames = new ArrayList(); - ChannelMinElemNames.add("0"); - ChannelMinElemNames.add("1"); - ChannelMinElemNames.add("2"); - ChannelMinElemNames.add("3"); - ChannelMinElemNames.add("4"); - ChannelMinElemNames.add("5"); - ChannelMinElemNames.add("6"); - ChannelMinElemNames.add("7"); - fields.add( new UAVObjectField("ChannelMin", "us", UAVObjectField.FieldType.INT16, ChannelMinElemNames, null) ); - - List ArmedTimeoutElemNames = new ArrayList(); - ArmedTimeoutElemNames.add("0"); - fields.add( new UAVObjectField("ArmedTimeout", "ms", UAVObjectField.FieldType.UINT16, ArmedTimeoutElemNames, null) ); - // Compute the number of bytes for this object int numBytes = 0; @@ -309,44 +230,6 @@ public class ManualControlSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("InputMode").setValue("PWM"); - getField("Roll").setValue("Channel1"); - getField("Pitch").setValue("Channel2"); - getField("Yaw").setValue("Channel3"); - getField("Throttle").setValue("Channel4"); - getField("FlightMode").setValue("Channel5"); - getField("Accessory1").setValue("None"); - getField("Accessory2").setValue("None"); - getField("Accessory3").setValue("None"); - getField("Arming").setValue("Always Disarmed"); - getField("Stabilization1Settings").setValue("Attitude",0); - getField("Stabilization1Settings").setValue("Attitude",1); - getField("Stabilization1Settings").setValue("Attitude",2); - getField("Stabilization2Settings").setValue("Attitude",0); - getField("Stabilization2Settings").setValue("Attitude",1); - getField("Stabilization2Settings").setValue("Attitude",2); - getField("Stabilization3Settings").setValue("Attitude",0); - getField("Stabilization3Settings").setValue("Attitude",1); - getField("Stabilization3Settings").setValue("Attitude",2); - getField("FlightModePosition").setValue("Manual",0); - getField("FlightModePosition").setValue("Manual",1); - getField("FlightModePosition").setValue("Manual",2); - getField("ChannelMax").setValue(2000,0); - getField("ChannelMax").setValue(2000,1); - getField("ChannelMax").setValue(2000,2); - getField("ChannelMax").setValue(2000,3); - getField("ChannelMax").setValue(2000,4); - getField("ChannelMax").setValue(2000,5); - getField("ChannelMax").setValue(2000,6); - getField("ChannelMax").setValue(2000,7); - getField("ChannelNeutral").setValue(1500,0); - getField("ChannelNeutral").setValue(1500,1); - getField("ChannelNeutral").setValue(1500,2); - getField("ChannelNeutral").setValue(1500,3); - getField("ChannelNeutral").setValue(1500,4); - getField("ChannelNeutral").setValue(1500,5); - getField("ChannelNeutral").setValue(1500,6); - getField("ChannelNeutral").setValue(1500,7); getField("ChannelMin").setValue(1000,0); getField("ChannelMin").setValue(1000,1); getField("ChannelMin").setValue(1000,2); @@ -355,7 +238,57 @@ public class ManualControlSettings extends UAVDataObject { getField("ChannelMin").setValue(1000,5); getField("ChannelMin").setValue(1000,6); getField("ChannelMin").setValue(1000,7); + getField("ChannelMin").setValue(1000,8); + getField("ChannelNeutral").setValue(1500,0); + getField("ChannelNeutral").setValue(1500,1); + getField("ChannelNeutral").setValue(1500,2); + getField("ChannelNeutral").setValue(1500,3); + getField("ChannelNeutral").setValue(1500,4); + getField("ChannelNeutral").setValue(1500,5); + getField("ChannelNeutral").setValue(1500,6); + getField("ChannelNeutral").setValue(1500,7); + getField("ChannelNeutral").setValue(1500,8); + getField("ChannelMax").setValue(2000,0); + getField("ChannelMax").setValue(2000,1); + getField("ChannelMax").setValue(2000,2); + getField("ChannelMax").setValue(2000,3); + getField("ChannelMax").setValue(2000,4); + getField("ChannelMax").setValue(2000,5); + getField("ChannelMax").setValue(2000,6); + getField("ChannelMax").setValue(2000,7); + getField("ChannelMax").setValue(2000,8); getField("ArmedTimeout").setValue(30000); + getField("ChannelGroups").setValue("None",0); + getField("ChannelGroups").setValue("None",1); + getField("ChannelGroups").setValue("None",2); + getField("ChannelGroups").setValue("None",3); + getField("ChannelGroups").setValue("None",4); + getField("ChannelGroups").setValue("None",5); + getField("ChannelGroups").setValue("None",6); + getField("ChannelGroups").setValue("None",7); + getField("ChannelGroups").setValue("None",8); + getField("ChannelNumber").setValue(0,0); + getField("ChannelNumber").setValue(0,1); + getField("ChannelNumber").setValue(0,2); + getField("ChannelNumber").setValue(0,3); + getField("ChannelNumber").setValue(0,4); + getField("ChannelNumber").setValue(0,5); + getField("ChannelNumber").setValue(0,6); + getField("ChannelNumber").setValue(0,7); + getField("ChannelNumber").setValue(0,8); + getField("Arming").setValue("Always Disarmed"); + getField("Stabilization1Settings").setValue("Attitude",0); + getField("Stabilization1Settings").setValue("Attitude",1); + getField("Stabilization1Settings").setValue("Rate",2); + getField("Stabilization2Settings").setValue("Attitude",0); + getField("Stabilization2Settings").setValue("Attitude",1); + getField("Stabilization2Settings").setValue("Rate",2); + getField("Stabilization3Settings").setValue("Attitude",0); + getField("Stabilization3Settings").setValue("Attitude",1); + getField("Stabilization3Settings").setValue("Rate",2); + getField("FlightModePosition").setValue("Manual",0); + getField("FlightModePosition").setValue("Stabilized1",1); + getField("FlightModePosition").setValue("Stabilized2",2); } @@ -384,7 +317,7 @@ public class ManualControlSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x2B82102; + protected static final int OBJID = 0x24959BB0; protected static final String NAME = "ManualControlSettings"; protected static String DESCRIPTION = "Settings to indicate how to decode receiver input by @ref ManualControlModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java index 9aa87d49e..76841d8ff 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java @@ -83,12 +83,37 @@ public class MixerSettings extends UAVDataObject { ThrottleCurve2ElemNames.add("100"); fields.add( new UAVObjectField("ThrottleCurve2", "percent", UAVObjectField.FieldType.FLOAT32, ThrottleCurve2ElemNames, null) ); + List Curve2SourceElemNames = new ArrayList(); + Curve2SourceElemNames.add("0"); + List Curve2SourceEnumOptions = new ArrayList(); + Curve2SourceEnumOptions.add("Throttle"); + Curve2SourceEnumOptions.add("Roll"); + Curve2SourceEnumOptions.add("Pitch"); + Curve2SourceEnumOptions.add("Yaw"); + Curve2SourceEnumOptions.add("Collective"); + Curve2SourceEnumOptions.add("Accessory0"); + Curve2SourceEnumOptions.add("Accessory1"); + Curve2SourceEnumOptions.add("Accessory2"); + Curve2SourceEnumOptions.add("Accessory3"); + Curve2SourceEnumOptions.add("Accessory4"); + Curve2SourceEnumOptions.add("Accessory5"); + fields.add( new UAVObjectField("Curve2Source", "", UAVObjectField.FieldType.ENUM, Curve2SourceElemNames, Curve2SourceEnumOptions) ); + List Mixer1TypeElemNames = new ArrayList(); Mixer1TypeElemNames.add("0"); List Mixer1TypeEnumOptions = new ArrayList(); Mixer1TypeEnumOptions.add("Disabled"); Mixer1TypeEnumOptions.add("Motor"); Mixer1TypeEnumOptions.add("Servo"); + Mixer1TypeEnumOptions.add("CameraRoll"); + Mixer1TypeEnumOptions.add("CameraPitch"); + Mixer1TypeEnumOptions.add("CameraYaw"); + Mixer1TypeEnumOptions.add("Accessory0"); + Mixer1TypeEnumOptions.add("Accessory1"); + Mixer1TypeEnumOptions.add("Accessory2"); + Mixer1TypeEnumOptions.add("Accessory3"); + Mixer1TypeEnumOptions.add("Accessory4"); + Mixer1TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer1Type", "", UAVObjectField.FieldType.ENUM, Mixer1TypeElemNames, Mixer1TypeEnumOptions) ); List Mixer1VectorElemNames = new ArrayList(); @@ -105,6 +130,15 @@ public class MixerSettings extends UAVDataObject { Mixer2TypeEnumOptions.add("Disabled"); Mixer2TypeEnumOptions.add("Motor"); Mixer2TypeEnumOptions.add("Servo"); + Mixer2TypeEnumOptions.add("CameraRoll"); + Mixer2TypeEnumOptions.add("CameraPitch"); + Mixer2TypeEnumOptions.add("CameraYaw"); + Mixer2TypeEnumOptions.add("Accessory0"); + Mixer2TypeEnumOptions.add("Accessory1"); + Mixer2TypeEnumOptions.add("Accessory2"); + Mixer2TypeEnumOptions.add("Accessory3"); + Mixer2TypeEnumOptions.add("Accessory4"); + Mixer2TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer2Type", "", UAVObjectField.FieldType.ENUM, Mixer2TypeElemNames, Mixer2TypeEnumOptions) ); List Mixer2VectorElemNames = new ArrayList(); @@ -121,6 +155,15 @@ public class MixerSettings extends UAVDataObject { Mixer3TypeEnumOptions.add("Disabled"); Mixer3TypeEnumOptions.add("Motor"); Mixer3TypeEnumOptions.add("Servo"); + Mixer3TypeEnumOptions.add("CameraRoll"); + Mixer3TypeEnumOptions.add("CameraPitch"); + Mixer3TypeEnumOptions.add("CameraYaw"); + Mixer3TypeEnumOptions.add("Accessory0"); + Mixer3TypeEnumOptions.add("Accessory1"); + Mixer3TypeEnumOptions.add("Accessory2"); + Mixer3TypeEnumOptions.add("Accessory3"); + Mixer3TypeEnumOptions.add("Accessory4"); + Mixer3TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer3Type", "", UAVObjectField.FieldType.ENUM, Mixer3TypeElemNames, Mixer3TypeEnumOptions) ); List Mixer3VectorElemNames = new ArrayList(); @@ -137,6 +180,15 @@ public class MixerSettings extends UAVDataObject { Mixer4TypeEnumOptions.add("Disabled"); Mixer4TypeEnumOptions.add("Motor"); Mixer4TypeEnumOptions.add("Servo"); + Mixer4TypeEnumOptions.add("CameraRoll"); + Mixer4TypeEnumOptions.add("CameraPitch"); + Mixer4TypeEnumOptions.add("CameraYaw"); + Mixer4TypeEnumOptions.add("Accessory0"); + Mixer4TypeEnumOptions.add("Accessory1"); + Mixer4TypeEnumOptions.add("Accessory2"); + Mixer4TypeEnumOptions.add("Accessory3"); + Mixer4TypeEnumOptions.add("Accessory4"); + Mixer4TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer4Type", "", UAVObjectField.FieldType.ENUM, Mixer4TypeElemNames, Mixer4TypeEnumOptions) ); List Mixer4VectorElemNames = new ArrayList(); @@ -153,6 +205,15 @@ public class MixerSettings extends UAVDataObject { Mixer5TypeEnumOptions.add("Disabled"); Mixer5TypeEnumOptions.add("Motor"); Mixer5TypeEnumOptions.add("Servo"); + Mixer5TypeEnumOptions.add("CameraRoll"); + Mixer5TypeEnumOptions.add("CameraPitch"); + Mixer5TypeEnumOptions.add("CameraYaw"); + Mixer5TypeEnumOptions.add("Accessory0"); + Mixer5TypeEnumOptions.add("Accessory1"); + Mixer5TypeEnumOptions.add("Accessory2"); + Mixer5TypeEnumOptions.add("Accessory3"); + Mixer5TypeEnumOptions.add("Accessory4"); + Mixer5TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer5Type", "", UAVObjectField.FieldType.ENUM, Mixer5TypeElemNames, Mixer5TypeEnumOptions) ); List Mixer5VectorElemNames = new ArrayList(); @@ -169,6 +230,15 @@ public class MixerSettings extends UAVDataObject { Mixer6TypeEnumOptions.add("Disabled"); Mixer6TypeEnumOptions.add("Motor"); Mixer6TypeEnumOptions.add("Servo"); + Mixer6TypeEnumOptions.add("CameraRoll"); + Mixer6TypeEnumOptions.add("CameraPitch"); + Mixer6TypeEnumOptions.add("CameraYaw"); + Mixer6TypeEnumOptions.add("Accessory0"); + Mixer6TypeEnumOptions.add("Accessory1"); + Mixer6TypeEnumOptions.add("Accessory2"); + Mixer6TypeEnumOptions.add("Accessory3"); + Mixer6TypeEnumOptions.add("Accessory4"); + Mixer6TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer6Type", "", UAVObjectField.FieldType.ENUM, Mixer6TypeElemNames, Mixer6TypeEnumOptions) ); List Mixer6VectorElemNames = new ArrayList(); @@ -185,6 +255,15 @@ public class MixerSettings extends UAVDataObject { Mixer7TypeEnumOptions.add("Disabled"); Mixer7TypeEnumOptions.add("Motor"); Mixer7TypeEnumOptions.add("Servo"); + Mixer7TypeEnumOptions.add("CameraRoll"); + Mixer7TypeEnumOptions.add("CameraPitch"); + Mixer7TypeEnumOptions.add("CameraYaw"); + Mixer7TypeEnumOptions.add("Accessory0"); + Mixer7TypeEnumOptions.add("Accessory1"); + Mixer7TypeEnumOptions.add("Accessory2"); + Mixer7TypeEnumOptions.add("Accessory3"); + Mixer7TypeEnumOptions.add("Accessory4"); + Mixer7TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer7Type", "", UAVObjectField.FieldType.ENUM, Mixer7TypeElemNames, Mixer7TypeEnumOptions) ); List Mixer7VectorElemNames = new ArrayList(); @@ -201,6 +280,15 @@ public class MixerSettings extends UAVDataObject { Mixer8TypeEnumOptions.add("Disabled"); Mixer8TypeEnumOptions.add("Motor"); Mixer8TypeEnumOptions.add("Servo"); + Mixer8TypeEnumOptions.add("CameraRoll"); + Mixer8TypeEnumOptions.add("CameraPitch"); + Mixer8TypeEnumOptions.add("CameraYaw"); + Mixer8TypeEnumOptions.add("Accessory0"); + Mixer8TypeEnumOptions.add("Accessory1"); + Mixer8TypeEnumOptions.add("Accessory2"); + Mixer8TypeEnumOptions.add("Accessory3"); + Mixer8TypeEnumOptions.add("Accessory4"); + Mixer8TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer8Type", "", UAVObjectField.FieldType.ENUM, Mixer8TypeElemNames, Mixer8TypeEnumOptions) ); List Mixer8VectorElemNames = new ArrayList(); @@ -211,6 +299,56 @@ public class MixerSettings extends UAVDataObject { Mixer8VectorElemNames.add("Yaw"); fields.add( new UAVObjectField("Mixer8Vector", "", UAVObjectField.FieldType.INT8, Mixer8VectorElemNames, null) ); + List Mixer9TypeElemNames = new ArrayList(); + Mixer9TypeElemNames.add("0"); + List Mixer9TypeEnumOptions = new ArrayList(); + Mixer9TypeEnumOptions.add("Disabled"); + Mixer9TypeEnumOptions.add("Motor"); + Mixer9TypeEnumOptions.add("Servo"); + Mixer9TypeEnumOptions.add("CameraRoll"); + Mixer9TypeEnumOptions.add("CameraPitch"); + Mixer9TypeEnumOptions.add("CameraYaw"); + Mixer9TypeEnumOptions.add("Accessory0"); + Mixer9TypeEnumOptions.add("Accessory1"); + Mixer9TypeEnumOptions.add("Accessory2"); + Mixer9TypeEnumOptions.add("Accessory3"); + Mixer9TypeEnumOptions.add("Accessory4"); + Mixer9TypeEnumOptions.add("Accessory5"); + fields.add( new UAVObjectField("Mixer9Type", "", UAVObjectField.FieldType.ENUM, Mixer9TypeElemNames, Mixer9TypeEnumOptions) ); + + List Mixer9VectorElemNames = new ArrayList(); + Mixer9VectorElemNames.add("ThrottleCurve1"); + Mixer9VectorElemNames.add("ThrottleCurve2"); + Mixer9VectorElemNames.add("Roll"); + Mixer9VectorElemNames.add("Pitch"); + Mixer9VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer9Vector", "", UAVObjectField.FieldType.INT8, Mixer9VectorElemNames, null) ); + + List Mixer10TypeElemNames = new ArrayList(); + Mixer10TypeElemNames.add("0"); + List Mixer10TypeEnumOptions = new ArrayList(); + Mixer10TypeEnumOptions.add("Disabled"); + Mixer10TypeEnumOptions.add("Motor"); + Mixer10TypeEnumOptions.add("Servo"); + Mixer10TypeEnumOptions.add("CameraRoll"); + Mixer10TypeEnumOptions.add("CameraPitch"); + Mixer10TypeEnumOptions.add("CameraYaw"); + Mixer10TypeEnumOptions.add("Accessory0"); + Mixer10TypeEnumOptions.add("Accessory1"); + Mixer10TypeEnumOptions.add("Accessory2"); + Mixer10TypeEnumOptions.add("Accessory3"); + Mixer10TypeEnumOptions.add("Accessory4"); + Mixer10TypeEnumOptions.add("Accessory5"); + fields.add( new UAVObjectField("Mixer10Type", "", UAVObjectField.FieldType.ENUM, Mixer10TypeElemNames, Mixer10TypeEnumOptions) ); + + List Mixer10VectorElemNames = new ArrayList(); + Mixer10VectorElemNames.add("ThrottleCurve1"); + Mixer10VectorElemNames.add("ThrottleCurve2"); + Mixer10VectorElemNames.add("Roll"); + Mixer10VectorElemNames.add("Pitch"); + Mixer10VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer10Vector", "", UAVObjectField.FieldType.INT8, Mixer10VectorElemNames, null) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -261,15 +399,16 @@ public class MixerSettings extends UAVDataObject { getField("AccelTime").setValue(0); getField("DecelTime").setValue(0); getField("ThrottleCurve1").setValue(0,0); - getField("ThrottleCurve1").setValue(0.25,1); - getField("ThrottleCurve1").setValue(0.5,2); - getField("ThrottleCurve1").setValue(0.75,3); - getField("ThrottleCurve1").setValue(1,4); + getField("ThrottleCurve1").setValue(0,1); + getField("ThrottleCurve1").setValue(0,2); + getField("ThrottleCurve1").setValue(0,3); + getField("ThrottleCurve1").setValue(0,4); getField("ThrottleCurve2").setValue(0,0); getField("ThrottleCurve2").setValue(0.25,1); getField("ThrottleCurve2").setValue(0.5,2); getField("ThrottleCurve2").setValue(0.75,3); getField("ThrottleCurve2").setValue(1,4); + getField("Curve2Source").setValue("Throttle"); getField("Mixer1Type").setValue("Disabled"); getField("Mixer1Vector").setValue(0,0); getField("Mixer1Vector").setValue(0,1); @@ -318,6 +457,18 @@ public class MixerSettings extends UAVDataObject { getField("Mixer8Vector").setValue(0,2); getField("Mixer8Vector").setValue(0,3); getField("Mixer8Vector").setValue(0,4); + getField("Mixer9Type").setValue("Disabled"); + getField("Mixer9Vector").setValue(0,0); + getField("Mixer9Vector").setValue(0,1); + getField("Mixer9Vector").setValue(0,2); + getField("Mixer9Vector").setValue(0,3); + getField("Mixer9Vector").setValue(0,4); + getField("Mixer10Type").setValue("Disabled"); + getField("Mixer10Vector").setValue(0,0); + getField("Mixer10Vector").setValue(0,1); + getField("Mixer10Vector").setValue(0,2); + getField("Mixer10Vector").setValue(0,3); + getField("Mixer10Vector").setValue(0,4); } @@ -346,7 +497,7 @@ public class MixerSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x4FAE374E; + protected static final int OBJID = 0x5D16D6C4; protected static final String NAME = "MixerSettings"; protected static String DESCRIPTION = "Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java index fbd405b40..106220a8c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java @@ -156,7 +156,7 @@ public class MixerStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0xF6A33F10; + protected static final int OBJID = 0x11CFB4E6; protected static final String NAME = "MixerStatus"; protected static String DESCRIPTION = "Status for the matrix mixer showing the output of each mixer after all scaling"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java index f16ddd199..3b09dd1f8 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java @@ -136,7 +136,7 @@ public class NedAccel extends UAVDataObject { } // Constants - protected static final int OBJID = 0x8E852CE8; + protected static final int OBJID = 0x7C7F5BC0; protected static final String NAME = "NedAccel"; protected static String DESCRIPTION = "The projection of acceleration in the NED reference frame used by @ref Guidance."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java index 2a09c2b40..dccd85d36 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java @@ -51,12 +51,23 @@ public class ObjectPersistence extends UAVDataObject { List fields = new ArrayList(); + List ObjectIDElemNames = new ArrayList(); + ObjectIDElemNames.add("0"); + fields.add( new UAVObjectField("ObjectID", "", UAVObjectField.FieldType.UINT32, ObjectIDElemNames, null) ); + + List InstanceIDElemNames = new ArrayList(); + InstanceIDElemNames.add("0"); + fields.add( new UAVObjectField("InstanceID", "", UAVObjectField.FieldType.UINT32, InstanceIDElemNames, null) ); + List OperationElemNames = new ArrayList(); OperationElemNames.add("0"); List OperationEnumOptions = new ArrayList(); + OperationEnumOptions.add("NOP"); OperationEnumOptions.add("Load"); OperationEnumOptions.add("Save"); OperationEnumOptions.add("Delete"); + OperationEnumOptions.add("FullErase"); + OperationEnumOptions.add("Completed"); fields.add( new UAVObjectField("Operation", "", UAVObjectField.FieldType.ENUM, OperationElemNames, OperationEnumOptions) ); List SelectionElemNames = new ArrayList(); @@ -68,14 +79,6 @@ public class ObjectPersistence extends UAVDataObject { SelectionEnumOptions.add("AllObjects"); fields.add( new UAVObjectField("Selection", "", UAVObjectField.FieldType.ENUM, SelectionElemNames, SelectionEnumOptions) ); - List ObjectIDElemNames = new ArrayList(); - ObjectIDElemNames.add("0"); - fields.add( new UAVObjectField("ObjectID", "", UAVObjectField.FieldType.UINT32, ObjectIDElemNames, null) ); - - List InstanceIDElemNames = new ArrayList(); - InstanceIDElemNames.add("0"); - fields.add( new UAVObjectField("InstanceID", "", UAVObjectField.FieldType.UINT32, InstanceIDElemNames, null) ); - // Compute the number of bytes for this object int numBytes = 0; @@ -106,7 +109,7 @@ public class ObjectPersistence extends UAVDataObject { metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; metadata.flightTelemetryUpdatePeriod = 0; metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; @@ -149,7 +152,7 @@ public class ObjectPersistence extends UAVDataObject { } // Constants - protected static final int OBJID = 0x22216832; + protected static final int OBJID = 0xF69AD8B8; protected static final String NAME = "ObjectPersistence"; protected static String DESCRIPTION = "Someone who knows please enter this"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java index 444009f90..ac30ad4f5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java @@ -136,7 +136,7 @@ public class PositionActual extends UAVDataObject { } // Constants - protected static final int OBJID = 0xE0739636; + protected static final int OBJID = 0xF9691DA4; protected static final String NAME = "PositionActual"; protected static String DESCRIPTION = "Contains the current position relative to @ref HomeLocation"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java index 5cf51df71..2ff5a5586 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java @@ -136,7 +136,7 @@ public class PositionDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0x2FC4E5BA; + protected static final int OBJID = 0x33C9EAB4; protected static final String NAME = "PositionDesired"; protected static String DESCRIPTION = "The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner "; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java index 7164c0957..ddeacd8d4 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java @@ -136,7 +136,7 @@ public class RateDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0xBA41B51C; + protected static final int OBJID = 0xCE8C826; protected static final String NAME = "RateDesired"; protected static String DESCRIPTION = "Status for the matrix mixer showing the output of each mixer after all scaling"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java similarity index 61% rename from androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java rename to androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java index 6af673930..a40b27e38 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java @@ -5,7 +5,7 @@ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief Template for an uavobject in java * This is a autogenerated file!! Do not modify and expect a result. - * Battery configuration information. + * Monitors which receiver channels have been active within the last second. * * @see The GNU Public License (GPL) Version 3 * @@ -39,40 +39,33 @@ import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObjectField; /** -Battery configuration information. +Monitors which receiver channels have been active within the last second. -generated from batterysettings.xml +generated from receiveractivity.xml **/ -public class BatterySettings extends UAVDataObject { +public class ReceiverActivity extends UAVDataObject { - public BatterySettings() { + public ReceiverActivity() { super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); List fields = new ArrayList(); - List BatteryVoltageElemNames = new ArrayList(); - BatteryVoltageElemNames.add("0"); - fields.add( new UAVObjectField("BatteryVoltage", "V", UAVObjectField.FieldType.FLOAT32, BatteryVoltageElemNames, null) ); + List ActiveGroupElemNames = new ArrayList(); + ActiveGroupElemNames.add("0"); + List ActiveGroupEnumOptions = new ArrayList(); + ActiveGroupEnumOptions.add("PWM"); + ActiveGroupEnumOptions.add("PPM"); + ActiveGroupEnumOptions.add("DSM (MainPort)"); + ActiveGroupEnumOptions.add("DSM (FlexiPort)"); + ActiveGroupEnumOptions.add("S.Bus"); + ActiveGroupEnumOptions.add("GCS"); + ActiveGroupEnumOptions.add("None"); + fields.add( new UAVObjectField("ActiveGroup", "Channel Group", UAVObjectField.FieldType.ENUM, ActiveGroupElemNames, ActiveGroupEnumOptions) ); - List BatteryCapacityElemNames = new ArrayList(); - BatteryCapacityElemNames.add("0"); - fields.add( new UAVObjectField("BatteryCapacity", "mAh", UAVObjectField.FieldType.UINT32, BatteryCapacityElemNames, null) ); - - List BatteryTypeElemNames = new ArrayList(); - BatteryTypeElemNames.add("0"); - List BatteryTypeEnumOptions = new ArrayList(); - BatteryTypeEnumOptions.add("LiPo"); - BatteryTypeEnumOptions.add("A123"); - BatteryTypeEnumOptions.add("LiCo"); - BatteryTypeEnumOptions.add("LiFeSO4"); - BatteryTypeEnumOptions.add("None"); - fields.add( new UAVObjectField("BatteryType", "", UAVObjectField.FieldType.ENUM, BatteryTypeElemNames, BatteryTypeEnumOptions) ); - - List CalibrationsElemNames = new ArrayList(); - CalibrationsElemNames.add("Voltage"); - CalibrationsElemNames.add("Current"); - fields.add( new UAVObjectField("Calibrations", "", UAVObjectField.FieldType.FLOAT32, CalibrationsElemNames, null) ); + List ActiveChannelElemNames = new ArrayList(); + ActiveChannelElemNames.add("0"); + fields.add( new UAVObjectField("ActiveChannel", "channel", UAVObjectField.FieldType.UINT8, ActiveChannelElemNames, null) ); // Compute the number of bytes for this object @@ -97,13 +90,13 @@ public class BatterySettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READONLY; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; metadata.gcsTelemetryUpdatePeriod = 0; metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; metadata.flightTelemetryUpdatePeriod = 0; @@ -119,11 +112,8 @@ public class BatterySettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("BatteryVoltage").setValue(11.1); - getField("BatteryCapacity").setValue(2200); - getField("BatteryType").setValue("LiPo"); - getField("Calibrations").setValue(1,0); - getField("Calibrations").setValue(1,1); + getField("ActiveGroup").setValue("None"); + getField("ActiveChannel").setValue(255); } @@ -135,7 +125,7 @@ public class BatterySettings extends UAVDataObject { public UAVDataObject clone(int instID) { // TODO: Need to get specific instance to clone try { - BatterySettings obj = new BatterySettings(); + ReceiverActivity obj = new ReceiverActivity(); obj.initialize(instID, this.getMetaObject()); return obj; } catch (Exception e) { @@ -146,17 +136,17 @@ public class BatterySettings extends UAVDataObject { /** * Static function to retrieve an instance of the object. */ - public BatterySettings GetInstance(UAVObjectManager objMngr, int instID) + public ReceiverActivity GetInstance(UAVObjectManager objMngr, int instID) { - return (BatterySettings)(objMngr.getObject(BatterySettings.OBJID, instID)); + return (ReceiverActivity)(objMngr.getObject(ReceiverActivity.OBJID, instID)); } // Constants - protected static final int OBJID = 0xA5FF1D9A; - protected static final String NAME = "BatterySettings"; - protected static String DESCRIPTION = "Battery configuration information."; + protected static final int OBJID = 0x1E7C53DA; + protected static final String NAME = "ReceiverActivity"; + protected static String DESCRIPTION = "Monitors which receiver channels have been active within the last second."; protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; protected static int NUMBYTES = 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java index 4e9f0b8b8..18cf6f4d6 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java @@ -128,7 +128,7 @@ public class SonarAltitude extends UAVDataObject { } // Constants - protected static final int OBJID = 0x1FDD844C; + protected static final int OBJID = 0x6C5A0CBC; protected static final String NAME = "SonarAltitude"; protected static String DESCRIPTION = "The raw data from the ultrasound sonar sensor with altitude estimate."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java index 8cba8a54c..32d2c735c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java @@ -75,6 +75,8 @@ public class StabilizationDesired extends UAVDataObject { StabilizationModeEnumOptions.add("None"); StabilizationModeEnumOptions.add("Rate"); StabilizationModeEnumOptions.add("Attitude"); + StabilizationModeEnumOptions.add("AxisLock"); + StabilizationModeEnumOptions.add("WeakLeveling"); fields.add( new UAVObjectField("StabilizationMode", "", UAVObjectField.FieldType.ENUM, StabilizationModeElemNames, StabilizationModeEnumOptions) ); @@ -150,7 +152,7 @@ public class StabilizationDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0x41AA9DC2; + protected static final int OBJID = 0xDB8FFC3C; protected static final String NAME = "StabilizationDesired"; protected static String DESCRIPTION = "The desired attitude that @ref StabilizationModule will try and achieve if FlightMode is Stabilized. Comes from @ref ManaulControlModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java index 74c480e1c..ab78bdc74 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java @@ -51,18 +51,6 @@ public class StabilizationSettings extends UAVDataObject { List fields = new ArrayList(); - List RollMaxElemNames = new ArrayList(); - RollMaxElemNames.add("0"); - fields.add( new UAVObjectField("RollMax", "degrees", UAVObjectField.FieldType.UINT8, RollMaxElemNames, null) ); - - List PitchMaxElemNames = new ArrayList(); - PitchMaxElemNames.add("0"); - fields.add( new UAVObjectField("PitchMax", "degrees", UAVObjectField.FieldType.UINT8, PitchMaxElemNames, null) ); - - List YawMaxElemNames = new ArrayList(); - YawMaxElemNames.add("0"); - fields.add( new UAVObjectField("YawMax", "degrees", UAVObjectField.FieldType.UINT8, YawMaxElemNames, null) ); - List ManualRateElemNames = new ArrayList(); ManualRateElemNames.add("Roll"); ManualRateElemNames.add("Pitch"); @@ -75,23 +63,26 @@ public class StabilizationSettings extends UAVDataObject { MaximumRateElemNames.add("Yaw"); fields.add( new UAVObjectField("MaximumRate", "degrees/sec", UAVObjectField.FieldType.FLOAT32, MaximumRateElemNames, null) ); - List RollRatePIElemNames = new ArrayList(); - RollRatePIElemNames.add("Kp"); - RollRatePIElemNames.add("Ki"); - RollRatePIElemNames.add("ILimit"); - fields.add( new UAVObjectField("RollRatePI", "", UAVObjectField.FieldType.FLOAT32, RollRatePIElemNames, null) ); + List RollRatePIDElemNames = new ArrayList(); + RollRatePIDElemNames.add("Kp"); + RollRatePIDElemNames.add("Ki"); + RollRatePIDElemNames.add("Kd"); + RollRatePIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("RollRatePID", "", UAVObjectField.FieldType.FLOAT32, RollRatePIDElemNames, null) ); - List PitchRatePIElemNames = new ArrayList(); - PitchRatePIElemNames.add("Kp"); - PitchRatePIElemNames.add("Ki"); - PitchRatePIElemNames.add("ILimit"); - fields.add( new UAVObjectField("PitchRatePI", "", UAVObjectField.FieldType.FLOAT32, PitchRatePIElemNames, null) ); + List PitchRatePIDElemNames = new ArrayList(); + PitchRatePIDElemNames.add("Kp"); + PitchRatePIDElemNames.add("Ki"); + PitchRatePIDElemNames.add("Kd"); + PitchRatePIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("PitchRatePID", "", UAVObjectField.FieldType.FLOAT32, PitchRatePIDElemNames, null) ); - List YawRatePIElemNames = new ArrayList(); - YawRatePIElemNames.add("Kp"); - YawRatePIElemNames.add("Ki"); - YawRatePIElemNames.add("ILimit"); - fields.add( new UAVObjectField("YawRatePI", "", UAVObjectField.FieldType.FLOAT32, YawRatePIElemNames, null) ); + List YawRatePIDElemNames = new ArrayList(); + YawRatePIDElemNames.add("Kp"); + YawRatePIDElemNames.add("Ki"); + YawRatePIDElemNames.add("Kd"); + YawRatePIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("YawRatePID", "", UAVObjectField.FieldType.FLOAT32, YawRatePIDElemNames, null) ); List RollPIElemNames = new ArrayList(); RollPIElemNames.add("Kp"); @@ -111,6 +102,45 @@ public class StabilizationSettings extends UAVDataObject { YawPIElemNames.add("ILimit"); fields.add( new UAVObjectField("YawPI", "", UAVObjectField.FieldType.FLOAT32, YawPIElemNames, null) ); + List GyroTauElemNames = new ArrayList(); + GyroTauElemNames.add("0"); + fields.add( new UAVObjectField("GyroTau", "", UAVObjectField.FieldType.FLOAT32, GyroTauElemNames, null) ); + + List WeakLevelingKpElemNames = new ArrayList(); + WeakLevelingKpElemNames.add("0"); + fields.add( new UAVObjectField("WeakLevelingKp", "(deg/s)/deg", UAVObjectField.FieldType.FLOAT32, WeakLevelingKpElemNames, null) ); + + List RollMaxElemNames = new ArrayList(); + RollMaxElemNames.add("0"); + fields.add( new UAVObjectField("RollMax", "degrees", UAVObjectField.FieldType.UINT8, RollMaxElemNames, null) ); + + List PitchMaxElemNames = new ArrayList(); + PitchMaxElemNames.add("0"); + fields.add( new UAVObjectField("PitchMax", "degrees", UAVObjectField.FieldType.UINT8, PitchMaxElemNames, null) ); + + List YawMaxElemNames = new ArrayList(); + YawMaxElemNames.add("0"); + fields.add( new UAVObjectField("YawMax", "degrees", UAVObjectField.FieldType.UINT8, YawMaxElemNames, null) ); + + List MaxAxisLockElemNames = new ArrayList(); + MaxAxisLockElemNames.add("0"); + fields.add( new UAVObjectField("MaxAxisLock", "deg", UAVObjectField.FieldType.UINT8, MaxAxisLockElemNames, null) ); + + List MaxAxisLockRateElemNames = new ArrayList(); + MaxAxisLockRateElemNames.add("0"); + fields.add( new UAVObjectField("MaxAxisLockRate", "deg/s", UAVObjectField.FieldType.UINT8, MaxAxisLockRateElemNames, null) ); + + List MaxWeakLevelingRateElemNames = new ArrayList(); + MaxWeakLevelingRateElemNames.add("0"); + fields.add( new UAVObjectField("MaxWeakLevelingRate", "deg/s", UAVObjectField.FieldType.UINT8, MaxWeakLevelingRateElemNames, null) ); + + List LowThrottleZeroIntegralElemNames = new ArrayList(); + LowThrottleZeroIntegralElemNames.add("0"); + List LowThrottleZeroIntegralEnumOptions = new ArrayList(); + LowThrottleZeroIntegralEnumOptions.add("FALSE"); + LowThrottleZeroIntegralEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("LowThrottleZeroIntegral", "", UAVObjectField.FieldType.ENUM, LowThrottleZeroIntegralElemNames, LowThrottleZeroIntegralEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -156,24 +186,24 @@ public class StabilizationSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("RollMax").setValue(35); - getField("PitchMax").setValue(35); - getField("YawMax").setValue(35); getField("ManualRate").setValue(150,0); getField("ManualRate").setValue(150,1); getField("ManualRate").setValue(150,2); getField("MaximumRate").setValue(300,0); getField("MaximumRate").setValue(300,1); getField("MaximumRate").setValue(300,2); - getField("RollRatePI").setValue(0.0015,0); - getField("RollRatePI").setValue(0,1); - getField("RollRatePI").setValue(0.3,2); - getField("PitchRatePI").setValue(0.0015,0); - getField("PitchRatePI").setValue(0,1); - getField("PitchRatePI").setValue(0.3,2); - getField("YawRatePI").setValue(0.003,0); - getField("YawRatePI").setValue(0,1); - getField("YawRatePI").setValue(0.3,2); + getField("RollRatePID").setValue(0.002,0); + getField("RollRatePID").setValue(0,1); + getField("RollRatePID").setValue(0,2); + getField("RollRatePID").setValue(0.3,3); + getField("PitchRatePID").setValue(0.002,0); + getField("PitchRatePID").setValue(0,1); + getField("PitchRatePID").setValue(0,2); + getField("PitchRatePID").setValue(0.3,3); + getField("YawRatePID").setValue(0.0035,0); + getField("YawRatePID").setValue(0.0035,1); + getField("YawRatePID").setValue(0,2); + getField("YawRatePID").setValue(0.3,3); getField("RollPI").setValue(2,0); getField("RollPI").setValue(0,1); getField("RollPI").setValue(50,2); @@ -183,6 +213,15 @@ public class StabilizationSettings extends UAVDataObject { getField("YawPI").setValue(2,0); getField("YawPI").setValue(0,1); getField("YawPI").setValue(50,2); + getField("GyroTau").setValue(0.005); + getField("WeakLevelingKp").setValue(0.1); + getField("RollMax").setValue(55); + getField("PitchMax").setValue(55); + getField("YawMax").setValue(35); + getField("MaxAxisLock").setValue(15); + getField("MaxAxisLockRate").setValue(2); + getField("MaxWeakLevelingRate").setValue(5); + getField("LowThrottleZeroIntegral").setValue("TRUE"); } @@ -211,7 +250,7 @@ public class StabilizationSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0xE2147404; + protected static final int OBJID = 0x5F78C51E; protected static final String NAME = "StabilizationSettings"; protected static String DESCRIPTION = "PID settings used by the Stabilization module to combine the @ref AttitudeActual and @ref AttitudeDesired to compute @ref ActuatorDesired"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java index e9313472c..458dd9d10 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java @@ -68,6 +68,7 @@ public class SystemAlarms extends UAVDataObject { AlarmElemNames.add("FlightTime"); AlarmElemNames.add("I2C"); AlarmElemNames.add("GPS"); + AlarmElemNames.add("BootFault"); List AlarmEnumOptions = new ArrayList(); AlarmEnumOptions.add("Uninitialised"); AlarmEnumOptions.add("OK"); @@ -106,8 +107,8 @@ public class SystemAlarms extends UAVDataObject { metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 4000; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; metadata.loggingUpdatePeriod = 1000; @@ -137,6 +138,7 @@ public class SystemAlarms extends UAVDataObject { getField("Alarm").setValue("Uninitialised",13); getField("Alarm").setValue("Uninitialised",14); getField("Alarm").setValue("Uninitialised",15); + getField("Alarm").setValue("Uninitialised",16); } @@ -165,7 +167,7 @@ public class SystemAlarms extends UAVDataObject { } // Constants - protected static final int OBJID = 0x89C3DCB2; + protected static final int OBJID = 0x737ADCF2; protected static final String NAME = "SystemAlarms"; protected static String DESCRIPTION = "Alarms from OpenPilot to indicate failure conditions or warnings. Set by various modules."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java index 99bceb6ba..e3c2cf0b0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java @@ -51,6 +51,11 @@ public class SystemSettings extends UAVDataObject { List fields = new ArrayList(); + List GUIConfigDataElemNames = new ArrayList(); + GUIConfigDataElemNames.add("0"); + GUIConfigDataElemNames.add("1"); + fields.add( new UAVObjectField("GUIConfigData", "bits", UAVObjectField.FieldType.UINT32, GUIConfigDataElemNames, null) ); + List AirframeTypeElemNames = new ArrayList(); AirframeTypeElemNames.add("0"); List AirframeTypeEnumOptions = new ArrayList(); @@ -117,6 +122,8 @@ public class SystemSettings extends UAVDataObject { */ public void setDefaultFieldValues() { + getField("GUIConfigData").setValue(0,0); + getField("GUIConfigData").setValue(0,1); getField("AirframeType").setValue("FixedWing"); } @@ -146,7 +153,7 @@ public class SystemSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x3875CEE; + protected static final int OBJID = 0x30BD5D7C; protected static final String NAME = "SystemSettings"; protected static String DESCRIPTION = "Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java index 7c34360e9..d1c51d43f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java @@ -59,6 +59,10 @@ public class SystemStats extends UAVDataObject { HeapRemainingElemNames.add("0"); fields.add( new UAVObjectField("HeapRemaining", "bytes", UAVObjectField.FieldType.UINT16, HeapRemainingElemNames, null) ); + List IRQStackRemainingElemNames = new ArrayList(); + IRQStackRemainingElemNames.add("0"); + fields.add( new UAVObjectField("IRQStackRemaining", "bytes", UAVObjectField.FieldType.UINT16, IRQStackRemainingElemNames, null) ); + List CPULoadElemNames = new ArrayList(); CPULoadElemNames.add("0"); fields.add( new UAVObjectField("CPULoad", "%", UAVObjectField.FieldType.UINT8, CPULoadElemNames, null) ); @@ -140,7 +144,7 @@ public class SystemStats extends UAVDataObject { } // Constants - protected static final int OBJID = 0xAA26FFFA; + protected static final int OBJID = 0xD610A0F0; protected static final String NAME = "SystemStats"; protected static String DESCRIPTION = "CPU and memory usage from OpenPilot computer. "; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java index 3ad065b5c..54825fafe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java @@ -65,6 +65,8 @@ public class TaskInfo extends UAVDataObject { StackRemainingElemNames.add("Stabilization"); StackRemainingElemNames.add("Guidance"); StackRemainingElemNames.add("FlightPlan"); + StackRemainingElemNames.add("Com2UsbBridge"); + StackRemainingElemNames.add("Usb2ComBridge"); fields.add( new UAVObjectField("StackRemaining", "bytes", UAVObjectField.FieldType.UINT16, StackRemainingElemNames, null) ); List RunningElemNames = new ArrayList(); @@ -81,11 +83,31 @@ public class TaskInfo extends UAVDataObject { RunningElemNames.add("Stabilization"); RunningElemNames.add("Guidance"); RunningElemNames.add("FlightPlan"); + RunningElemNames.add("Com2UsbBridge"); + RunningElemNames.add("Usb2ComBridge"); List RunningEnumOptions = new ArrayList(); RunningEnumOptions.add("False"); RunningEnumOptions.add("True"); fields.add( new UAVObjectField("Running", "bool", UAVObjectField.FieldType.ENUM, RunningElemNames, RunningEnumOptions) ); + List RunningTimeElemNames = new ArrayList(); + RunningTimeElemNames.add("System"); + RunningTimeElemNames.add("Actuator"); + RunningTimeElemNames.add("Attitude"); + RunningTimeElemNames.add("TelemetryTx"); + RunningTimeElemNames.add("TelemetryTxPri"); + RunningTimeElemNames.add("TelemetryRx"); + RunningTimeElemNames.add("GPS"); + RunningTimeElemNames.add("ManualControl"); + RunningTimeElemNames.add("Altitude"); + RunningTimeElemNames.add("AHRSComms"); + RunningTimeElemNames.add("Stabilization"); + RunningTimeElemNames.add("Guidance"); + RunningTimeElemNames.add("FlightPlan"); + RunningTimeElemNames.add("Com2UsbBridge"); + RunningTimeElemNames.add("Usb2ComBridge"); + fields.add( new UAVObjectField("RunningTime", "%", UAVObjectField.FieldType.UINT8, RunningTimeElemNames, null) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -159,7 +181,7 @@ public class TaskInfo extends UAVDataObject { } // Constants - protected static final int OBJID = 0x50F599F0; + protected static final int OBJID = 0xE34A7C32; protected static final String NAME = "TaskInfo"; protected static String DESCRIPTION = "Task information"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java index d1d47aebb..c2cf64d49 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java @@ -28,13 +28,14 @@ package org.openpilot.uavtalk.uavobjects; -//import org.openpilot.uavtalk.uavobjects.*; +import org.openpilot.uavtalk.uavobjects.*; import org.openpilot.uavtalk.UAVObjectManager; public class UAVObjectsInitialize { public static void register(UAVObjectManager objMngr) { try { + objMngr.registerObject( new AccessoryDesired() ); objMngr.registerObject( new ActuatorCommand() ); objMngr.registerObject( new ActuatorDesired() ); objMngr.registerObject( new ActuatorSettings() ); @@ -45,19 +46,25 @@ public class UAVObjectsInitialize { objMngr.registerObject( new AttitudeRaw() ); objMngr.registerObject( new AttitudeSettings() ); objMngr.registerObject( new BaroAltitude() ); - objMngr.registerObject( new BatterySettings() ); + objMngr.registerObject( new CameraDesired() ); + objMngr.registerObject( new CameraStabSettings() ); + objMngr.registerObject( new FaultSettings() ); objMngr.registerObject( new FirmwareIAPObj() ); + objMngr.registerObject( new FlightBatterySettings() ); objMngr.registerObject( new FlightBatteryState() ); objMngr.registerObject( new FlightPlanControl() ); objMngr.registerObject( new FlightPlanSettings() ); objMngr.registerObject( new FlightPlanStatus() ); + objMngr.registerObject( new FlightStatus() ); objMngr.registerObject( new FlightTelemetryStats() ); + objMngr.registerObject( new GCSReceiver() ); objMngr.registerObject( new GCSTelemetryStats() ); objMngr.registerObject( new GPSPosition() ); objMngr.registerObject( new GPSSatellites() ); objMngr.registerObject( new GPSTime() ); objMngr.registerObject( new GuidanceSettings() ); objMngr.registerObject( new HomeLocation() ); + objMngr.registerObject( new HwSettings() ); objMngr.registerObject( new I2CStats() ); objMngr.registerObject( new ManualControlCommand() ); objMngr.registerObject( new ManualControlSettings() ); @@ -68,6 +75,7 @@ public class UAVObjectsInitialize { objMngr.registerObject( new PositionActual() ); objMngr.registerObject( new PositionDesired() ); objMngr.registerObject( new RateDesired() ); + objMngr.registerObject( new ReceiverActivity() ); objMngr.registerObject( new SonarAltitude() ); objMngr.registerObject( new StabilizationDesired() ); objMngr.registerObject( new StabilizationSettings() ); @@ -75,7 +83,6 @@ public class UAVObjectsInitialize { objMngr.registerObject( new SystemSettings() ); objMngr.registerObject( new SystemStats() ); objMngr.registerObject( new TaskInfo() ); - objMngr.registerObject( new TelemetrySettings() ); objMngr.registerObject( new VelocityActual() ); objMngr.registerObject( new VelocityDesired() ); objMngr.registerObject( new WatchdogStatus() ); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java index 649e6c122..97d038cfe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java @@ -136,7 +136,7 @@ public class VelocityActual extends UAVDataObject { } // Constants - protected static final int OBJID = 0x48009C88; + protected static final int OBJID = 0x43007EB0; protected static final String NAME = "VelocityActual"; protected static String DESCRIPTION = "Updated by @ref AHRSCommsModule and used within @ref GuidanceModule for velocity control"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java index 27f290898..f39fbd6de 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java @@ -136,7 +136,7 @@ public class VelocityDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0x122F5E3A; + protected static final int OBJID = 0x25139D1A; protected static final String NAME = "VelocityDesired"; protected static String DESCRIPTION = "Used within @ref GuidanceModule to communicate between the task computing the desired velocity and the PID loop to achieve it (running at different rates)."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java index 3adcad96b..acbdb43d1 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java @@ -132,7 +132,7 @@ public class WatchdogStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0xD646E910; + protected static final int OBJID = 0xA207FA7C; protected static final String NAME = "WatchdogStatus"; protected static String DESCRIPTION = "For monitoring the flags in the watchdog and especially the bootup flags"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp index e942b238f..dc593fd5f 100644 --- a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp +++ b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp @@ -258,7 +258,7 @@ bool UAVObjectGeneratorJava::process_object(ObjectInfo* info) outCode.replace(QString("$(INITFIELDS)"), initfields); // Write the java code - bool res = writeFileIfDiffrent( javaOutputPath.absolutePath() + "/" + info->namelc + ".java", outCode ); + bool res = writeFileIfDiffrent( javaOutputPath.absolutePath() + "/" + info->name + ".java", outCode ); if (!res) { cout << "Error: Could not write gcs output files" << endl; return false; From 4a38eac0db8f63a33f996407078dde58b59946cb Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 5 Apr 2012 23:35:04 -0500 Subject: [PATCH 051/284] Small upgrades to teh android install --- androidgcs/.classpath | 1 + androidgcs/proguard.cfg | 2 +- androidgcs/res/layout/gcs_home.xml | 50 ++++++++---- .../androidgcs/OPTelemetryService.java | 79 ++++++++++++++++++- 4 files changed, 114 insertions(+), 18 deletions(-) diff --git a/androidgcs/.classpath b/androidgcs/.classpath index eb33e4360..c88f96260 100644 --- a/androidgcs/.classpath +++ b/androidgcs/.classpath @@ -5,5 +5,6 @@ + diff --git a/androidgcs/proguard.cfg b/androidgcs/proguard.cfg index 12dd0392c..ec78e7622 100644 --- a/androidgcs/proguard.cfg +++ b/androidgcs/proguard.cfg @@ -14,7 +14,7 @@ -keep public class * extends android.preference.Preference -keep public class com.android.vending.licensing.ILicensingService --keepclasseswithmembernames class * { +-keepclasseswithmembers class * { native ; } diff --git a/androidgcs/res/layout/gcs_home.xml b/androidgcs/res/layout/gcs_home.xml index e07f5b003..0ff427bcd 100644 --- a/androidgcs/res/layout/gcs_home.xml +++ b/androidgcs/res/layout/gcs_home.xml @@ -1,15 +1,37 @@ - - - - + + + + + + + \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index ce90f5a48..bc711560d 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -71,21 +71,25 @@ public class OPTelemetryService extends Service { stopSelf(msg.arg2); break; case MSG_CONNECT: - Toast.makeText(getApplicationContext(), "Attempting connection", Toast.LENGTH_SHORT).show(); terminate = false; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); - //int connection_type = Integer.decode(prefs.getString("connection_type", "")); - int connection_type = 1; + int connection_type = Integer.decode(prefs.getString("connection_type", "")); switch(connection_type) { case 0: // No connection return; case 1: + Toast.makeText(getApplicationContext(), "Attempting fake connection", Toast.LENGTH_SHORT).show(); activeTelem = new FakeTelemetryThread(); break; case 2: + Toast.makeText(getApplicationContext(), "Attempting BT connection", Toast.LENGTH_SHORT).show(); activeTelem = new BTTelemetryThread(); break; case 3: + Toast.makeText(getApplicationContext(), "Attempting TCP connection", Toast.LENGTH_SHORT).show(); + activeTelem = new TcpTelemetryThread(); + break; + default: throw new Error("Unsupported"); } activeTelem.start(); @@ -329,6 +333,75 @@ public class OPTelemetryService extends Service { }; + private class TcpTelemetryThread extends Thread implements TelemTask { + + private UAVObjectManager objMngr; + private UAVTalk uavTalk; + private Telemetry tel; + private TelemetryMonitor mon; + + public UAVObjectManager getObjectManager() { return objMngr; }; + + TcpTelemetryThread() { + objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + } + + public void run() { + if (DEBUG) Log.d(TAG, "Telemetry Thread started"); + + Looper.prepare(); + + TcpUAVTalk tcp = new TcpUAVTalk(OPTelemetryService.this); + for( int i = 0; i < 10; i++ ) { + if (DEBUG) Log.d(TAG, "Attempting network Connection"); + + tcp.connect(objMngr); + + if (DEBUG) Log.d(TAG, "Done attempting connection"); + if( tcp.getConnected() ) + break; + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + Log.e(TAG, "Thread interrupted while trying to connect"); + e.printStackTrace(); + return; + } + } + if( ! tcp.getConnected() ) { + return; + } + + + if (DEBUG) Log.d(TAG, "Connected via network"); + + uavTalk = tcp.getUavtalk(); + tel = new Telemetry(uavTalk, objMngr); + mon = new TelemetryMonitor(objMngr,tel); + mon.addObserver(new Observer() { + public void update(Observable arg0, Object arg1) { + System.out.println("Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated()); + if(mon.getConnected() /*&& mon.getObjectsUpdated()*/) { + Intent intent = new Intent(); + intent.setAction(INTENT_ACTION_CONNECTED); + sendBroadcast(intent,null); + } + } + }); + + + if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop"); + while( !terminate ) { + if( !uavTalk.processInputStream() ) + break; + } + if (DEBUG) Log.d(TAG, "UAVTalk stream disconnected"); + } + + }; + void postNotification(int id, String message) { String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNManager = (NotificationManager) getSystemService(ns); From 3445cafb0a34c5dfa2bda706b1343927edbef7e3 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 10:22:38 -0500 Subject: [PATCH 052/284] Add TCP UAVTalk interface for android --- .../org/openpilot/androidgcs/TcpUAVTalk.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java diff --git a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java new file mode 100644 index 000000000..ad503757e --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java @@ -0,0 +1,84 @@ +package org.openpilot.androidgcs; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVTalk; + +import android.content.Context; +import android.util.Log; + +public class TcpUAVTalk { + private final String TAG = "TcpUAVTalk"; + public static int LOGLEVEL = 2; + public static boolean WARN = LOGLEVEL > 1; + public static boolean DEBUG = LOGLEVEL > 0; + + // Temporarily define fixed device name + public final static String IP_ADDRESS = "127.0.0.1"; + public final static int PORT = 9001; + + private UAVTalk uavTalk; + private boolean connected; + + public TcpUAVTalk(Context caller) { + if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + IP_ADDRESS); + + connected = false; + } + + public boolean connect(UAVObjectManager objMngr) { + if( getConnected() ) + return true; + if( !openTelemetryTcp(objMngr) ) + return false; + return true; + } + + public boolean getConnected() { + return connected; + } + + public UAVTalk getUavtalk() { + return uavTalk; + } + + + private boolean openTelemetryTcp(UAVObjectManager objMngr) { + Log.d(TAG, "Opening conncetion to " + IP_ADDRESS); + + InetAddress serverAddr = null; + try { + serverAddr = InetAddress.getByName(IP_ADDRESS); + } catch (UnknownHostException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + return false; + } + + Socket socket = null; + try { + socket = new Socket(serverAddr,PORT); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + return false; + } + + connected = true; + + try { + uavTalk = new UAVTalk(socket.getInputStream(), socket.getOutputStream(), objMngr); + } catch (IOException e) { + Log.e(TAG,"Error starting UAVTalk"); + // TODO Auto-generated catch block + //e.printStackTrace(); + return false; + } + + return true; + } + +} From 3bcfeca77ce83993fb2aed42ac7270824810209a Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 11:59:50 -0500 Subject: [PATCH 053/284] Enable some debugging statements --- .../org/openpilot/androidgcs/TcpUAVTalk.java | 4 ++-- .../src/org/openpilot/uavtalk/Telemetry.java | 2 +- .../openpilot/uavtalk/TelemetryMonitor.java | 3 ++- .../src/org/openpilot/uavtalk/UAVTalk.java | 18 +++++++++++------- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java index ad503757e..47074f968 100644 --- a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java +++ b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java @@ -17,7 +17,7 @@ public class TcpUAVTalk { public static boolean DEBUG = LOGLEVEL > 0; // Temporarily define fixed device name - public final static String IP_ADDRESS = "127.0.0.1"; + public final static String IP_ADDRESS = "10.21.18.120"; public final static int PORT = 9001; private UAVTalk uavTalk; @@ -47,7 +47,7 @@ public class TcpUAVTalk { private boolean openTelemetryTcp(UAVObjectManager objMngr) { - Log.d(TAG, "Opening conncetion to " + IP_ADDRESS); + Log.d(TAG, "Opening conncetion to " + IP_ADDRESS + " at address " + PORT); InetAddress serverAddr = null; try { diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 1395a5c08..11e6cb2ca 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -17,7 +17,7 @@ import android.util.Log; public class Telemetry { private final String TAG = "Telemetry"; - public static int LOGLEVEL = 0; + public static int LOGLEVEL = 2; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index daedcc85b..903b6b29f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -185,7 +185,8 @@ public class TelemetryMonitor extends Observable{ // Force update if not yet connected gcsStatsObj = objMngr.getObject("GCSTelemetryStats"); flightStatsObj = objMngr.getObject("FlightTelemetryStats"); - + if (DEBUG) Log.d(TAG,"GCS Status: " + gcsStatsObj.getField("Status").getValue()); + if (DEBUG) Log.d(TAG,"Flight Status: " + flightStatsObj.getField("Status").getValue()); if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") != 0 || ((String) flightStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 ) { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 39c1f6ee7..5a3a9a1a5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -12,7 +12,7 @@ import android.util.Log; public class UAVTalk extends Observable { static final String TAG = "UAVTalk"; - public static int LOGLEVEL = 0; + public static int LOGLEVEL = 2; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; @@ -433,6 +433,7 @@ public class UAVTalk extends Observable { rxCSPacket = rxbyte; if (rxCS != rxCSPacket) { // packet error - faulty CRC + if (DEBUG) Log.d(TAG,"Bad crc"); stats.rxErrors++; rxState = RxStateType.STATE_SYNC; break; @@ -441,11 +442,14 @@ public class UAVTalk extends Observable { if (rxPacketLength != (packetSize + 1)) { // packet error - // mismatched packet // size + if (DEBUG) Log.d(TAG,"Bad size"); stats.rxErrors++; rxState = RxStateType.STATE_SYNC; break; } + if (DEBUG) Log.d(TAG,"Received"); + rxBuffer.position(0); receiveObject(rxType, rxObjId, rxInstId, rxBuffer); stats.rxObjectBytes += rxLength; @@ -500,8 +504,8 @@ public class UAVTalk extends Observable { case TYPE_OBJ_ACK: // All instances, not allowed for OBJ_ACK messages if (!allInstances) { - // System.out.println("Received object ack: " + objId + " " + - // objMngr.getObject(objId).getName()); + System.out.println("Received object ack: " + objId + " " + + objMngr.getObject(objId).getName()); // Get object and update its data obj = updateObject(objId, instId, data); // Transmit ACK @@ -517,8 +521,8 @@ public class UAVTalk extends Observable { case TYPE_OBJ_REQ: // Get object, if all instances are requested get instance 0 of the // object - // System.out.println("Received object request: " + objId + " " + - // objMngr.getObject(objId).getName()); + System.out.println("Received object request: " + objId + " " + + objMngr.getObject(objId).getName()); if (allInstances) { obj = objMngr.getObject(objId); } else { @@ -534,8 +538,8 @@ public class UAVTalk extends Observable { case TYPE_ACK: // All instances, not allowed for ACK messages if (!allInstances) { - // System.out.println("Received ack: " + objId + " " + - // objMngr.getObject(objId).getName()); + System.out.println("Received ack: " + objId + " " + + objMngr.getObject(objId).getName()); // Get object obj = objMngr.getObject(objId, instId); // Check if an ack is pending From beb75f22cf62cec49f12d352b59f82c32a180bcd Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 12:06:36 -0500 Subject: [PATCH 054/284] Remove the TCHAIN_PREFIX flag from the OSX Makefile. No clue how that got merged in. --- flight/Revolution/Makefile.osx | 3 --- 1 file changed, 3 deletions(-) diff --git a/flight/Revolution/Makefile.osx b/flight/Revolution/Makefile.osx index e2c8ea694..a38bced0d 100644 --- a/flight/Revolution/Makefile.osx +++ b/flight/Revolution/Makefile.osx @@ -40,9 +40,6 @@ USE_BOOTLOADER ?= NO # Set to YES when using Code Sourcery toolchain CODE_SOURCERY ?= NO -# Toolchain prefix (i.e arm-elf- -> arm-elf-gcc.exe) -TCHAIN_PREFIX ?= /usr/local/android-ndk-r5/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi- - # Remove command is different for Code Sourcery on Windows REMOVE_CMD ?= rm From aa99433310ada974ecfae473351818f7858b10a9 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 14:42:19 -0500 Subject: [PATCH 055/284] Fix an insidious bug in the Android UAVObjectField unpack method for enums that was exposed by shuffling field orders. There goes 5 hours, FML. --- androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 78ad70630..286859e63 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -226,9 +226,9 @@ public class UAVObjectField { } case ENUM: { - List l = (List) data; + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - l.set(index, dataIn.get(index)); + l.set(index, dataIn.get()); } break; } From e9964668be5fcfa8962cb63c0181c82037d71785 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 14:49:57 -0500 Subject: [PATCH 056/284] Update objects and delete old UAVObjects --- .../uavtalk/uavobjects/AHRSCalibration.java | 252 ------------------ .../uavtalk/uavobjects/AHRSSettings.java | 178 ------------- .../uavtalk/uavobjects/AhrsStatus.java | 201 -------------- .../uavtalk/uavobjects/AttitudeRaw.java | 158 ----------- .../uavtalk/uavobjects/FlightStatus.java | 4 +- .../uavtalk/uavobjects/GuidanceSettings.java | 8 +- .../uavtalk/uavobjects/HomeLocation.java | 32 +-- .../uavtalk/uavobjects/HwSettings.java | 98 +++++-- .../uavobjects/ManualControlSettings.java | 4 +- .../uavtalk/uavobjects/MixerStatus.java | 10 +- .../uavtalk/uavobjects/NedAccel.java | 6 +- .../uavtalk/uavobjects/PositionActual.java | 8 +- .../uavtalk/uavobjects/PositionDesired.java | 8 +- .../uavtalk/uavobjects/SystemAlarms.java | 4 +- .../uavtalk/uavobjects/SystemStats.java | 14 +- .../uavtalk/uavobjects/TaskInfo.java | 17 +- .../uavobjects/UAVObjectsInitialize.java | 18 +- .../uavtalk/uavobjects/VelocityActual.java | 8 +- .../uavtalk/uavobjects/VelocityDesired.java | 8 +- 19 files changed, 153 insertions(+), 883 deletions(-) delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java deleted file mode 100644 index 47d42991e..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java +++ /dev/null @@ -1,252 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * Contains the calibration settings for the @ref AHRSCommsModule - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -Contains the calibration settings for the @ref AHRSCommsModule - -generated from ahrscalibration.xml - **/ -public class AHRSCalibration extends UAVDataObject { - - public AHRSCalibration() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List accel_biasElemNames = new ArrayList(); - accel_biasElemNames.add("X"); - accel_biasElemNames.add("Y"); - accel_biasElemNames.add("Z"); - fields.add( new UAVObjectField("accel_bias", "m/s", UAVObjectField.FieldType.FLOAT32, accel_biasElemNames, null) ); - - List accel_scaleElemNames = new ArrayList(); - accel_scaleElemNames.add("X"); - accel_scaleElemNames.add("Y"); - accel_scaleElemNames.add("Z"); - fields.add( new UAVObjectField("accel_scale", "(m/s)/lsb", UAVObjectField.FieldType.FLOAT32, accel_scaleElemNames, null) ); - - List accel_orthoElemNames = new ArrayList(); - accel_orthoElemNames.add("XY"); - accel_orthoElemNames.add("XZ"); - accel_orthoElemNames.add("YZ"); - fields.add( new UAVObjectField("accel_ortho", "scale", UAVObjectField.FieldType.FLOAT32, accel_orthoElemNames, null) ); - - List accel_varElemNames = new ArrayList(); - accel_varElemNames.add("X"); - accel_varElemNames.add("Y"); - accel_varElemNames.add("Z"); - fields.add( new UAVObjectField("accel_var", "(m/s)^2", UAVObjectField.FieldType.FLOAT32, accel_varElemNames, null) ); - - List gyro_biasElemNames = new ArrayList(); - gyro_biasElemNames.add("X"); - gyro_biasElemNames.add("Y"); - gyro_biasElemNames.add("Z"); - fields.add( new UAVObjectField("gyro_bias", "rad/s", UAVObjectField.FieldType.FLOAT32, gyro_biasElemNames, null) ); - - List gyro_scaleElemNames = new ArrayList(); - gyro_scaleElemNames.add("X"); - gyro_scaleElemNames.add("Y"); - gyro_scaleElemNames.add("Z"); - fields.add( new UAVObjectField("gyro_scale", "(rad/s)/lsb", UAVObjectField.FieldType.FLOAT32, gyro_scaleElemNames, null) ); - - List gyro_varElemNames = new ArrayList(); - gyro_varElemNames.add("X"); - gyro_varElemNames.add("Y"); - gyro_varElemNames.add("Z"); - fields.add( new UAVObjectField("gyro_var", "(rad/s)^2", UAVObjectField.FieldType.FLOAT32, gyro_varElemNames, null) ); - - List gyro_tempcompfactorElemNames = new ArrayList(); - gyro_tempcompfactorElemNames.add("X"); - gyro_tempcompfactorElemNames.add("Y"); - gyro_tempcompfactorElemNames.add("Z"); - fields.add( new UAVObjectField("gyro_tempcompfactor", "raw/raw", UAVObjectField.FieldType.FLOAT32, gyro_tempcompfactorElemNames, null) ); - - List mag_biasElemNames = new ArrayList(); - mag_biasElemNames.add("X"); - mag_biasElemNames.add("Y"); - mag_biasElemNames.add("Z"); - fields.add( new UAVObjectField("mag_bias", "mGau", UAVObjectField.FieldType.FLOAT32, mag_biasElemNames, null) ); - - List mag_scaleElemNames = new ArrayList(); - mag_scaleElemNames.add("X"); - mag_scaleElemNames.add("Y"); - mag_scaleElemNames.add("Z"); - fields.add( new UAVObjectField("mag_scale", "(mGau)/lsb", UAVObjectField.FieldType.FLOAT32, mag_scaleElemNames, null) ); - - List mag_varElemNames = new ArrayList(); - mag_varElemNames.add("X"); - mag_varElemNames.add("Y"); - mag_varElemNames.add("Z"); - fields.add( new UAVObjectField("mag_var", "mGau^2", UAVObjectField.FieldType.FLOAT32, mag_varElemNames, null) ); - - List vel_varElemNames = new ArrayList(); - vel_varElemNames.add("0"); - fields.add( new UAVObjectField("vel_var", "(m/s)^2", UAVObjectField.FieldType.FLOAT32, vel_varElemNames, null) ); - - List pos_varElemNames = new ArrayList(); - pos_varElemNames.add("0"); - fields.add( new UAVObjectField("pos_var", "m^2", UAVObjectField.FieldType.FLOAT32, pos_varElemNames, null) ); - - List measure_varElemNames = new ArrayList(); - measure_varElemNames.add("0"); - List measure_varEnumOptions = new ArrayList(); - measure_varEnumOptions.add("SET"); - measure_varEnumOptions.add("MEASURE"); - fields.add( new UAVObjectField("measure_var", "", UAVObjectField.FieldType.ENUM, measure_varElemNames, measure_varEnumOptions) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - getField("accel_bias").setValue(-73.5,0); - getField("accel_bias").setValue(-73.5,1); - getField("accel_bias").setValue(73.5,2); - getField("accel_scale").setValue(0.0359,0); - getField("accel_scale").setValue(0.0359,1); - getField("accel_scale").setValue(0.0359,2); - getField("accel_ortho").setValue(0,0); - getField("accel_ortho").setValue(0,1); - getField("accel_ortho").setValue(0,2); - getField("accel_var").setValue(0.0005,0); - getField("accel_var").setValue(0.0005,1); - getField("accel_var").setValue(0.0005,2); - getField("gyro_bias").setValue(28,0); - getField("gyro_bias").setValue(-28,1); - getField("gyro_bias").setValue(28,2); - getField("gyro_scale").setValue(-0.017,0); - getField("gyro_scale").setValue(0.017,1); - getField("gyro_scale").setValue(-0.017,2); - getField("gyro_var").setValue(0.0001,0); - getField("gyro_var").setValue(0.0001,1); - getField("gyro_var").setValue(0.0001,2); - getField("gyro_tempcompfactor").setValue(0,0); - getField("gyro_tempcompfactor").setValue(0,1); - getField("gyro_tempcompfactor").setValue(0,2); - getField("mag_bias").setValue(0,0); - getField("mag_bias").setValue(0,1); - getField("mag_bias").setValue(0,2); - getField("mag_scale").setValue(1,0); - getField("mag_scale").setValue(1,1); - getField("mag_scale").setValue(1,2); - getField("mag_var").setValue(50,0); - getField("mag_var").setValue(50,1); - getField("mag_var").setValue(50,2); - getField("vel_var").setValue(10); - getField("pos_var").setValue(0.04); - getField("measure_var").setValue("SET"); - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - AHRSCalibration obj = new AHRSCalibration(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public AHRSCalibration GetInstance(UAVObjectManager objMngr, int instID) - { - return (AHRSCalibration)(objMngr.getObject(AHRSCalibration.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0xFD0EDFC4; - protected static final String NAME = "AHRSCalibration"; - protected static String DESCRIPTION = "Contains the calibration settings for the @ref AHRSCommsModule"; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 1 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java deleted file mode 100644 index 032dae775..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java +++ /dev/null @@ -1,178 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * Settings for the @ref AHRSCommsModule to control the algorithm and what is updated - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -Settings for the @ref AHRSCommsModule to control the algorithm and what is updated - -generated from ahrssettings.xml - **/ -public class AHRSSettings extends UAVDataObject { - - public AHRSSettings() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List YawBiasElemNames = new ArrayList(); - YawBiasElemNames.add("0"); - fields.add( new UAVObjectField("YawBias", "", UAVObjectField.FieldType.FLOAT32, YawBiasElemNames, null) ); - - List PitchBiasElemNames = new ArrayList(); - PitchBiasElemNames.add("0"); - fields.add( new UAVObjectField("PitchBias", "", UAVObjectField.FieldType.FLOAT32, PitchBiasElemNames, null) ); - - List RollBiasElemNames = new ArrayList(); - RollBiasElemNames.add("0"); - fields.add( new UAVObjectField("RollBias", "", UAVObjectField.FieldType.FLOAT32, RollBiasElemNames, null) ); - - List AlgorithmElemNames = new ArrayList(); - AlgorithmElemNames.add("0"); - List AlgorithmEnumOptions = new ArrayList(); - AlgorithmEnumOptions.add("SIMPLE"); - AlgorithmEnumOptions.add("INSGPS_INDOOR_NOMAG"); - AlgorithmEnumOptions.add("INSGPS_INDOOR"); - AlgorithmEnumOptions.add("INSGPS_OUTDOOR"); - fields.add( new UAVObjectField("Algorithm", "", UAVObjectField.FieldType.ENUM, AlgorithmElemNames, AlgorithmEnumOptions) ); - - List DownsamplingElemNames = new ArrayList(); - DownsamplingElemNames.add("0"); - fields.add( new UAVObjectField("Downsampling", "", UAVObjectField.FieldType.UINT8, DownsamplingElemNames, null) ); - - List UpdatePeriodElemNames = new ArrayList(); - UpdatePeriodElemNames.add("0"); - fields.add( new UAVObjectField("UpdatePeriod", "ms", UAVObjectField.FieldType.UINT8, UpdatePeriodElemNames, null) ); - - List BiasCorrectedRawElemNames = new ArrayList(); - BiasCorrectedRawElemNames.add("0"); - List BiasCorrectedRawEnumOptions = new ArrayList(); - BiasCorrectedRawEnumOptions.add("TRUE"); - BiasCorrectedRawEnumOptions.add("FALSE"); - fields.add( new UAVObjectField("BiasCorrectedRaw", "", UAVObjectField.FieldType.ENUM, BiasCorrectedRawElemNames, BiasCorrectedRawEnumOptions) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - getField("YawBias").setValue(0); - getField("PitchBias").setValue(0); - getField("RollBias").setValue(0); - getField("Algorithm").setValue("INSGPS_INDOOR_NOMAG"); - getField("Downsampling").setValue(20); - getField("UpdatePeriod").setValue(1); - getField("BiasCorrectedRaw").setValue("TRUE"); - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - AHRSSettings obj = new AHRSSettings(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public AHRSSettings GetInstance(UAVObjectManager objMngr, int instID) - { - return (AHRSSettings)(objMngr.getObject(AHRSSettings.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0xF8591ED8; - protected static final String NAME = "AHRSSettings"; - protected static String DESCRIPTION = "Settings for the @ref AHRSCommsModule to control the algorithm and what is updated"; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 1 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java deleted file mode 100644 index 82e447a70..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java +++ /dev/null @@ -1,201 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * Status for the @ref AHRSCommsModule, including communication errors - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -Status for the @ref AHRSCommsModule, including communication errors - -generated from ahrsstatus.xml - **/ -public class AhrsStatus extends UAVDataObject { - - public AhrsStatus() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List RunningTimeElemNames = new ArrayList(); - RunningTimeElemNames.add("0"); - fields.add( new UAVObjectField("RunningTime", "ms", UAVObjectField.FieldType.UINT32, RunningTimeElemNames, null) ); - - List SerialNumberElemNames = new ArrayList(); - SerialNumberElemNames.add("0"); - SerialNumberElemNames.add("1"); - SerialNumberElemNames.add("2"); - SerialNumberElemNames.add("3"); - SerialNumberElemNames.add("4"); - SerialNumberElemNames.add("5"); - SerialNumberElemNames.add("6"); - SerialNumberElemNames.add("7"); - fields.add( new UAVObjectField("SerialNumber", "", UAVObjectField.FieldType.UINT8, SerialNumberElemNames, null) ); - - List CPULoadElemNames = new ArrayList(); - CPULoadElemNames.add("0"); - fields.add( new UAVObjectField("CPULoad", "count", UAVObjectField.FieldType.UINT8, CPULoadElemNames, null) ); - - List IdleTimePerCyleElemNames = new ArrayList(); - IdleTimePerCyleElemNames.add("0"); - fields.add( new UAVObjectField("IdleTimePerCyle", "10x ms", UAVObjectField.FieldType.UINT8, IdleTimePerCyleElemNames, null) ); - - List RunningTimePerCyleElemNames = new ArrayList(); - RunningTimePerCyleElemNames.add("0"); - fields.add( new UAVObjectField("RunningTimePerCyle", "10x ms", UAVObjectField.FieldType.UINT8, RunningTimePerCyleElemNames, null) ); - - List DroppedUpdatesElemNames = new ArrayList(); - DroppedUpdatesElemNames.add("0"); - fields.add( new UAVObjectField("DroppedUpdates", "count", UAVObjectField.FieldType.UINT8, DroppedUpdatesElemNames, null) ); - - List LinkRunningElemNames = new ArrayList(); - LinkRunningElemNames.add("0"); - List LinkRunningEnumOptions = new ArrayList(); - LinkRunningEnumOptions.add("FALSE"); - LinkRunningEnumOptions.add("TRUE"); - fields.add( new UAVObjectField("LinkRunning", "", UAVObjectField.FieldType.ENUM, LinkRunningElemNames, LinkRunningEnumOptions) ); - - List AhrsKickstartsElemNames = new ArrayList(); - AhrsKickstartsElemNames.add("0"); - fields.add( new UAVObjectField("AhrsKickstarts", "count", UAVObjectField.FieldType.UINT8, AhrsKickstartsElemNames, null) ); - - List AhrsCrcErrorsElemNames = new ArrayList(); - AhrsCrcErrorsElemNames.add("0"); - fields.add( new UAVObjectField("AhrsCrcErrors", "count", UAVObjectField.FieldType.UINT8, AhrsCrcErrorsElemNames, null) ); - - List AhrsRetriesElemNames = new ArrayList(); - AhrsRetriesElemNames.add("0"); - fields.add( new UAVObjectField("AhrsRetries", "count", UAVObjectField.FieldType.UINT8, AhrsRetriesElemNames, null) ); - - List AhrsInvalidPacketsElemNames = new ArrayList(); - AhrsInvalidPacketsElemNames.add("0"); - fields.add( new UAVObjectField("AhrsInvalidPackets", "count", UAVObjectField.FieldType.UINT8, AhrsInvalidPacketsElemNames, null) ); - - List OpCrcErrorsElemNames = new ArrayList(); - OpCrcErrorsElemNames.add("0"); - fields.add( new UAVObjectField("OpCrcErrors", "count", UAVObjectField.FieldType.UINT8, OpCrcErrorsElemNames, null) ); - - List OpRetriesElemNames = new ArrayList(); - OpRetriesElemNames.add("0"); - fields.add( new UAVObjectField("OpRetries", "count", UAVObjectField.FieldType.UINT8, OpRetriesElemNames, null) ); - - List OpInvalidPacketsElemNames = new ArrayList(); - OpInvalidPacketsElemNames.add("0"); - fields.add( new UAVObjectField("OpInvalidPackets", "count", UAVObjectField.FieldType.UINT8, OpInvalidPacketsElemNames, null) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - AhrsStatus obj = new AhrsStatus(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public AhrsStatus GetInstance(UAVObjectManager objMngr, int instID) - { - return (AhrsStatus)(objMngr.getObject(AhrsStatus.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0x706D1AB8; - protected static final String NAME = "AhrsStatus"; - protected static String DESCRIPTION = "Status for the @ref AHRSCommsModule, including communication errors"; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 0 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java deleted file mode 100644 index b8c3aacb4..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java +++ /dev/null @@ -1,158 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * The raw attitude sensor data from @ref AHRSCommsModule. Not always updated. - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -The raw attitude sensor data from @ref AHRSCommsModule. Not always updated. - -generated from attituderaw.xml - **/ -public class AttitudeRaw extends UAVDataObject { - - public AttitudeRaw() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List gyrosElemNames = new ArrayList(); - gyrosElemNames.add("X"); - gyrosElemNames.add("Y"); - gyrosElemNames.add("Z"); - fields.add( new UAVObjectField("gyros", "deg/s", UAVObjectField.FieldType.FLOAT32, gyrosElemNames, null) ); - - List accelsElemNames = new ArrayList(); - accelsElemNames.add("X"); - accelsElemNames.add("Y"); - accelsElemNames.add("Z"); - fields.add( new UAVObjectField("accels", "m/s^2", UAVObjectField.FieldType.FLOAT32, accelsElemNames, null) ); - - List magnetometersElemNames = new ArrayList(); - magnetometersElemNames.add("X"); - magnetometersElemNames.add("Y"); - magnetometersElemNames.add("Z"); - fields.add( new UAVObjectField("magnetometers", "mGa", UAVObjectField.FieldType.INT16, magnetometersElemNames, null) ); - - List gyrotempElemNames = new ArrayList(); - gyrotempElemNames.add("XY"); - gyrotempElemNames.add("Z"); - fields.add( new UAVObjectField("gyrotemp", "raw", UAVObjectField.FieldType.UINT16, gyrotempElemNames, null) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - AttitudeRaw obj = new AttitudeRaw(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public AttitudeRaw GetInstance(UAVObjectManager objMngr, int instID) - { - return (AttitudeRaw)(objMngr.getObject(AttitudeRaw.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0xDB722974; - protected static final String NAME = "AttitudeRaw"; - protected static String DESCRIPTION = "The raw attitude sensor data from @ref AHRSCommsModule. Not always updated."; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 0 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java index d775b21e7..ac3812aa6 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java @@ -66,8 +66,10 @@ public class FlightStatus extends UAVDataObject { FlightModeEnumOptions.add("Stabilized1"); FlightModeEnumOptions.add("Stabilized2"); FlightModeEnumOptions.add("Stabilized3"); + FlightModeEnumOptions.add("AltitudeHold"); FlightModeEnumOptions.add("VelocityControl"); FlightModeEnumOptions.add("PositionHold"); + FlightModeEnumOptions.add("PathPlanner"); fields.add( new UAVObjectField("FlightMode", "", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); @@ -144,7 +146,7 @@ public class FlightStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0x743DB13C; + protected static final int OBJID = 0x19B92D8; protected static final String NAME = "FlightStatus"; protected static String DESCRIPTION = "Contains major flight status information for other modules."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java index 205384efe..5510a901d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java @@ -55,14 +55,14 @@ public class GuidanceSettings extends UAVDataObject { HorizontalPosPIElemNames.add("Kp"); HorizontalPosPIElemNames.add("Ki"); HorizontalPosPIElemNames.add("ILimit"); - fields.add( new UAVObjectField("HorizontalPosPI", "(cm/s)/cm", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) ); + fields.add( new UAVObjectField("HorizontalPosPI", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) ); List HorizontalVelPIDElemNames = new ArrayList(); HorizontalVelPIDElemNames.add("Kp"); HorizontalVelPIDElemNames.add("Ki"); HorizontalVelPIDElemNames.add("Kd"); HorizontalVelPIDElemNames.add("ILimit"); - fields.add( new UAVObjectField("HorizontalVelPID", "deg/(cm/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); + fields.add( new UAVObjectField("HorizontalVelPID", "deg/(m/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); List VerticalPosPIElemNames = new ArrayList(); VerticalPosPIElemNames.add("Kp"); @@ -87,11 +87,11 @@ public class GuidanceSettings extends UAVDataObject { List HorizontalVelMaxElemNames = new ArrayList(); HorizontalVelMaxElemNames.add("0"); - fields.add( new UAVObjectField("HorizontalVelMax", "cm/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) ); + fields.add( new UAVObjectField("HorizontalVelMax", "m/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) ); List VerticalVelMaxElemNames = new ArrayList(); VerticalVelMaxElemNames.add("0"); - fields.add( new UAVObjectField("VerticalVelMax", "cm/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) ); + fields.add( new UAVObjectField("VerticalVelMax", "m/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) ); List GuidanceModeElemNames = new ArrayList(); GuidanceModeElemNames.add("0"); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java index 68abb3633..3f3b3d8dd 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java @@ -63,24 +63,6 @@ public class HomeLocation extends UAVDataObject { AltitudeElemNames.add("0"); fields.add( new UAVObjectField("Altitude", "m over geoid", UAVObjectField.FieldType.FLOAT32, AltitudeElemNames, null) ); - List ECEFElemNames = new ArrayList(); - ECEFElemNames.add("0"); - ECEFElemNames.add("1"); - ECEFElemNames.add("2"); - fields.add( new UAVObjectField("ECEF", "cm", UAVObjectField.FieldType.INT32, ECEFElemNames, null) ); - - List RNEElemNames = new ArrayList(); - RNEElemNames.add("0"); - RNEElemNames.add("1"); - RNEElemNames.add("2"); - RNEElemNames.add("3"); - RNEElemNames.add("4"); - RNEElemNames.add("5"); - RNEElemNames.add("6"); - RNEElemNames.add("7"); - RNEElemNames.add("8"); - fields.add( new UAVObjectField("RNE", "", UAVObjectField.FieldType.FLOAT32, RNEElemNames, null) ); - List BeElemNames = new ArrayList(); BeElemNames.add("0"); BeElemNames.add("1"); @@ -146,18 +128,6 @@ public class HomeLocation extends UAVDataObject { getField("Latitude").setValue(0); getField("Longitude").setValue(0); getField("Altitude").setValue(0); - getField("ECEF").setValue(0,0); - getField("ECEF").setValue(0,1); - getField("ECEF").setValue(0,2); - getField("RNE").setValue(0,0); - getField("RNE").setValue(0,1); - getField("RNE").setValue(0,2); - getField("RNE").setValue(0,3); - getField("RNE").setValue(0,4); - getField("RNE").setValue(0,5); - getField("RNE").setValue(0,6); - getField("RNE").setValue(0,7); - getField("RNE").setValue(0,8); getField("Be").setValue(0,0); getField("Be").setValue(0,1); getField("Be").setValue(0,2); @@ -191,7 +161,7 @@ public class HomeLocation extends UAVDataObject { } // Constants - protected static final int OBJID = 0x5BB3AEFC; + protected static final int OBJID = 0x6185DC6E; protected static final String NAME = "HomeLocation"; protected static String DESCRIPTION = "HomeLocation setting which contains the constants to tranlate from longitutde and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java index 83b7ae7b6..f56982e69 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java @@ -89,31 +89,70 @@ public class HwSettings extends UAVDataObject { CC_FlexiPortEnumOptions.add("ComBridge"); fields.add( new UAVObjectField("CC_FlexiPort", "function", UAVObjectField.FieldType.ENUM, CC_FlexiPortElemNames, CC_FlexiPortEnumOptions) ); - List OP_RcvrPortElemNames = new ArrayList(); - OP_RcvrPortElemNames.add("0"); - List OP_RcvrPortEnumOptions = new ArrayList(); - OP_RcvrPortEnumOptions.add("Disabled"); - OP_RcvrPortEnumOptions.add("PWM"); - OP_RcvrPortEnumOptions.add("PPM"); - OP_RcvrPortEnumOptions.add("DSM2"); - OP_RcvrPortEnumOptions.add("DSMX (10bit)"); - OP_RcvrPortEnumOptions.add("DSMX (11bit)"); - OP_RcvrPortEnumOptions.add("Debug"); - fields.add( new UAVObjectField("OP_RcvrPort", "function", UAVObjectField.FieldType.ENUM, OP_RcvrPortElemNames, OP_RcvrPortEnumOptions) ); + List RV_RcvrPortElemNames = new ArrayList(); + RV_RcvrPortElemNames.add("0"); + List RV_RcvrPortEnumOptions = new ArrayList(); + RV_RcvrPortEnumOptions.add("Disabled"); + RV_RcvrPortEnumOptions.add("PWM"); + RV_RcvrPortEnumOptions.add("PPM"); + RV_RcvrPortEnumOptions.add("PPM+Outputs"); + RV_RcvrPortEnumOptions.add("Outputs"); + fields.add( new UAVObjectField("RV_RcvrPort", "function", UAVObjectField.FieldType.ENUM, RV_RcvrPortElemNames, RV_RcvrPortEnumOptions) ); - List OP_MainPortElemNames = new ArrayList(); - OP_MainPortElemNames.add("0"); - List OP_MainPortEnumOptions = new ArrayList(); - OP_MainPortEnumOptions.add("Disabled"); - OP_MainPortEnumOptions.add("Telemetry"); - fields.add( new UAVObjectField("OP_MainPort", "function", UAVObjectField.FieldType.ENUM, OP_MainPortElemNames, OP_MainPortEnumOptions) ); + List RV_AuxPortElemNames = new ArrayList(); + RV_AuxPortElemNames.add("0"); + List RV_AuxPortEnumOptions = new ArrayList(); + RV_AuxPortEnumOptions.add("Disabled"); + RV_AuxPortEnumOptions.add("Telemetry"); + RV_AuxPortEnumOptions.add("DSM2"); + RV_AuxPortEnumOptions.add("DSMX (10bit)"); + RV_AuxPortEnumOptions.add("DSMX (11bit)"); + RV_AuxPortEnumOptions.add("ComAux"); + RV_AuxPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("RV_AuxPort", "function", UAVObjectField.FieldType.ENUM, RV_AuxPortElemNames, RV_AuxPortEnumOptions) ); - List OP_FlexiPortElemNames = new ArrayList(); - OP_FlexiPortElemNames.add("0"); - List OP_FlexiPortEnumOptions = new ArrayList(); - OP_FlexiPortEnumOptions.add("Disabled"); - OP_FlexiPortEnumOptions.add("GPS"); - fields.add( new UAVObjectField("OP_FlexiPort", "function", UAVObjectField.FieldType.ENUM, OP_FlexiPortElemNames, OP_FlexiPortEnumOptions) ); + List RV_AuxSBusPortElemNames = new ArrayList(); + RV_AuxSBusPortElemNames.add("0"); + List RV_AuxSBusPortEnumOptions = new ArrayList(); + RV_AuxSBusPortEnumOptions.add("Disabled"); + RV_AuxSBusPortEnumOptions.add("S.Bus"); + RV_AuxSBusPortEnumOptions.add("DSM2"); + RV_AuxSBusPortEnumOptions.add("DSMX (10bit)"); + RV_AuxSBusPortEnumOptions.add("DSMX (11bit)"); + RV_AuxSBusPortEnumOptions.add("ComAux"); + RV_AuxSBusPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("RV_AuxSBusPort", "function", UAVObjectField.FieldType.ENUM, RV_AuxSBusPortElemNames, RV_AuxSBusPortEnumOptions) ); + + List RV_FlexiPortElemNames = new ArrayList(); + RV_FlexiPortElemNames.add("0"); + List RV_FlexiPortEnumOptions = new ArrayList(); + RV_FlexiPortEnumOptions.add("Disabled"); + RV_FlexiPortEnumOptions.add("I2C"); + RV_FlexiPortEnumOptions.add("DSM2"); + RV_FlexiPortEnumOptions.add("DSMX (10bit)"); + RV_FlexiPortEnumOptions.add("DSMX (11bit)"); + RV_FlexiPortEnumOptions.add("ComAux"); + RV_FlexiPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("RV_FlexiPort", "function", UAVObjectField.FieldType.ENUM, RV_FlexiPortElemNames, RV_FlexiPortEnumOptions) ); + + List RV_TelemetryPortElemNames = new ArrayList(); + RV_TelemetryPortElemNames.add("0"); + List RV_TelemetryPortEnumOptions = new ArrayList(); + RV_TelemetryPortEnumOptions.add("Disabled"); + RV_TelemetryPortEnumOptions.add("Telemetry"); + RV_TelemetryPortEnumOptions.add("ComAux"); + RV_TelemetryPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("RV_TelemetryPort", "function", UAVObjectField.FieldType.ENUM, RV_TelemetryPortElemNames, RV_TelemetryPortEnumOptions) ); + + List RV_GPSPortElemNames = new ArrayList(); + RV_GPSPortElemNames.add("0"); + List RV_GPSPortEnumOptions = new ArrayList(); + RV_GPSPortEnumOptions.add("Disabled"); + RV_GPSPortEnumOptions.add("Telemetry"); + RV_GPSPortEnumOptions.add("GPS"); + RV_GPSPortEnumOptions.add("ComAux"); + RV_GPSPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("RV_GPSPort", "function", UAVObjectField.FieldType.ENUM, RV_GPSPortElemNames, RV_GPSPortEnumOptions) ); List TelemetrySpeedElemNames = new ArrayList(); TelemetrySpeedElemNames.add("0"); @@ -180,6 +219,7 @@ public class HwSettings extends UAVDataObject { OptionalModulesElemNames.add("ComUsbBridge"); OptionalModulesElemNames.add("Fault"); OptionalModulesElemNames.add("Altitude"); + OptionalModulesElemNames.add("TxPID"); List OptionalModulesEnumOptions = new ArrayList(); OptionalModulesEnumOptions.add("Disabled"); OptionalModulesEnumOptions.add("Enabled"); @@ -237,9 +277,12 @@ public class HwSettings extends UAVDataObject { getField("CC_RcvrPort").setValue("PWM"); getField("CC_MainPort").setValue("Disabled"); getField("CC_FlexiPort").setValue("Disabled"); - getField("OP_RcvrPort").setValue("PWM"); - getField("OP_MainPort").setValue("Telemetry"); - getField("OP_FlexiPort").setValue("GPS"); + getField("RV_RcvrPort").setValue("PWM"); + getField("RV_AuxPort").setValue("Disabled"); + getField("RV_AuxSBusPort").setValue("Disabled"); + getField("RV_FlexiPort").setValue("Disabled"); + getField("RV_TelemetryPort").setValue("Telemetry"); + getField("RV_GPSPort").setValue("GPS"); getField("TelemetrySpeed").setValue("57600"); getField("GPSSpeed").setValue("57600"); getField("ComUsbBridgeSpeed").setValue("57600"); @@ -251,6 +294,7 @@ public class HwSettings extends UAVDataObject { getField("OptionalModules").setValue("Disabled",2); getField("OptionalModules").setValue("Disabled",3); getField("OptionalModules").setValue("Disabled",4); + getField("OptionalModules").setValue("Disabled",5); getField("DSMxBind").setValue(0); } @@ -280,7 +324,7 @@ public class HwSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x2EE6575A; + protected static final int OBJID = 0x4730375C; protected static final String NAME = "HwSettings"; protected static String DESCRIPTION = "Selection of optional hardware configurations."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java index bb846695d..c8f460bc4 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java @@ -181,8 +181,10 @@ public class ManualControlSettings extends UAVDataObject { FlightModePositionEnumOptions.add("Stabilized1"); FlightModePositionEnumOptions.add("Stabilized2"); FlightModePositionEnumOptions.add("Stabilized3"); + FlightModePositionEnumOptions.add("AltitudeHold"); FlightModePositionEnumOptions.add("VelocityControl"); FlightModePositionEnumOptions.add("PositionHold"); + FlightModePositionEnumOptions.add("PathPlanner"); fields.add( new UAVObjectField("FlightModePosition", "", UAVObjectField.FieldType.ENUM, FlightModePositionElemNames, FlightModePositionEnumOptions) ); @@ -317,7 +319,7 @@ public class ManualControlSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x24959BB0; + protected static final int OBJID = 0x59C4551C; protected static final String NAME = "ManualControlSettings"; protected static String DESCRIPTION = "Settings to indicate how to decode receiver input by @ref ManualControlModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java index 106220a8c..80e3b15bf 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java @@ -83,6 +83,14 @@ public class MixerStatus extends UAVDataObject { Mixer8ElemNames.add("0"); fields.add( new UAVObjectField("Mixer8", "", UAVObjectField.FieldType.FLOAT32, Mixer8ElemNames, null) ); + List Mixer9ElemNames = new ArrayList(); + Mixer9ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer9", "", UAVObjectField.FieldType.FLOAT32, Mixer9ElemNames, null) ); + + List Mixer10ElemNames = new ArrayList(); + Mixer10ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer10", "", UAVObjectField.FieldType.FLOAT32, Mixer10ElemNames, null) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -156,7 +164,7 @@ public class MixerStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0x11CFB4E6; + protected static final int OBJID = 0x124E28A; protected static final String NAME = "MixerStatus"; protected static String DESCRIPTION = "Status for the matrix mixer showing the output of each mixer after all scaling"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java index 3b09dd1f8..1629a19d2 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java @@ -53,15 +53,15 @@ public class NedAccel extends UAVDataObject { List NorthElemNames = new ArrayList(); NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "cm/s^2", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); + fields.add( new UAVObjectField("North", "m/s^2", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); List EastElemNames = new ArrayList(); EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "cm/s^2", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); + fields.add( new UAVObjectField("East", "m/s^2", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); List DownElemNames = new ArrayList(); DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "cm/s^2", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); + fields.add( new UAVObjectField("Down", "m/s^2", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); // Compute the number of bytes for this object diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java index ac30ad4f5..184098a16 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java @@ -53,15 +53,15 @@ public class PositionActual extends UAVDataObject { List NorthElemNames = new ArrayList(); NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "cm", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + fields.add( new UAVObjectField("North", "m", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); List EastElemNames = new ArrayList(); EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "cm", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + fields.add( new UAVObjectField("East", "m", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); List DownElemNames = new ArrayList(); DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "cm", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + fields.add( new UAVObjectField("Down", "m", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); // Compute the number of bytes for this object @@ -136,7 +136,7 @@ public class PositionActual extends UAVDataObject { } // Constants - protected static final int OBJID = 0xF9691DA4; + protected static final int OBJID = 0xFA9E2D42; protected static final String NAME = "PositionActual"; protected static String DESCRIPTION = "Contains the current position relative to @ref HomeLocation"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java index 2ff5a5586..123ca58af 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java @@ -53,15 +53,15 @@ public class PositionDesired extends UAVDataObject { List NorthElemNames = new ArrayList(); NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "cm", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + fields.add( new UAVObjectField("North", "m", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); List EastElemNames = new ArrayList(); EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "cm", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + fields.add( new UAVObjectField("East", "m", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); List DownElemNames = new ArrayList(); DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "cm", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + fields.add( new UAVObjectField("Down", "m", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); // Compute the number of bytes for this object @@ -136,7 +136,7 @@ public class PositionDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0x33C9EAB4; + protected static final int OBJID = 0x778DBE24; protected static final String NAME = "PositionDesired"; protected static String DESCRIPTION = "The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner "; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java index 458dd9d10..bc4bf0625 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java @@ -61,6 +61,7 @@ public class SystemAlarms extends UAVDataObject { AlarmElemNames.add("ManualControl"); AlarmElemNames.add("Actuator"); AlarmElemNames.add("Attitude"); + AlarmElemNames.add("Sensors"); AlarmElemNames.add("Stabilization"); AlarmElemNames.add("Guidance"); AlarmElemNames.add("AHRSComms"); @@ -139,6 +140,7 @@ public class SystemAlarms extends UAVDataObject { getField("Alarm").setValue("Uninitialised",14); getField("Alarm").setValue("Uninitialised",15); getField("Alarm").setValue("Uninitialised",16); + getField("Alarm").setValue("Uninitialised",17); } @@ -167,7 +169,7 @@ public class SystemAlarms extends UAVDataObject { } // Constants - protected static final int OBJID = 0x737ADCF2; + protected static final int OBJID = 0x9C7CBFE; protected static final String NAME = "SystemAlarms"; protected static String DESCRIPTION = "Alarms from OpenPilot to indicate failure conditions or warnings. Set by various modules."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java index d1c51d43f..26d01f2a0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java @@ -55,6 +55,18 @@ public class SystemStats extends UAVDataObject { FlightTimeElemNames.add("0"); fields.add( new UAVObjectField("FlightTime", "ms", UAVObjectField.FieldType.UINT32, FlightTimeElemNames, null) ); + List EventSystemWarningIDElemNames = new ArrayList(); + EventSystemWarningIDElemNames.add("0"); + fields.add( new UAVObjectField("EventSystemWarningID", "uavoid", UAVObjectField.FieldType.UINT32, EventSystemWarningIDElemNames, null) ); + + List ObjectManagerCallbackIDElemNames = new ArrayList(); + ObjectManagerCallbackIDElemNames.add("0"); + fields.add( new UAVObjectField("ObjectManagerCallbackID", "uavoid", UAVObjectField.FieldType.UINT32, ObjectManagerCallbackIDElemNames, null) ); + + List ObjectManagerQueueIDElemNames = new ArrayList(); + ObjectManagerQueueIDElemNames.add("0"); + fields.add( new UAVObjectField("ObjectManagerQueueID", "uavoid", UAVObjectField.FieldType.UINT32, ObjectManagerQueueIDElemNames, null) ); + List HeapRemainingElemNames = new ArrayList(); HeapRemainingElemNames.add("0"); fields.add( new UAVObjectField("HeapRemaining", "bytes", UAVObjectField.FieldType.UINT16, HeapRemainingElemNames, null) ); @@ -144,7 +156,7 @@ public class SystemStats extends UAVDataObject { } // Constants - protected static final int OBJID = 0xD610A0F0; + protected static final int OBJID = 0x364D1406; protected static final String NAME = "SystemStats"; protected static String DESCRIPTION = "CPU and memory usage from OpenPilot computer. "; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java index 54825fafe..eefcef6d9 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java @@ -55,36 +55,42 @@ public class TaskInfo extends UAVDataObject { StackRemainingElemNames.add("System"); StackRemainingElemNames.add("Actuator"); StackRemainingElemNames.add("Attitude"); + StackRemainingElemNames.add("Sensors"); StackRemainingElemNames.add("TelemetryTx"); StackRemainingElemNames.add("TelemetryTxPri"); StackRemainingElemNames.add("TelemetryRx"); StackRemainingElemNames.add("GPS"); StackRemainingElemNames.add("ManualControl"); StackRemainingElemNames.add("Altitude"); - StackRemainingElemNames.add("AHRSComms"); StackRemainingElemNames.add("Stabilization"); + StackRemainingElemNames.add("AltitudeHold"); StackRemainingElemNames.add("Guidance"); StackRemainingElemNames.add("FlightPlan"); + StackRemainingElemNames.add("PathPlanner"); StackRemainingElemNames.add("Com2UsbBridge"); StackRemainingElemNames.add("Usb2ComBridge"); + StackRemainingElemNames.add("OveroSync"); fields.add( new UAVObjectField("StackRemaining", "bytes", UAVObjectField.FieldType.UINT16, StackRemainingElemNames, null) ); List RunningElemNames = new ArrayList(); RunningElemNames.add("System"); RunningElemNames.add("Actuator"); RunningElemNames.add("Attitude"); + RunningElemNames.add("Sensors"); RunningElemNames.add("TelemetryTx"); RunningElemNames.add("TelemetryTxPri"); RunningElemNames.add("TelemetryRx"); RunningElemNames.add("GPS"); RunningElemNames.add("ManualControl"); RunningElemNames.add("Altitude"); - RunningElemNames.add("AHRSComms"); RunningElemNames.add("Stabilization"); + RunningElemNames.add("AltitudeHold"); RunningElemNames.add("Guidance"); RunningElemNames.add("FlightPlan"); + RunningElemNames.add("PathPlanner"); RunningElemNames.add("Com2UsbBridge"); RunningElemNames.add("Usb2ComBridge"); + RunningElemNames.add("OveroSync"); List RunningEnumOptions = new ArrayList(); RunningEnumOptions.add("False"); RunningEnumOptions.add("True"); @@ -94,18 +100,21 @@ public class TaskInfo extends UAVDataObject { RunningTimeElemNames.add("System"); RunningTimeElemNames.add("Actuator"); RunningTimeElemNames.add("Attitude"); + RunningTimeElemNames.add("Sensors"); RunningTimeElemNames.add("TelemetryTx"); RunningTimeElemNames.add("TelemetryTxPri"); RunningTimeElemNames.add("TelemetryRx"); RunningTimeElemNames.add("GPS"); RunningTimeElemNames.add("ManualControl"); RunningTimeElemNames.add("Altitude"); - RunningTimeElemNames.add("AHRSComms"); RunningTimeElemNames.add("Stabilization"); + RunningTimeElemNames.add("AltitudeHold"); RunningTimeElemNames.add("Guidance"); RunningTimeElemNames.add("FlightPlan"); + RunningTimeElemNames.add("PathPlanner"); RunningTimeElemNames.add("Com2UsbBridge"); RunningTimeElemNames.add("Usb2ComBridge"); + RunningTimeElemNames.add("OveroSync"); fields.add( new UAVObjectField("RunningTime", "%", UAVObjectField.FieldType.UINT8, RunningTimeElemNames, null) ); @@ -181,7 +190,7 @@ public class TaskInfo extends UAVDataObject { } // Constants - protected static final int OBJID = 0xE34A7C32; + protected static final int OBJID = 0x498F54BA; protected static final String NAME = "TaskInfo"; protected static String DESCRIPTION = "Task information"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java index c2cf64d49..823643130 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java @@ -35,15 +35,15 @@ public class UAVObjectsInitialize { public static void register(UAVObjectManager objMngr) { try { + objMngr.registerObject( new Accels() ); objMngr.registerObject( new AccessoryDesired() ); objMngr.registerObject( new ActuatorCommand() ); objMngr.registerObject( new ActuatorDesired() ); objMngr.registerObject( new ActuatorSettings() ); - objMngr.registerObject( new AHRSCalibration() ); - objMngr.registerObject( new AHRSSettings() ); - objMngr.registerObject( new AhrsStatus() ); + objMngr.registerObject( new AltHoldSmoothed() ); + objMngr.registerObject( new AltitudeHoldDesired() ); + objMngr.registerObject( new AltitudeHoldSettings() ); objMngr.registerObject( new AttitudeActual() ); - objMngr.registerObject( new AttitudeRaw() ); objMngr.registerObject( new AttitudeSettings() ); objMngr.registerObject( new BaroAltitude() ); objMngr.registerObject( new CameraDesired() ); @@ -62,16 +62,23 @@ public class UAVObjectsInitialize { objMngr.registerObject( new GPSPosition() ); objMngr.registerObject( new GPSSatellites() ); objMngr.registerObject( new GPSTime() ); + objMngr.registerObject( new GPSVelocity() ); + objMngr.registerObject( new Gyros() ); + objMngr.registerObject( new GyrosBias() ); objMngr.registerObject( new GuidanceSettings() ); objMngr.registerObject( new HomeLocation() ); objMngr.registerObject( new HwSettings() ); objMngr.registerObject( new I2CStats() ); + objMngr.registerObject( new GPSPosition() ); + objMngr.registerObject( new Magnetometer() ); objMngr.registerObject( new ManualControlCommand() ); objMngr.registerObject( new ManualControlSettings() ); objMngr.registerObject( new MixerSettings() ); objMngr.registerObject( new MixerStatus() ); + objMngr.registerObject( new NEDPosition() ); objMngr.registerObject( new NedAccel() ); objMngr.registerObject( new ObjectPersistence() ); + objMngr.registerObject( new PathDesired() ); objMngr.registerObject( new PositionActual() ); objMngr.registerObject( new PositionDesired() ); objMngr.registerObject( new RateDesired() ); @@ -82,10 +89,13 @@ public class UAVObjectsInitialize { objMngr.registerObject( new SystemAlarms() ); objMngr.registerObject( new SystemSettings() ); objMngr.registerObject( new SystemStats() ); + objMngr.registerObject( new TxPIDSettings() ); objMngr.registerObject( new TaskInfo() ); objMngr.registerObject( new VelocityActual() ); objMngr.registerObject( new VelocityDesired() ); objMngr.registerObject( new WatchdogStatus() ); + objMngr.registerObject( new Waypoint() ); + objMngr.registerObject( new WaypointActive() ); } catch (Exception e) { e.printStackTrace(); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java index 97d038cfe..2a8cd3754 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java @@ -53,15 +53,15 @@ public class VelocityActual extends UAVDataObject { List NorthElemNames = new ArrayList(); NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "cm/s", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + fields.add( new UAVObjectField("North", "m/s", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); List EastElemNames = new ArrayList(); EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "cm/s", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + fields.add( new UAVObjectField("East", "m/s", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); List DownElemNames = new ArrayList(); DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "cm/s", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + fields.add( new UAVObjectField("Down", "m/s", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); // Compute the number of bytes for this object @@ -136,7 +136,7 @@ public class VelocityActual extends UAVDataObject { } // Constants - protected static final int OBJID = 0x43007EB0; + protected static final int OBJID = 0x5A08F61A; protected static final String NAME = "VelocityActual"; protected static String DESCRIPTION = "Updated by @ref AHRSCommsModule and used within @ref GuidanceModule for velocity control"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java index f39fbd6de..436ef6448 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java @@ -53,15 +53,15 @@ public class VelocityDesired extends UAVDataObject { List NorthElemNames = new ArrayList(); NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "cm/s", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + fields.add( new UAVObjectField("North", "m/s", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); List EastElemNames = new ArrayList(); EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "cm/s", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + fields.add( new UAVObjectField("East", "m/s", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); List DownElemNames = new ArrayList(); DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "cm/s", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + fields.add( new UAVObjectField("Down", "m/s", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); // Compute the number of bytes for this object @@ -136,7 +136,7 @@ public class VelocityDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0x25139D1A; + protected static final int OBJID = 0x9E946992; protected static final String NAME = "VelocityDesired"; protected static String DESCRIPTION = "Used within @ref GuidanceModule to communicate between the task computing the desired velocity and the PID loop to achieve it (running at different rates)."; protected static final boolean ISSINGLEINST = 1 == 1; From 02f9452193da60e0b1bc82883775bd8218170417 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 16:12:45 -0500 Subject: [PATCH 057/284] Update fake telemetry object --- .../org/openpilot/androidgcs/OPTelemetryService.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index bc711560d..074049d79 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -222,18 +222,6 @@ public class OPTelemetryService extends Service { homeLocation.getField("Latitude").setDouble(379420315); homeLocation.getField("Longitude").setDouble(-88330078); - homeLocation.getField("ECEF").setDouble(497665694,0); - homeLocation.getField("ECEF").setDouble(-77336320,1); - homeLocation.getField("ECEF").setDouble(390037169,2); - homeLocation.getField("RNE").setDouble(-0.60757166,0); - homeLocation.getField("RNE").setDouble(0.09441550,1); - homeLocation.getField("RNE").setDouble(0.78863323,2); - homeLocation.getField("RNE").setDouble(0.15355512,3); - homeLocation.getField("RNE").setDouble(0.98814011,4); - homeLocation.getField("RNE").setDouble(0,5); - homeLocation.getField("RNE").setDouble(-0.77928013,6); - homeLocation.getField("RNE").setDouble(0.12109867,7); - homeLocation.getField("RNE").setDouble(-0.61486387,8); homeLocation.getField("Be").setDouble(26702.78710938,0); homeLocation.getField("Be").setDouble(-1468.33605957,1); homeLocation.getField("Be").setDouble(34181.78515625,2); From 574c2000b66831df0a5b01d59ca559814e26eaaa Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 16:38:49 -0500 Subject: [PATCH 058/284] Lower all the debugging levels again --- .../org/openpilot/androidgcs/OPTelemetryService.java | 2 +- androidgcs/src/org/openpilot/uavtalk/Telemetry.java | 2 +- .../src/org/openpilot/uavtalk/TelemetryMonitor.java | 10 ++++++++-- androidgcs/src/org/openpilot/uavtalk/UAVTalk.java | 10 ++++------ 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 074049d79..1a4b61eb8 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -33,7 +33,7 @@ public class OPTelemetryService extends Service { // Logging settings private final String TAG = "OPTelemetryService"; - public static int LOGLEVEL = 2; + public static int LOGLEVEL = 0; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 11e6cb2ca..1395a5c08 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -17,7 +17,7 @@ import android.util.Log; public class Telemetry { private final String TAG = "Telemetry"; - public static int LOGLEVEL = 2; + public static int LOGLEVEL = 0; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index 903b6b29f..87a0cdc70 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -13,7 +13,7 @@ import android.util.Log; public class TelemetryMonitor extends Observable{ private static final String TAG = "TelemetryMonitor"; - public static int LOGLEVEL = 2; + public static int LOGLEVEL = 0; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; @@ -204,6 +204,8 @@ public class TelemetryMonitor extends Observable{ Telemetry.TelemetryStats telStats = tel.getStats(); tel.resetStats(); + if (DEBUG) Log.d(TAG, "processStatsUpdates() - stats reset"); + // Update stats object gcsStatsObj.getField("RxDataRate").setDouble( (float)telStats.rxBytes / ((float)currentPeriod/1000.0) ); gcsStatsObj.getField("TxDataRate").setDouble( (float)telStats.txBytes / ((float)currentPeriod/1000.0) ); @@ -214,6 +216,8 @@ public class TelemetryMonitor extends Observable{ field = gcsStatsObj.getField("TxRetries"); field.setDouble(field.getDouble() + telStats.txRetries); + if (DEBUG) Log.d(TAG, "processStatsUpdates() - stats updated"); + // Check for a connection timeout boolean connectionTimeout; if ( telStats.rxObjects > 0 ) @@ -296,8 +300,10 @@ public class TelemetryMonitor extends Observable{ objects_updated = false; setChanged(); } + + if (DEBUG) Log.d(TAG, "processStatsUpdates() - before notify"); notifyObservers(); - + if (DEBUG) Log.d(TAG, "processStatsUpdates() - after notify"); } private void setPeriod(int ms) { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 5a3a9a1a5..9cdd11ccb 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -12,7 +12,7 @@ import android.util.Log; public class UAVTalk extends Observable { static final String TAG = "UAVTalk"; - public static int LOGLEVEL = 2; + public static int LOGLEVEL = 0; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; @@ -504,8 +504,7 @@ public class UAVTalk extends Observable { case TYPE_OBJ_ACK: // All instances, not allowed for OBJ_ACK messages if (!allInstances) { - System.out.println("Received object ack: " + objId + " " + - objMngr.getObject(objId).getName()); + if (DEBUG) Log.d(TAG,"Received object ack: " + objId + " " + objMngr.getObject(objId).getName()); // Get object and update its data obj = updateObject(objId, instId, data); // Transmit ACK @@ -521,7 +520,7 @@ public class UAVTalk extends Observable { case TYPE_OBJ_REQ: // Get object, if all instances are requested get instance 0 of the // object - System.out.println("Received object request: " + objId + " " + + if (DEBUG) Log.d(TAG,"Received object request: " + objId + " " + objMngr.getObject(objId).getName()); if (allInstances) { obj = objMngr.getObject(objId); @@ -538,8 +537,7 @@ public class UAVTalk extends Observable { case TYPE_ACK: // All instances, not allowed for ACK messages if (!allInstances) { - System.out.println("Received ack: " + objId + " " + - objMngr.getObject(objId).getName()); + if (DEBUG) Log.d(TAG,"Received ack: " + objId + " " + objMngr.getObject(objId).getName()); // Get object obj = objMngr.getObject(objId, instId); // Check if an ack is pending From 1a63c21be904ece1baea2bd9054b0274133d938b Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 2 Aug 2012 11:04:35 -0500 Subject: [PATCH 059/284] First step to fixing metat data representation for android --- .../org/openpilot/uavtalk/UAVMetaObject.java | 46 ++++-------- .../src/org/openpilot/uavtalk/UAVObject.java | 70 +++++++------------ .../org/openpilot/uavtalk/UAVObjectField.java | 48 ++++++++++++- 3 files changed, 85 insertions(+), 79 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java index 7aab176ef..c57b6c2fe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java @@ -13,43 +13,25 @@ public class UAVMetaObject extends UAVObject { ownMetadata = new Metadata(); - ownMetadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - ownMetadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - ownMetadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - ownMetadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - ownMetadata.flightTelemetryUpdatePeriod = 0; - ownMetadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - ownMetadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + ownMetadata.flags = 0; // TODO: Fix flags ownMetadata.gcsTelemetryUpdatePeriod = 0; - ownMetadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; ownMetadata.loggingUpdatePeriod = 0; - // Setup fields - List boolEnum = new ArrayList(); - boolEnum.add("False"); - boolEnum.add("True"); - List updateModeEnum = new ArrayList(); - updateModeEnum.add("Periodic"); - updateModeEnum.add("On Change"); - updateModeEnum.add("Manual"); - updateModeEnum.add("Never"); + List modesBitField = new ArrayList(); + modesBitField.add("FlightReadOnly"); + modesBitField.add("GCSReadOnly"); + modesBitField.add("FlightTelemetryAcked"); + modesBitField.add("GCSTelemetryAcked"); + modesBitField.add("FlightUpdatePeriodic"); + modesBitField.add("FlightUpdateOnChange"); + modesBitField.add("GCSUpdatePeriodic"); + modesBitField.add("GCSUpdateOnChange"); - List accessModeEnum = new ArrayList(); - accessModeEnum.add("Read/Write"); - accessModeEnum.add("Read Only"); - - List fields = new ArrayList(); - fields.add( new UAVObjectField("Flight Access Mode", "", UAVObjectField.FieldType.ENUM, 1, accessModeEnum) ); - fields.add( new UAVObjectField("GCS Access Mode", "", UAVObjectField.FieldType.ENUM, 1, accessModeEnum) ); - fields.add( new UAVObjectField("Flight Telemetry Acked", "", UAVObjectField.FieldType.ENUM, 1, boolEnum) ); - fields.add( new UAVObjectField("Flight Telemetry Update Mode", "", UAVObjectField.FieldType.ENUM, 1, updateModeEnum) ); - fields.add( new UAVObjectField("Flight Telemetry Update Period", "", UAVObjectField.FieldType.UINT32, 1, null) ); - fields.add( new UAVObjectField("GCS Telemetry Acked", "", UAVObjectField.FieldType.ENUM, 1, boolEnum) ); - fields.add( new UAVObjectField("GCS Telemetry Update Mode", "", UAVObjectField.FieldType.ENUM, 1, updateModeEnum) ); - fields.add( new UAVObjectField("GCS Telemetry Update Period", "", UAVObjectField.FieldType.UINT32, 1, null ) ); - fields.add( new UAVObjectField("Logging Update Mode", "", UAVObjectField.FieldType.ENUM, 1, updateModeEnum) ); - fields.add( new UAVObjectField("Logging Update Period", "", UAVObjectField.FieldType.UINT32, 1, null ) ); + fields.add( new UAVObjectField("Modes", "", UAVObjectField.FieldType.BITFIELD, 1, modesBitField) ); + fields.add( new UAVObjectField("Flight Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); + fields.add( new UAVObjectField("GCS Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); + fields.add( new UAVObjectField("Logging Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); int numBytes = 0; ListIterator li = fields.listIterator(); diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 940b076a5..20d4cb02a 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -120,17 +120,10 @@ public abstract class UAVObject { * Object update mode */ public enum UpdateMode { - UPDATEMODE_PERIODIC, /** - * Automatically update object at periodic - * intervals - */ + UPDATEMODE_MANUAL, /** Manually update object, by calling the updated() function */ + UPDATEMODE_PERIODIC, /** Automatically update object at periodic intervals */ UPDATEMODE_ONCHANGE, /** Only update object when its data changes */ - UPDATEMODE_MANUAL, /** - * Manually update object, by calling the updated() - * function - */ - UPDATEMODE_NEVER - /** Object is never updated */ + UPDATEMODE_THROTTLED /** Object is updated on change, but not more often than the interval time */ }; /** @@ -140,47 +133,32 @@ public abstract class UAVObject { ACCESS_READWRITE, ACCESS_READONLY }; - /** - * Access mode - */ - public enum Acked { - FALSE, TRUE - }; - public final class Metadata { - public AccessMode flightAccess; /** - * Defines the access level for the local flight transactions (readonly - * and readwrite) + * Object metadata, each object has a meta object that holds its metadata. The metadata define + * properties for each object and can be used by multiple modules (e.g. telemetry and logger) + * + * The object metadata flags are packed into a single 16 bit integer. + * The bits in the flag field are defined as: + * + * Bit(s) Name Meaning + * ------ ---- ------- + * 0 access Defines the access level for the local transactions (readonly=0 and readwrite=1) + * 1 gcsAccess Defines the access level for the local GCS transactions (readonly=0 and readwrite=1), not used in the flight s/w + * 2 telemetryAcked Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) + * 3 gcsTelemetryAcked Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) + * 4-5 telemetryUpdateMode Update mode used by the telemetry module (UAVObjUpdateMode) + * 6-7 gcsTelemetryUpdateMode Update mode used by the GCS (UAVObjUpdateMode) */ - public AccessMode gcsAccess; - /** - * Defines the access level for the local GCS transactions (readonly and - * readwrite) - */ - public Acked flightTelemetryAcked; - /** - * Defines if an ack is required for the transactions of this object - * (1:acked, 0:not acked) - */ - public UpdateMode flightTelemetryUpdateMode; - /** Update mode used by the autopilot (UpdateMode) */ + public int flags; /** Defines flags for update and logging modes and whether an update should be ACK'd (bits defined above) */ + + /** Update period used by the telemetry module (only if telemetry mode is PERIODIC) */ public int flightTelemetryUpdatePeriod; - /** - * Update period used by the autopilot (only if telemetry mode is - * PERIODIC) - */ - public Acked gcsTelemetryAcked; - /** - * Defines if an ack is required for the transactions of this object - * (1:acked, 0:not acked) - */ - public UpdateMode gcsTelemetryUpdateMode; - /** Update mode used by the GCS (UpdateMode) */ - public int gcsTelemetryUpdatePeriod; + + /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ + public int gcsTelemetryUpdatePeriod; + /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ - public UpdateMode loggingUpdateMode; - /** Update mode used by the logging module (UpdateMode) */ public int loggingUpdatePeriod; /** * Update period used by the logging module (only if logging mode is diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 286859e63..c2965f6cc 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -7,7 +7,7 @@ import java.util.List; public class UAVObjectField { - public enum FieldType { INT8, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, STRING }; + public enum FieldType { INT8, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, BITFIELD, STRING }; public UAVObjectField(String name, String units, FieldType type, int numElements, List options) { List elementNames = new ArrayList(); @@ -56,6 +56,8 @@ public class UAVObjectField { return "float32"; case ENUM: return "enum"; + case BITFIELD: + return "bitfield"; case STRING: return "string"; default: @@ -144,6 +146,11 @@ public class UAVObjectField { for (int index = 0; index < numElements; ++index) dataOut.put((Byte) l.get(index)); break; + case BITFIELD: + for (int index = 0; index < numElements; ++index) { + Integer val = (Integer) getValue(index); + dataOut.put(val.byteValue()); + } case STRING: // TODO: Implement strings throw new Error("Strings not yet implemented"); @@ -224,6 +231,16 @@ public class UAVObjectField { } break; } + case BITFIELD: + { + List l = (List) this.data; + for (int index = 0 ; index < numElements; ++index) { + int signedval = (int) dataIn.get(); // this sign extends it + int unsignedval = signedval & 0xff; // drop sign extension + l.set(index, (short) unsignedval); + } + break; + } case ENUM: { List l = (List) this.data; @@ -275,6 +292,9 @@ public class UAVObjectField { return options.get(val); } + case BITFIELD: + return ((List) data).get(index).intValue(); + case STRING: { //throw new Exception("Shit I should do this"); @@ -354,6 +374,12 @@ public class UAVObjectField { l.set(index, val); break; } + case BITFIELD: + { + List l = (List) this.data; + l.set(index, bound(data).shortValue()); + break; + } case STRING: { //throw new Exception("Sorry I haven't implemented strings yet"); @@ -404,6 +430,8 @@ public class UAVObjectField { return true; case ENUM: return false; + case BITFIELD: + return true; case STRING: return false; default: @@ -430,6 +458,8 @@ public class UAVObjectField { return false; case ENUM: return true; + case BITFIELD: + return false; case STRING: return true; default: @@ -493,6 +523,12 @@ public class UAVObjectField { ((ArrayList) data).add((float) 0); } break; + case BITFIELD: + ((ArrayList) data).clear(); + for(int index = 0; index < numElements; ++index) { + ((ArrayList) data).add((short) 0); + } + break; case ENUM: ((ArrayList) data).clear(); for(int index = 0; index < numElements; ++index) { @@ -549,6 +585,10 @@ public class UAVObjectField { data = (Object) new ArrayList(this.numElements); numBytesPerElement = 1; break; + case BITFIELD: + data = (Object) new ArrayList(this.numElements); + numBytesPerElement = 1; + break; case STRING: data = (Object) new ArrayList(this.numElements); numBytesPerElement = 1; @@ -614,6 +654,12 @@ public class UAVObjectField { if(num > 4294967295L) return 4294967295L; return num; + case BITFIELD: + if(num < 0) + return (long) 0; + if(num > 255) + return (long) 255; + return num; } return num; From 62bb4601c5876b2e0c5aeeb78a30f4c503ea13fd Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 2 Aug 2012 12:49:34 -0500 Subject: [PATCH 060/284] Finish porting the meta data changes from GCS and update all the UAVOs --- .../src/org/openpilot/uavtalk/Telemetry.java | 29 +- .../openpilot/uavtalk/TelemetryMonitor.java | 37 ++- .../src/org/openpilot/uavtalk/UAVObject.java | 194 +++++++++++- .../org/openpilot/uavtalk/UAVObjectField.java | 2 +- .../uavtalk/uavobjects/AccessoryDesired.java | 23 +- .../uavtalk/uavobjects/ActuatorCommand.java | 23 +- .../uavtalk/uavobjects/ActuatorDesired.java | 23 +- .../uavtalk/uavobjects/ActuatorSettings.java | 280 +----------------- .../uavtalk/uavobjects/AttitudeActual.java | 23 +- .../uavtalk/uavobjects/AttitudeSettings.java | 23 +- .../uavtalk/uavobjects/BaroAltitude.java | 23 +- .../uavtalk/uavobjects/CameraDesired.java | 23 +- .../uavobjects/CameraStabSettings.java | 23 +- .../uavtalk/uavobjects/FaultSettings.java | 23 +- .../uavtalk/uavobjects/FirmwareIAPObj.java | 23 +- .../uavobjects/FlightBatterySettings.java | 36 ++- .../uavobjects/FlightBatteryState.java | 30 +- .../uavtalk/uavobjects/FlightPlanControl.java | 23 +- .../uavobjects/FlightPlanSettings.java | 23 +- .../uavtalk/uavobjects/FlightPlanStatus.java | 23 +- .../uavtalk/uavobjects/FlightStatus.java | 26 +- .../uavobjects/FlightTelemetryStats.java | 23 +- .../uavtalk/uavobjects/GCSReceiver.java | 27 +- .../uavtalk/uavobjects/GCSTelemetryStats.java | 23 +- .../uavtalk/uavobjects/GPSPosition.java | 23 +- .../uavtalk/uavobjects/GPSSatellites.java | 23 +- .../openpilot/uavtalk/uavobjects/GPSTime.java | 23 +- .../uavtalk/uavobjects/GuidanceSettings.java | 211 ------------- .../uavtalk/uavobjects/HomeLocation.java | 23 +- .../uavtalk/uavobjects/HwSettings.java | 44 +-- .../uavtalk/uavobjects/I2CStats.java | 23 +- .../uavobjects/ManualControlCommand.java | 23 +- .../uavobjects/ManualControlSettings.java | 48 ++- .../uavtalk/uavobjects/MixerSettings.java | 23 +- .../uavtalk/uavobjects/MixerStatus.java | 23 +- .../uavtalk/uavobjects/NedAccel.java | 23 +- .../uavtalk/uavobjects/ObjectPersistence.java | 26 +- .../uavtalk/uavobjects/PositionActual.java | 23 +- .../uavtalk/uavobjects/PositionDesired.java | 147 --------- .../uavtalk/uavobjects/RateDesired.java | 23 +- .../uavtalk/uavobjects/ReceiverActivity.java | 23 +- .../uavtalk/uavobjects/SonarAltitude.java | 23 +- .../uavobjects/StabilizationDesired.java | 26 +- .../uavobjects/StabilizationSettings.java | 78 ++++- .../uavtalk/uavobjects/SystemAlarms.java | 29 +- .../uavtalk/uavobjects/SystemSettings.java | 34 ++- .../uavtalk/uavobjects/SystemStats.java | 23 +- .../uavtalk/uavobjects/TaskInfo.java | 40 +-- .../uavobjects/UAVObjectsInitialize.java | 21 +- .../uavtalk/uavobjects/VelocityActual.java | 23 +- .../uavtalk/uavobjects/VelocityDesired.java | 23 +- .../uavtalk/uavobjects/WatchdogStatus.java | 23 +- .../templates/uavobjecttemplate.java | 23 +- 53 files changed, 880 insertions(+), 1244 deletions(-) delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 1395a5c08..2ee5ab9a4 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -10,8 +10,6 @@ import java.util.Queue; import java.util.Timer; import java.util.TimerTask; -import org.openpilot.uavtalk.UAVObject.Acked; - import android.util.Log; public class Telemetry { @@ -20,7 +18,7 @@ public class Telemetry { public static int LOGLEVEL = 0; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; - + public class TelemetryStats { public int txBytes; public int rxBytes; @@ -50,7 +48,7 @@ public class Telemetry { boolean allInstances; boolean objRequest; int retriesRemaining; - Acked acked; + boolean acked; } ; /** @@ -249,7 +247,7 @@ public class Telemetry { // Setup object depending on update mode int eventMask; - if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_PERIODIC ) + if ( metadata.GetGcsTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_PERIODIC ) { // Set update period setUpdatePeriod(obj, metadata.gcsTelemetryUpdatePeriod); @@ -260,7 +258,7 @@ public class Telemetry { connectToObjectInstances(obj, eventMask); } - else if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE ) + else if ( metadata.GetGcsTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE ) { // Set update period setUpdatePeriod(obj, 0); @@ -271,7 +269,11 @@ public class Telemetry { connectToObjectInstances(obj, eventMask); } - else if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_MANUAL ) + else if ( metadata.GetGcsTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_THROTTLED ) + { + // TODO + } + else if ( metadata.GetGcsTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_MANUAL ) { // Set update period setUpdatePeriod(obj, 0); @@ -282,13 +284,6 @@ public class Telemetry { connectToObjectInstances(obj, eventMask); } - else if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_NEVER ) - { - // Set update period - setUpdatePeriod(obj, 0); - // Disconnect from object - connectToObjectInstances(obj, 0); - } } /** @@ -360,10 +355,10 @@ public class Telemetry { } else { - utalk.sendObject(transInfo.obj, transInfo.acked == Acked.TRUE, transInfo.allInstances); + utalk.sendObject(transInfo.obj, transInfo.acked, transInfo.allInstances); } // Start timer if a response is expected - if ( transInfo.objRequest || transInfo.acked == Acked.TRUE ) + if ( transInfo.objRequest || transInfo.acked ) { transTimerSetPeriod(REQ_TIMEOUT_MS); } @@ -476,7 +471,7 @@ public class Telemetry { transInfo.obj = objInfo.obj; transInfo.allInstances = objInfo.allInstances; transInfo.retriesRemaining = MAX_RETRIES; - transInfo.acked = metadata.gcsTelemetryAcked; + transInfo.acked = metadata.GetGcsTelemetryAcked(); if ( objInfo.event == EV_UPDATED || objInfo.event == EV_UPDATED_MANUAL ) { transInfo.objRequest = false; diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index 87a0cdc70..d1d7a9c44 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -76,27 +76,24 @@ public class TelemetryMonitor extends Observable{ List instList = objListIterator.next(); UAVObject obj = instList.get(0); UAVObject.Metadata mdata = obj.getMetadata(); - if ( mdata.gcsTelemetryUpdateMode != UAVObject.UpdateMode.UPDATEMODE_NEVER ) + if ( obj.isMetadata() ) { - if ( obj.isMetadata() ) - { - queue.add(obj); - } - else /* Data object */ - { - UAVDataObject dobj = (UAVDataObject) obj; - if ( dobj.isSettings() ) - { - queue.add(obj); - } - else - { - if ( mdata.flightTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE ) - { - queue.add(obj); - } - } - } + queue.add(obj); + } + else /* Data object */ + { + UAVDataObject dobj = (UAVDataObject) obj; + if ( dobj.isSettings() ) + { + queue.add(obj); + } + else + { + if ( mdata.GetFlightTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE ) + { + queue.add(obj); + } + } } } // Start retrieving diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 20d4cb02a..28c279040 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -133,7 +133,15 @@ public abstract class UAVObject { ACCESS_READWRITE, ACCESS_READONLY }; - public final class Metadata { + public final static int UAVOBJ_ACCESS_SHIFT = 0; + public final static int UAVOBJ_GCS_ACCESS_SHIFT = 1; + public final static int UAVOBJ_TELEMETRY_ACKED_SHIFT = 2; + public final static int UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT = 3; + public final static int UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT = 4; + public final static int UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT = 6; + public final static int UAVOBJ_UPDATE_MODE_MASK = 0x3; + + public final static class Metadata { /** * Object metadata, each object has a meta object that holds its metadata. The metadata define * properties for each object and can be used by multiple modules (e.g. telemetry and logger) @@ -164,6 +172,190 @@ public abstract class UAVObject { * Update period used by the logging module (only if logging mode is * PERIODIC) */ + + /** + * @brief Helper method for metadata accessors + * @param var The starting value + * @param shift The offset of these bits + * @param value The new value + * @param mask The mask of these bits + * @return + */ + private void SET_BITS(int shift, int value, int mask) { + this.flags = (this.flags & ~(mask << shift)) | (value << shift); + } + + /** + * Get the UAVObject metadata access member + * \return the access type + */ + public AccessMode GetFlightAccess() + { + return AccessModeEnum((this.flags >> UAVOBJ_ACCESS_SHIFT) & 1); + } + + /** + * Set the UAVObject metadata access member + * \param[in] mode The access mode + */ + public void SetFlightAccess(Metadata metadata, AccessMode mode) + { + // Need to convert java enums which have no numeric value to bits + SET_BITS(UAVOBJ_ACCESS_SHIFT, AccessModeNum(mode), 1); + } + + /** + * Get the UAVObject metadata GCS access member + * \return the GCS access type + */ + public AccessMode GetGcsAccess() + { + return AccessModeEnum((this.flags >> UAVOBJ_GCS_ACCESS_SHIFT) & 1); + } + + /** + * Set the UAVObject metadata GCS access member + * \param[in] mode The access mode + */ + public void SetGcsAccess(Metadata metadata, AccessMode mode) { + // Need to convert java enums which have no numeric value to bits + SET_BITS(UAVOBJ_GCS_ACCESS_SHIFT, AccessModeNum(mode), 1); + } + + /** + * Get the UAVObject metadata telemetry acked member + * \return the telemetry acked boolean + */ + public boolean GetFlightTelemetryAcked() { + return (((this.flags >> UAVOBJ_TELEMETRY_ACKED_SHIFT) & 1) == 1); + } + + /** + * Set the UAVObject metadata telemetry acked member + * \param[in] val The telemetry acked boolean + */ + public void SetFlightTelemetryAcked(boolean val) { + SET_BITS(UAVOBJ_TELEMETRY_ACKED_SHIFT, val ? 1 : 0, 1); + } + + /** + * Get the UAVObject metadata GCS telemetry acked member + * \return the telemetry acked boolean + */ + public boolean GetGcsTelemetryAcked() { + return ((this.flags >> UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT) & 1) == 1; + } + + /** + * Set the UAVObject metadata GCS telemetry acked member + * \param[in] val The GCS telemetry acked boolean + */ + public void SetGcsTelemetryAcked(boolean val) { + SET_BITS(UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT, val ? 1 : 0, 1); + } + + /** + * Maps from the bitfield number to the symbolic java enumeration + * @param num The value in the bitfield after shifting + * @return The update mode + */ + public static AccessMode AccessModeEnum(int num) { + switch(num) { + case 0: + return AccessMode.ACCESS_READONLY; + case 1: + return AccessMode.ACCESS_READWRITE; + } + return AccessMode.ACCESS_READONLY; + } + + /** + * Maps from the java symbolic enumeration of update mode to the bitfield value + * @param e The update mode + * @return The numeric value to use on the wire + */ + public static int AccessModeNum(AccessMode e) { + switch(e) { + case ACCESS_READONLY: + return 0; + case ACCESS_READWRITE: + return 1; + } + return 0; + } + + /** + * Maps from the bitfield number to the symbolic java enumeration + * @param num The value in the bitfield after shifting + * @return The update mode + */ + public static UpdateMode UpdateModeEnum(int num) { + switch(num) { + case 0: + return UpdateMode.UPDATEMODE_MANUAL; + case 1: + return UpdateMode.UPDATEMODE_PERIODIC; + case 2: + return UpdateMode.UPDATEMODE_ONCHANGE; + default: + return UpdateMode.UPDATEMODE_THROTTLED; + } + } + + /** + * Maps from the java symbolic enumeration of update mode to the bitfield value + * @param e The update mode + * @return The numeric value to use on the wire + */ + public static int UpdateModeNum(UpdateMode e) { + switch(e) { + case UPDATEMODE_MANUAL: + return 0; + case UPDATEMODE_PERIODIC: + return 1; + case UPDATEMODE_ONCHANGE: + return 2; + case UPDATEMODE_THROTTLED: + return 3; + } + return 0; + } + + /** + * Get the UAVObject metadata telemetry update mode + * \return the telemetry update mode + */ + public UpdateMode GetFlightTelemetryUpdateMode() { + return UpdateModeEnum((this.flags >> UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT) & UAVOBJ_UPDATE_MODE_MASK); + } + + /** + * Set the UAVObject metadata telemetry update mode member + * \param[in] metadata The metadata object + * \param[in] val The telemetry update mode + */ + public void SetFlightTelemetryUpdateMode(UpdateMode val) { + SET_BITS(UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT, UpdateModeNum(val), UAVOBJ_UPDATE_MODE_MASK); + } + + /** + * Get the UAVObject metadata GCS telemetry update mode + * \param[in] metadata The metadata object + * \return the GCS telemetry update mode + */ + public UpdateMode GetGcsTelemetryUpdateMode() { + return UpdateModeEnum((this.flags >> UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT) & UAVOBJ_UPDATE_MODE_MASK); + } + + /** + * Set the UAVObject metadata GCS telemetry update mode member + * \param[in] metadata The metadata object + * \param[in] val The GCS telemetry update mode + */ + public void SetGcsTelemetryUpdateMode(UpdateMode val) { + SET_BITS(UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT, UpdateModeNum(val), UAVOBJ_UPDATE_MODE_MASK); + } + }; public UAVObject(int objID, Boolean isSingleInst, String name) { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index c2965f6cc..3ed221079 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -314,7 +314,7 @@ public class UAVObjectField { // Get metadata UAVObject.Metadata mdata = obj.getMetadata(); // Update value if the access mode permits - if ( mdata.gcsAccess == UAVObject.AccessMode.ACCESS_READWRITE ) + if ( mdata.GetGcsAccess() == UAVObject.AccessMode.ACCESS_READWRITE ) { switch (type) { diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java index 13c63dfdd..4b7c875a7 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java @@ -78,18 +78,17 @@ public class AccessoryDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java index 08f2ebefe..0120e0ce7 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java @@ -99,18 +99,17 @@ public class ActuatorCommand extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java index 03ff1985c..a00517906 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java @@ -98,18 +98,17 @@ public class ActuatorDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java index 71b0bb49f..2257da346 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java @@ -97,246 +97,6 @@ public class ActuatorSettings extends UAVDataObject { ChannelMinElemNames.add("9"); fields.add( new UAVObjectField("ChannelMin", "us", UAVObjectField.FieldType.INT16, ChannelMinElemNames, null) ); - List FixedWingRoll1ElemNames = new ArrayList(); - FixedWingRoll1ElemNames.add("0"); - List FixedWingRoll1EnumOptions = new ArrayList(); - FixedWingRoll1EnumOptions.add("Channel1"); - FixedWingRoll1EnumOptions.add("Channel2"); - FixedWingRoll1EnumOptions.add("Channel3"); - FixedWingRoll1EnumOptions.add("Channel4"); - FixedWingRoll1EnumOptions.add("Channel5"); - FixedWingRoll1EnumOptions.add("Channel6"); - FixedWingRoll1EnumOptions.add("Channel7"); - FixedWingRoll1EnumOptions.add("Channel8"); - FixedWingRoll1EnumOptions.add("Channel9"); - FixedWingRoll1EnumOptions.add("Channel10"); - FixedWingRoll1EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingRoll1", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll1ElemNames, FixedWingRoll1EnumOptions) ); - - List FixedWingRoll2ElemNames = new ArrayList(); - FixedWingRoll2ElemNames.add("0"); - List FixedWingRoll2EnumOptions = new ArrayList(); - FixedWingRoll2EnumOptions.add("Channel1"); - FixedWingRoll2EnumOptions.add("Channel2"); - FixedWingRoll2EnumOptions.add("Channel3"); - FixedWingRoll2EnumOptions.add("Channel4"); - FixedWingRoll2EnumOptions.add("Channel5"); - FixedWingRoll2EnumOptions.add("Channel6"); - FixedWingRoll2EnumOptions.add("Channel7"); - FixedWingRoll2EnumOptions.add("Channel8"); - FixedWingRoll2EnumOptions.add("Channel9"); - FixedWingRoll2EnumOptions.add("Channel10"); - FixedWingRoll2EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingRoll2", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll2ElemNames, FixedWingRoll2EnumOptions) ); - - List FixedWingPitch1ElemNames = new ArrayList(); - FixedWingPitch1ElemNames.add("0"); - List FixedWingPitch1EnumOptions = new ArrayList(); - FixedWingPitch1EnumOptions.add("Channel1"); - FixedWingPitch1EnumOptions.add("Channel2"); - FixedWingPitch1EnumOptions.add("Channel3"); - FixedWingPitch1EnumOptions.add("Channel4"); - FixedWingPitch1EnumOptions.add("Channel5"); - FixedWingPitch1EnumOptions.add("Channel6"); - FixedWingPitch1EnumOptions.add("Channel7"); - FixedWingPitch1EnumOptions.add("Channel8"); - FixedWingPitch1EnumOptions.add("Channel9"); - FixedWingPitch1EnumOptions.add("Channel10"); - FixedWingPitch1EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingPitch1", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch1ElemNames, FixedWingPitch1EnumOptions) ); - - List FixedWingPitch2ElemNames = new ArrayList(); - FixedWingPitch2ElemNames.add("0"); - List FixedWingPitch2EnumOptions = new ArrayList(); - FixedWingPitch2EnumOptions.add("Channel1"); - FixedWingPitch2EnumOptions.add("Channel2"); - FixedWingPitch2EnumOptions.add("Channel3"); - FixedWingPitch2EnumOptions.add("Channel4"); - FixedWingPitch2EnumOptions.add("Channel5"); - FixedWingPitch2EnumOptions.add("Channel6"); - FixedWingPitch2EnumOptions.add("Channel7"); - FixedWingPitch2EnumOptions.add("Channel8"); - FixedWingPitch2EnumOptions.add("Channel9"); - FixedWingPitch2EnumOptions.add("Channel10"); - FixedWingPitch2EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingPitch2", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch2ElemNames, FixedWingPitch2EnumOptions) ); - - List FixedWingYaw1ElemNames = new ArrayList(); - FixedWingYaw1ElemNames.add("0"); - List FixedWingYaw1EnumOptions = new ArrayList(); - FixedWingYaw1EnumOptions.add("Channel1"); - FixedWingYaw1EnumOptions.add("Channel2"); - FixedWingYaw1EnumOptions.add("Channel3"); - FixedWingYaw1EnumOptions.add("Channel4"); - FixedWingYaw1EnumOptions.add("Channel5"); - FixedWingYaw1EnumOptions.add("Channel6"); - FixedWingYaw1EnumOptions.add("Channel7"); - FixedWingYaw1EnumOptions.add("Channel8"); - FixedWingYaw1EnumOptions.add("Channel9"); - FixedWingYaw1EnumOptions.add("Channel10"); - FixedWingYaw1EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingYaw1", "channel", UAVObjectField.FieldType.ENUM, FixedWingYaw1ElemNames, FixedWingYaw1EnumOptions) ); - - List FixedWingYaw2ElemNames = new ArrayList(); - FixedWingYaw2ElemNames.add("0"); - List FixedWingYaw2EnumOptions = new ArrayList(); - FixedWingYaw2EnumOptions.add("Channel1"); - FixedWingYaw2EnumOptions.add("Channel2"); - FixedWingYaw2EnumOptions.add("Channel3"); - FixedWingYaw2EnumOptions.add("Channel4"); - FixedWingYaw2EnumOptions.add("Channel5"); - FixedWingYaw2EnumOptions.add("Channel6"); - FixedWingYaw2EnumOptions.add("Channel7"); - FixedWingYaw2EnumOptions.add("Channel8"); - FixedWingYaw2EnumOptions.add("Channel9"); - FixedWingYaw2EnumOptions.add("Channel10"); - FixedWingYaw2EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingYaw2", "channel", UAVObjectField.FieldType.ENUM, FixedWingYaw2ElemNames, FixedWingYaw2EnumOptions) ); - - List FixedWingThrottleElemNames = new ArrayList(); - FixedWingThrottleElemNames.add("0"); - List FixedWingThrottleEnumOptions = new ArrayList(); - FixedWingThrottleEnumOptions.add("Channel1"); - FixedWingThrottleEnumOptions.add("Channel2"); - FixedWingThrottleEnumOptions.add("Channel3"); - FixedWingThrottleEnumOptions.add("Channel4"); - FixedWingThrottleEnumOptions.add("Channel5"); - FixedWingThrottleEnumOptions.add("Channel6"); - FixedWingThrottleEnumOptions.add("Channel7"); - FixedWingThrottleEnumOptions.add("Channel8"); - FixedWingThrottleEnumOptions.add("Channel9"); - FixedWingThrottleEnumOptions.add("Channel10"); - FixedWingThrottleEnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingThrottle", "channel", UAVObjectField.FieldType.ENUM, FixedWingThrottleElemNames, FixedWingThrottleEnumOptions) ); - - List VTOLMotorNElemNames = new ArrayList(); - VTOLMotorNElemNames.add("0"); - List VTOLMotorNEnumOptions = new ArrayList(); - VTOLMotorNEnumOptions.add("Channel1"); - VTOLMotorNEnumOptions.add("Channel2"); - VTOLMotorNEnumOptions.add("Channel3"); - VTOLMotorNEnumOptions.add("Channel4"); - VTOLMotorNEnumOptions.add("Channel5"); - VTOLMotorNEnumOptions.add("Channel6"); - VTOLMotorNEnumOptions.add("Channel7"); - VTOLMotorNEnumOptions.add("Channel8"); - VTOLMotorNEnumOptions.add("Channel9"); - VTOLMotorNEnumOptions.add("Channel10"); - VTOLMotorNEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorN", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNElemNames, VTOLMotorNEnumOptions) ); - - List VTOLMotorNEElemNames = new ArrayList(); - VTOLMotorNEElemNames.add("0"); - List VTOLMotorNEEnumOptions = new ArrayList(); - VTOLMotorNEEnumOptions.add("Channel1"); - VTOLMotorNEEnumOptions.add("Channel2"); - VTOLMotorNEEnumOptions.add("Channel3"); - VTOLMotorNEEnumOptions.add("Channel4"); - VTOLMotorNEEnumOptions.add("Channel5"); - VTOLMotorNEEnumOptions.add("Channel6"); - VTOLMotorNEEnumOptions.add("Channel7"); - VTOLMotorNEEnumOptions.add("Channel8"); - VTOLMotorNEEnumOptions.add("Channel9"); - VTOLMotorNEEnumOptions.add("Channel10"); - VTOLMotorNEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorNE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNEElemNames, VTOLMotorNEEnumOptions) ); - - List VTOLMotorEElemNames = new ArrayList(); - VTOLMotorEElemNames.add("0"); - List VTOLMotorEEnumOptions = new ArrayList(); - VTOLMotorEEnumOptions.add("Channel1"); - VTOLMotorEEnumOptions.add("Channel2"); - VTOLMotorEEnumOptions.add("Channel3"); - VTOLMotorEEnumOptions.add("Channel4"); - VTOLMotorEEnumOptions.add("Channel5"); - VTOLMotorEEnumOptions.add("Channel6"); - VTOLMotorEEnumOptions.add("Channel7"); - VTOLMotorEEnumOptions.add("Channel8"); - VTOLMotorEEnumOptions.add("Channel9"); - VTOLMotorEEnumOptions.add("Channel10"); - VTOLMotorEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorEElemNames, VTOLMotorEEnumOptions) ); - - List VTOLMotorSEElemNames = new ArrayList(); - VTOLMotorSEElemNames.add("0"); - List VTOLMotorSEEnumOptions = new ArrayList(); - VTOLMotorSEEnumOptions.add("Channel1"); - VTOLMotorSEEnumOptions.add("Channel2"); - VTOLMotorSEEnumOptions.add("Channel3"); - VTOLMotorSEEnumOptions.add("Channel4"); - VTOLMotorSEEnumOptions.add("Channel5"); - VTOLMotorSEEnumOptions.add("Channel6"); - VTOLMotorSEEnumOptions.add("Channel7"); - VTOLMotorSEEnumOptions.add("Channel8"); - VTOLMotorSEEnumOptions.add("Channel9"); - VTOLMotorSEEnumOptions.add("Channel10"); - VTOLMotorSEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorSE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSEElemNames, VTOLMotorSEEnumOptions) ); - - List VTOLMotorSElemNames = new ArrayList(); - VTOLMotorSElemNames.add("0"); - List VTOLMotorSEnumOptions = new ArrayList(); - VTOLMotorSEnumOptions.add("Channel1"); - VTOLMotorSEnumOptions.add("Channel2"); - VTOLMotorSEnumOptions.add("Channel3"); - VTOLMotorSEnumOptions.add("Channel4"); - VTOLMotorSEnumOptions.add("Channel5"); - VTOLMotorSEnumOptions.add("Channel6"); - VTOLMotorSEnumOptions.add("Channel7"); - VTOLMotorSEnumOptions.add("Channel8"); - VTOLMotorSEnumOptions.add("Channel9"); - VTOLMotorSEnumOptions.add("Channel10"); - VTOLMotorSEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorS", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSElemNames, VTOLMotorSEnumOptions) ); - - List VTOLMotorSWElemNames = new ArrayList(); - VTOLMotorSWElemNames.add("0"); - List VTOLMotorSWEnumOptions = new ArrayList(); - VTOLMotorSWEnumOptions.add("Channel1"); - VTOLMotorSWEnumOptions.add("Channel2"); - VTOLMotorSWEnumOptions.add("Channel3"); - VTOLMotorSWEnumOptions.add("Channel4"); - VTOLMotorSWEnumOptions.add("Channel5"); - VTOLMotorSWEnumOptions.add("Channel6"); - VTOLMotorSWEnumOptions.add("Channel7"); - VTOLMotorSWEnumOptions.add("Channel8"); - VTOLMotorSWEnumOptions.add("Channel9"); - VTOLMotorSWEnumOptions.add("Channel10"); - VTOLMotorSWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorSW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSWElemNames, VTOLMotorSWEnumOptions) ); - - List VTOLMotorWElemNames = new ArrayList(); - VTOLMotorWElemNames.add("0"); - List VTOLMotorWEnumOptions = new ArrayList(); - VTOLMotorWEnumOptions.add("Channel1"); - VTOLMotorWEnumOptions.add("Channel2"); - VTOLMotorWEnumOptions.add("Channel3"); - VTOLMotorWEnumOptions.add("Channel4"); - VTOLMotorWEnumOptions.add("Channel5"); - VTOLMotorWEnumOptions.add("Channel6"); - VTOLMotorWEnumOptions.add("Channel7"); - VTOLMotorWEnumOptions.add("Channel8"); - VTOLMotorWEnumOptions.add("Channel9"); - VTOLMotorWEnumOptions.add("Channel10"); - VTOLMotorWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorWElemNames, VTOLMotorWEnumOptions) ); - - List VTOLMotorNWElemNames = new ArrayList(); - VTOLMotorNWElemNames.add("0"); - List VTOLMotorNWEnumOptions = new ArrayList(); - VTOLMotorNWEnumOptions.add("Channel1"); - VTOLMotorNWEnumOptions.add("Channel2"); - VTOLMotorNWEnumOptions.add("Channel3"); - VTOLMotorNWEnumOptions.add("Channel4"); - VTOLMotorNWEnumOptions.add("Channel5"); - VTOLMotorNWEnumOptions.add("Channel6"); - VTOLMotorNWEnumOptions.add("Channel7"); - VTOLMotorNWEnumOptions.add("Channel8"); - VTOLMotorNWEnumOptions.add("Channel9"); - VTOLMotorNWEnumOptions.add("Channel10"); - VTOLMotorNWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorNW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNWElemNames, VTOLMotorNWEnumOptions) ); - List ChannelTypeElemNames = new ArrayList(); ChannelTypeElemNames.add("0"); ChannelTypeElemNames.add("1"); @@ -398,18 +158,17 @@ public class ActuatorSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -454,21 +213,6 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelMin").setValue(1000,7); getField("ChannelMin").setValue(1000,8); getField("ChannelMin").setValue(1000,9); - getField("FixedWingRoll1").setValue("None"); - getField("FixedWingRoll2").setValue("None"); - getField("FixedWingPitch1").setValue("None"); - getField("FixedWingPitch2").setValue("None"); - getField("FixedWingYaw1").setValue("None"); - getField("FixedWingYaw2").setValue("None"); - getField("FixedWingThrottle").setValue("None"); - getField("VTOLMotorN").setValue("None"); - getField("VTOLMotorNE").setValue("None"); - getField("VTOLMotorE").setValue("None"); - getField("VTOLMotorSE").setValue("None"); - getField("VTOLMotorS").setValue("None"); - getField("VTOLMotorSW").setValue("None"); - getField("VTOLMotorW").setValue("None"); - getField("VTOLMotorNW").setValue("None"); getField("ChannelType").setValue("PWM",0); getField("ChannelType").setValue("PWM",1); getField("ChannelType").setValue("PWM",2); @@ -518,7 +262,7 @@ public class ActuatorSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0xF2875746; + protected static final int OBJID = 0x7D555646; protected static final String NAME = "ActuatorSettings"; protected static String DESCRIPTION = "Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java index 7c9272cad..b117e501a 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java @@ -102,18 +102,17 @@ public class AttitudeActual extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 100; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 100; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java index 3034a99ad..9bcce7bf3 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java @@ -130,18 +130,17 @@ public class AttitudeSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java index ecde53985..cd649f84c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java @@ -86,18 +86,17 @@ public class BaroAltitude extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java index 7a36ec1ea..34c23e612 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java @@ -86,18 +86,17 @@ public class CameraDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java index a8e03df32..0b2f3b3f5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java @@ -125,18 +125,17 @@ public class CameraStabSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java index b22b8185e..8da58f793 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java @@ -85,18 +85,17 @@ public class FaultSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java index 71c681bd2..58fadcee5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java @@ -152,18 +152,17 @@ public class FirmwareIAPObj extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java index a3bc23eb3..850f64103 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java @@ -80,9 +80,12 @@ public class FlightBatterySettings extends UAVDataObject { fields.add( new UAVObjectField("NbCells", "", UAVObjectField.FieldType.UINT8, NbCellsElemNames, null) ); List SensorTypeElemNames = new ArrayList(); - SensorTypeElemNames.add("0"); + SensorTypeElemNames.add("BatteryCurrent"); + SensorTypeElemNames.add("BatteryVoltage"); + SensorTypeElemNames.add("BoardVoltage"); List SensorTypeEnumOptions = new ArrayList(); - SensorTypeEnumOptions.add("None"); + SensorTypeEnumOptions.add("Disabled"); + SensorTypeEnumOptions.add("Enabled"); fields.add( new UAVObjectField("SensorType", "", UAVObjectField.FieldType.ENUM, SensorTypeElemNames, SensorTypeEnumOptions) ); @@ -108,18 +111,17 @@ public class FlightBatterySettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -137,7 +139,9 @@ public class FlightBatterySettings extends UAVDataObject { getField("SensorCalibrations").setValue(1,1); getField("Type").setValue("LiPo"); getField("NbCells").setValue(3); - getField("SensorType").setValue("None"); + getField("SensorType").setValue("Disabled",0); + getField("SensorType").setValue("Disabled",1); + getField("SensorType").setValue("Disabled",2); } @@ -166,7 +170,7 @@ public class FlightBatterySettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0xF172BB18; + protected static final int OBJID = 0x94AC6AD2; protected static final String NAME = "FlightBatterySettings"; protected static String DESCRIPTION = "Flight Battery configuration."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java index 82fcfae47..d54648ad5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java @@ -59,6 +59,10 @@ public class FlightBatteryState extends UAVDataObject { CurrentElemNames.add("0"); fields.add( new UAVObjectField("Current", "A", UAVObjectField.FieldType.FLOAT32, CurrentElemNames, null) ); + List BoardSupplyVoltageElemNames = new ArrayList(); + BoardSupplyVoltageElemNames.add("0"); + fields.add( new UAVObjectField("BoardSupplyVoltage", "V", UAVObjectField.FieldType.FLOAT32, BoardSupplyVoltageElemNames, null) ); + List PeakCurrentElemNames = new ArrayList(); PeakCurrentElemNames.add("0"); fields.add( new UAVObjectField("PeakCurrent", "A", UAVObjectField.FieldType.FLOAT32, PeakCurrentElemNames, null) ); @@ -98,18 +102,17 @@ public class FlightBatteryState extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READONLY; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READONLY) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -122,6 +125,7 @@ public class FlightBatteryState extends UAVDataObject { { getField("Voltage").setValue(0); getField("Current").setValue(0); + getField("BoardSupplyVoltage").setValue(0); getField("PeakCurrent").setValue(0); getField("AvgCurrent").setValue(0); getField("ConsumedEnergy").setValue(0); @@ -154,7 +158,7 @@ public class FlightBatteryState extends UAVDataObject { } // Constants - protected static final int OBJID = 0x8C0D756; + protected static final int OBJID = 0xD2083596; protected static final String NAME = "FlightBatteryState"; protected static String DESCRIPTION = "Battery status information."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java index dbe959f96..cdea28a0f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java @@ -82,18 +82,17 @@ public class FlightPlanControl extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java index 6fc39a26e..184bbd1b7 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java @@ -78,18 +78,17 @@ public class FlightPlanSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java index 7b78bce71..8aa152789 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java @@ -119,18 +119,17 @@ public class FlightPlanStatus extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 2000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 2000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java index ac3812aa6..38697e573 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java @@ -70,6 +70,7 @@ public class FlightStatus extends UAVDataObject { FlightModeEnumOptions.add("VelocityControl"); FlightModeEnumOptions.add("PositionHold"); FlightModeEnumOptions.add("PathPlanner"); + FlightModeEnumOptions.add("RTH"); fields.add( new UAVObjectField("FlightMode", "", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); @@ -95,18 +96,17 @@ public class FlightStatus extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 5000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 5000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -146,7 +146,7 @@ public class FlightStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0x19B92D8; + protected static final int OBJID = 0x884FEF66; protected static final String NAME = "FlightStatus"; protected static String DESCRIPTION = "Contains major flight status information for other modules."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java index 403ea1d5e..3a042f52e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java @@ -103,18 +103,17 @@ public class FlightTelemetryStats extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 5000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 5000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 5000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 5000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java index 3cb3811ae..05fa87efb 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java @@ -58,6 +58,8 @@ public class GCSReceiver extends UAVDataObject { ChannelElemNames.add("3"); ChannelElemNames.add("4"); ChannelElemNames.add("5"); + ChannelElemNames.add("6"); + ChannelElemNames.add("7"); fields.add( new UAVObjectField("Channel", "us", UAVObjectField.FieldType.UINT16, ChannelElemNames, null) ); @@ -83,18 +85,17 @@ public class GCSReceiver extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READONLY; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -133,7 +134,7 @@ public class GCSReceiver extends UAVDataObject { } // Constants - protected static final int OBJID = 0xCC7E2BBC; + protected static final int OBJID = 0xCC7E1470; protected static final String NAME = "GCSReceiver"; protected static String DESCRIPTION = "A receiver channel group carried over the telemetry link."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java index b32f551ce..754272c8c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java @@ -103,18 +103,17 @@ public class GCSTelemetryStats extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.gcsTelemetryUpdatePeriod = 5000; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 5000; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java index 5f4e20b46..c2c8544a9 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java @@ -123,18 +123,17 @@ public class GPSPosition extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java index bb331132d..0f5b0161a 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java @@ -154,18 +154,17 @@ public class GPSSatellites extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 10000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 30000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 10000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 30000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java index 5aa4df7bf..7095aa18e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java @@ -98,18 +98,17 @@ public class GPSTime extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 10000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 30000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 10000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 30000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java deleted file mode 100644 index 5510a901d..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java +++ /dev/null @@ -1,211 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * Settings for the @ref GuidanceModule - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -Settings for the @ref GuidanceModule - -generated from guidancesettings.xml - **/ -public class GuidanceSettings extends UAVDataObject { - - public GuidanceSettings() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List HorizontalPosPIElemNames = new ArrayList(); - HorizontalPosPIElemNames.add("Kp"); - HorizontalPosPIElemNames.add("Ki"); - HorizontalPosPIElemNames.add("ILimit"); - fields.add( new UAVObjectField("HorizontalPosPI", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) ); - - List HorizontalVelPIDElemNames = new ArrayList(); - HorizontalVelPIDElemNames.add("Kp"); - HorizontalVelPIDElemNames.add("Ki"); - HorizontalVelPIDElemNames.add("Kd"); - HorizontalVelPIDElemNames.add("ILimit"); - fields.add( new UAVObjectField("HorizontalVelPID", "deg/(m/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); - - List VerticalPosPIElemNames = new ArrayList(); - VerticalPosPIElemNames.add("Kp"); - VerticalPosPIElemNames.add("Ki"); - VerticalPosPIElemNames.add("ILimit"); - fields.add( new UAVObjectField("VerticalPosPI", "", UAVObjectField.FieldType.FLOAT32, VerticalPosPIElemNames, null) ); - - List VerticalVelPIDElemNames = new ArrayList(); - VerticalVelPIDElemNames.add("Kp"); - VerticalVelPIDElemNames.add("Ki"); - VerticalVelPIDElemNames.add("Kd"); - VerticalVelPIDElemNames.add("ILimit"); - fields.add( new UAVObjectField("VerticalVelPID", "", UAVObjectField.FieldType.FLOAT32, VerticalVelPIDElemNames, null) ); - - List MaxRollPitchElemNames = new ArrayList(); - MaxRollPitchElemNames.add("0"); - fields.add( new UAVObjectField("MaxRollPitch", "deg", UAVObjectField.FieldType.FLOAT32, MaxRollPitchElemNames, null) ); - - List UpdatePeriodElemNames = new ArrayList(); - UpdatePeriodElemNames.add("0"); - fields.add( new UAVObjectField("UpdatePeriod", "", UAVObjectField.FieldType.INT32, UpdatePeriodElemNames, null) ); - - List HorizontalVelMaxElemNames = new ArrayList(); - HorizontalVelMaxElemNames.add("0"); - fields.add( new UAVObjectField("HorizontalVelMax", "m/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) ); - - List VerticalVelMaxElemNames = new ArrayList(); - VerticalVelMaxElemNames.add("0"); - fields.add( new UAVObjectField("VerticalVelMax", "m/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) ); - - List GuidanceModeElemNames = new ArrayList(); - GuidanceModeElemNames.add("0"); - List GuidanceModeEnumOptions = new ArrayList(); - GuidanceModeEnumOptions.add("DUAL_LOOP"); - GuidanceModeEnumOptions.add("VELOCITY_CONTROL"); - fields.add( new UAVObjectField("GuidanceMode", "", UAVObjectField.FieldType.ENUM, GuidanceModeElemNames, GuidanceModeEnumOptions) ); - - List ThrottleControlElemNames = new ArrayList(); - ThrottleControlElemNames.add("0"); - List ThrottleControlEnumOptions = new ArrayList(); - ThrottleControlEnumOptions.add("FALSE"); - ThrottleControlEnumOptions.add("TRUE"); - fields.add( new UAVObjectField("ThrottleControl", "", UAVObjectField.FieldType.ENUM, ThrottleControlElemNames, ThrottleControlEnumOptions) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - getField("HorizontalPosPI").setValue(0.1,0); - getField("HorizontalPosPI").setValue(0.001,1); - getField("HorizontalPosPI").setValue(300,2); - getField("HorizontalVelPID").setValue(0.05,0); - getField("HorizontalVelPID").setValue(0.002,1); - getField("HorizontalVelPID").setValue(0,2); - getField("HorizontalVelPID").setValue(1000,3); - getField("VerticalPosPI").setValue(0.1,0); - getField("VerticalPosPI").setValue(0.001,1); - getField("VerticalPosPI").setValue(200,2); - getField("VerticalVelPID").setValue(0.1,0); - getField("VerticalVelPID").setValue(0,1); - getField("VerticalVelPID").setValue(0,2); - getField("VerticalVelPID").setValue(0,3); - getField("MaxRollPitch").setValue(10); - getField("UpdatePeriod").setValue(100); - getField("HorizontalVelMax").setValue(300); - getField("VerticalVelMax").setValue(150); - getField("GuidanceMode").setValue("DUAL_LOOP"); - getField("ThrottleControl").setValue("FALSE"); - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - GuidanceSettings obj = new GuidanceSettings(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public GuidanceSettings GetInstance(UAVObjectManager objMngr, int instID) - { - return (GuidanceSettings)(objMngr.getObject(GuidanceSettings.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0x6EA79FB4; - protected static final String NAME = "GuidanceSettings"; - protected static String DESCRIPTION = "Settings for the @ref GuidanceModule"; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 1 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java index 3f3b3d8dd..0cd45db1b 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java @@ -103,18 +103,17 @@ public class HomeLocation extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java index f56982e69..9d8113846 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java @@ -190,14 +190,6 @@ public class HwSettings extends UAVDataObject { ComUsbBridgeSpeedEnumOptions.add("115200"); fields.add( new UAVObjectField("ComUsbBridgeSpeed", "bps", UAVObjectField.FieldType.ENUM, ComUsbBridgeSpeedElemNames, ComUsbBridgeSpeedEnumOptions) ); - List USB_DeviceTypeElemNames = new ArrayList(); - USB_DeviceTypeElemNames.add("0"); - List USB_DeviceTypeEnumOptions = new ArrayList(); - USB_DeviceTypeEnumOptions.add("HID-only"); - USB_DeviceTypeEnumOptions.add("HID+VCP"); - USB_DeviceTypeEnumOptions.add("VCP-only"); - fields.add( new UAVObjectField("USB_DeviceType", "descriptor", UAVObjectField.FieldType.ENUM, USB_DeviceTypeElemNames, USB_DeviceTypeEnumOptions) ); - List USB_HIDPortElemNames = new ArrayList(); USB_HIDPortElemNames.add("0"); List USB_HIDPortEnumOptions = new ArrayList(); @@ -219,7 +211,12 @@ public class HwSettings extends UAVDataObject { OptionalModulesElemNames.add("ComUsbBridge"); OptionalModulesElemNames.add("Fault"); OptionalModulesElemNames.add("Altitude"); + OptionalModulesElemNames.add("Airspeed"); OptionalModulesElemNames.add("TxPID"); + OptionalModulesElemNames.add("VtolPathFollower"); + OptionalModulesElemNames.add("FixedWingPathFollower"); + OptionalModulesElemNames.add("Battery"); + OptionalModulesElemNames.add("Overo"); List OptionalModulesEnumOptions = new ArrayList(); OptionalModulesEnumOptions.add("Disabled"); OptionalModulesEnumOptions.add("Enabled"); @@ -252,18 +249,17 @@ public class HwSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -286,7 +282,6 @@ public class HwSettings extends UAVDataObject { getField("TelemetrySpeed").setValue("57600"); getField("GPSSpeed").setValue("57600"); getField("ComUsbBridgeSpeed").setValue("57600"); - getField("USB_DeviceType").setValue("HID-only"); getField("USB_HIDPort").setValue("USBTelemetry"); getField("USB_VCPPort").setValue("Disabled"); getField("OptionalModules").setValue("Disabled",0); @@ -295,6 +290,11 @@ public class HwSettings extends UAVDataObject { getField("OptionalModules").setValue("Disabled",3); getField("OptionalModules").setValue("Disabled",4); getField("OptionalModules").setValue("Disabled",5); + getField("OptionalModules").setValue("Disabled",6); + getField("OptionalModules").setValue("Disabled",7); + getField("OptionalModules").setValue("Disabled",8); + getField("OptionalModules").setValue("Disabled",9); + getField("OptionalModules").setValue("Disabled",10); getField("DSMxBind").setValue(0); } @@ -324,7 +324,7 @@ public class HwSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x4730375C; + protected static final int OBJID = 0x5D950E50; protected static final String NAME = "HwSettings"; protected static String DESCRIPTION = "Selection of optional hardware configurations."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java index abd8f41f6..a09e4404d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java @@ -177,18 +177,17 @@ public class I2CStats extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 10000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 30000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 10000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 30000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java index 6ac5a1b2c..5ce51c245 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java @@ -113,18 +113,17 @@ public class ManualControlCommand extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 2000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 2000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java index c8f460bc4..47ebbc230 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java @@ -51,6 +51,10 @@ public class ManualControlSettings extends UAVDataObject { List fields = new ArrayList(); + List DeadbandElemNames = new ArrayList(); + DeadbandElemNames.add("0"); + fields.add( new UAVObjectField("Deadband", "%", UAVObjectField.FieldType.FLOAT32, DeadbandElemNames, null) ); + List ChannelMinElemNames = new ArrayList(); ChannelMinElemNames.add("Throttle"); ChannelMinElemNames.add("Roll"); @@ -146,6 +150,7 @@ public class ManualControlSettings extends UAVDataObject { Stabilization1SettingsEnumOptions.add("Attitude"); Stabilization1SettingsEnumOptions.add("AxisLock"); Stabilization1SettingsEnumOptions.add("WeakLeveling"); + Stabilization1SettingsEnumOptions.add("VirtualBar"); fields.add( new UAVObjectField("Stabilization1Settings", "", UAVObjectField.FieldType.ENUM, Stabilization1SettingsElemNames, Stabilization1SettingsEnumOptions) ); List Stabilization2SettingsElemNames = new ArrayList(); @@ -158,6 +163,7 @@ public class ManualControlSettings extends UAVDataObject { Stabilization2SettingsEnumOptions.add("Attitude"); Stabilization2SettingsEnumOptions.add("AxisLock"); Stabilization2SettingsEnumOptions.add("WeakLeveling"); + Stabilization2SettingsEnumOptions.add("VirtualBar"); fields.add( new UAVObjectField("Stabilization2Settings", "", UAVObjectField.FieldType.ENUM, Stabilization2SettingsElemNames, Stabilization2SettingsEnumOptions) ); List Stabilization3SettingsElemNames = new ArrayList(); @@ -170,6 +176,7 @@ public class ManualControlSettings extends UAVDataObject { Stabilization3SettingsEnumOptions.add("Attitude"); Stabilization3SettingsEnumOptions.add("AxisLock"); Stabilization3SettingsEnumOptions.add("WeakLeveling"); + Stabilization3SettingsEnumOptions.add("VirtualBar"); fields.add( new UAVObjectField("Stabilization3Settings", "", UAVObjectField.FieldType.ENUM, Stabilization3SettingsElemNames, Stabilization3SettingsEnumOptions) ); List FlightModePositionElemNames = new ArrayList(); @@ -185,8 +192,21 @@ public class ManualControlSettings extends UAVDataObject { FlightModePositionEnumOptions.add("VelocityControl"); FlightModePositionEnumOptions.add("PositionHold"); FlightModePositionEnumOptions.add("PathPlanner"); + FlightModePositionEnumOptions.add("RTH"); + FlightModePositionEnumOptions.add("Land"); fields.add( new UAVObjectField("FlightModePosition", "", UAVObjectField.FieldType.ENUM, FlightModePositionElemNames, FlightModePositionEnumOptions) ); + List FlightModeNumberElemNames = new ArrayList(); + FlightModeNumberElemNames.add("0"); + fields.add( new UAVObjectField("FlightModeNumber", "", UAVObjectField.FieldType.UINT8, FlightModeNumberElemNames, null) ); + + List FailsafeBehaviorElemNames = new ArrayList(); + FailsafeBehaviorElemNames.add("0"); + List FailsafeBehaviorEnumOptions = new ArrayList(); + FailsafeBehaviorEnumOptions.add("None"); + FailsafeBehaviorEnumOptions.add("RTH"); + fields.add( new UAVObjectField("FailsafeBehavior", "", UAVObjectField.FieldType.ENUM, FailsafeBehaviorElemNames, FailsafeBehaviorEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -210,18 +230,17 @@ public class ManualControlSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -232,6 +251,7 @@ public class ManualControlSettings extends UAVDataObject { */ public void setDefaultFieldValues() { + getField("Deadband").setValue(0); getField("ChannelMin").setValue(1000,0); getField("ChannelMin").setValue(1000,1); getField("ChannelMin").setValue(1000,2); @@ -291,6 +311,8 @@ public class ManualControlSettings extends UAVDataObject { getField("FlightModePosition").setValue("Manual",0); getField("FlightModePosition").setValue("Stabilized1",1); getField("FlightModePosition").setValue("Stabilized2",2); + getField("FlightModeNumber").setValue(3); + getField("FailsafeBehavior").setValue("None"); } @@ -319,7 +341,7 @@ public class ManualControlSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x59C4551C; + protected static final int OBJID = 0x6C188320; protected static final String NAME = "ManualControlSettings"; protected static String DESCRIPTION = "Settings to indicate how to decode receiver input by @ref ManualControlModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java index 76841d8ff..094d91545 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java @@ -372,18 +372,17 @@ public class MixerSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java index 80e3b15bf..1f767c5ba 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java @@ -114,18 +114,17 @@ public class MixerStatus extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java index 1629a19d2..6d09a799e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java @@ -86,18 +86,17 @@ public class NedAccel extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 10001; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 10001; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java index dccd85d36..42a65e3ab 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java @@ -68,6 +68,7 @@ public class ObjectPersistence extends UAVDataObject { OperationEnumOptions.add("Delete"); OperationEnumOptions.add("FullErase"); OperationEnumOptions.add("Completed"); + OperationEnumOptions.add("Error"); fields.add( new UAVObjectField("Operation", "", UAVObjectField.FieldType.ENUM, OperationElemNames, OperationEnumOptions) ); List SelectionElemNames = new ArrayList(); @@ -102,18 +103,17 @@ public class ObjectPersistence extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -152,7 +152,7 @@ public class ObjectPersistence extends UAVDataObject { } // Constants - protected static final int OBJID = 0xF69AD8B8; + protected static final int OBJID = 0x99C63292; protected static final String NAME = "ObjectPersistence"; protected static String DESCRIPTION = "Someone who knows please enter this"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java index 184098a16..1c87c21c3 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java @@ -86,18 +86,17 @@ public class PositionActual extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 1000; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java deleted file mode 100644 index 123ca58af..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java +++ /dev/null @@ -1,147 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner - -generated from positiondesired.xml - **/ -public class PositionDesired extends UAVDataObject { - - public PositionDesired() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List NorthElemNames = new ArrayList(); - NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "m", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); - - List EastElemNames = new ArrayList(); - EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "m", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); - - List DownElemNames = new ArrayList(); - DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "m", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - PositionDesired obj = new PositionDesired(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public PositionDesired GetInstance(UAVObjectManager objMngr, int instID) - { - return (PositionDesired)(objMngr.getObject(PositionDesired.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0x778DBE24; - protected static final String NAME = "PositionDesired"; - protected static String DESCRIPTION = "The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner "; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 0 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java index ddeacd8d4..51f7faa7d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java @@ -86,18 +86,17 @@ public class RateDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java index a40b27e38..15391ce71 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java @@ -90,18 +90,17 @@ public class ReceiverActivity extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READONLY; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READONLY) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java index 18cf6f4d6..1a5679d6a 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java @@ -78,18 +78,17 @@ public class SonarAltitude extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java index 32d2c735c..8ca5df722 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java @@ -77,6 +77,7 @@ public class StabilizationDesired extends UAVDataObject { StabilizationModeEnumOptions.add("Attitude"); StabilizationModeEnumOptions.add("AxisLock"); StabilizationModeEnumOptions.add("WeakLeveling"); + StabilizationModeEnumOptions.add("VirtualBar"); fields.add( new UAVObjectField("StabilizationMode", "", UAVObjectField.FieldType.ENUM, StabilizationModeElemNames, StabilizationModeEnumOptions) ); @@ -102,18 +103,17 @@ public class StabilizationDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -152,7 +152,7 @@ public class StabilizationDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0xDB8FFC3C; + protected static final int OBJID = 0xDE1EAAD6; protected static final String NAME = "StabilizationDesired"; protected static String DESCRIPTION = "The desired attitude that @ref StabilizationModule will try and achieve if FlightMode is Stabilized. Comes from @ref ManaulControlModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java index ab78bdc74..cc2c69e8f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java @@ -102,6 +102,31 @@ public class StabilizationSettings extends UAVDataObject { YawPIElemNames.add("ILimit"); fields.add( new UAVObjectField("YawPI", "", UAVObjectField.FieldType.FLOAT32, YawPIElemNames, null) ); + List VbarSensitivityElemNames = new ArrayList(); + VbarSensitivityElemNames.add("Roll"); + VbarSensitivityElemNames.add("Pitch"); + VbarSensitivityElemNames.add("Yaw"); + fields.add( new UAVObjectField("VbarSensitivity", "frac", UAVObjectField.FieldType.FLOAT32, VbarSensitivityElemNames, null) ); + + List VbarRollPIElemNames = new ArrayList(); + VbarRollPIElemNames.add("Kp"); + VbarRollPIElemNames.add("Ki"); + fields.add( new UAVObjectField("VbarRollPI", "1/(deg/s)", UAVObjectField.FieldType.FLOAT32, VbarRollPIElemNames, null) ); + + List VbarPitchPIElemNames = new ArrayList(); + VbarPitchPIElemNames.add("Kp"); + VbarPitchPIElemNames.add("Ki"); + fields.add( new UAVObjectField("VbarPitchPI", "1/(deg/s)", UAVObjectField.FieldType.FLOAT32, VbarPitchPIElemNames, null) ); + + List VbarYawPIElemNames = new ArrayList(); + VbarYawPIElemNames.add("Kp"); + VbarYawPIElemNames.add("Ki"); + fields.add( new UAVObjectField("VbarYawPI", "1/(deg/s)", UAVObjectField.FieldType.FLOAT32, VbarYawPIElemNames, null) ); + + List VbarTauElemNames = new ArrayList(); + VbarTauElemNames.add("0"); + fields.add( new UAVObjectField("VbarTau", "sec", UAVObjectField.FieldType.FLOAT32, VbarTauElemNames, null) ); + List GyroTauElemNames = new ArrayList(); GyroTauElemNames.add("0"); fields.add( new UAVObjectField("GyroTau", "", UAVObjectField.FieldType.FLOAT32, GyroTauElemNames, null) ); @@ -122,6 +147,21 @@ public class StabilizationSettings extends UAVDataObject { YawMaxElemNames.add("0"); fields.add( new UAVObjectField("YawMax", "degrees", UAVObjectField.FieldType.UINT8, YawMaxElemNames, null) ); + List VbarGyroSuppressElemNames = new ArrayList(); + VbarGyroSuppressElemNames.add("0"); + fields.add( new UAVObjectField("VbarGyroSuppress", "%", UAVObjectField.FieldType.INT8, VbarGyroSuppressElemNames, null) ); + + List VbarPiroCompElemNames = new ArrayList(); + VbarPiroCompElemNames.add("0"); + List VbarPiroCompEnumOptions = new ArrayList(); + VbarPiroCompEnumOptions.add("FALSE"); + VbarPiroCompEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("VbarPiroComp", "", UAVObjectField.FieldType.ENUM, VbarPiroCompElemNames, VbarPiroCompEnumOptions) ); + + List VbarMaxAngleElemNames = new ArrayList(); + VbarMaxAngleElemNames.add("0"); + fields.add( new UAVObjectField("VbarMaxAngle", "deg", UAVObjectField.FieldType.UINT8, VbarMaxAngleElemNames, null) ); + List MaxAxisLockElemNames = new ArrayList(); MaxAxisLockElemNames.add("0"); fields.add( new UAVObjectField("MaxAxisLock", "deg", UAVObjectField.FieldType.UINT8, MaxAxisLockElemNames, null) ); @@ -164,18 +204,17 @@ public class StabilizationSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -213,11 +252,24 @@ public class StabilizationSettings extends UAVDataObject { getField("YawPI").setValue(2,0); getField("YawPI").setValue(0,1); getField("YawPI").setValue(50,2); + getField("VbarSensitivity").setValue(0.5,0); + getField("VbarSensitivity").setValue(0.5,1); + getField("VbarSensitivity").setValue(0.5,2); + getField("VbarRollPI").setValue(0.005,0); + getField("VbarRollPI").setValue(0.002,1); + getField("VbarPitchPI").setValue(0.005,0); + getField("VbarPitchPI").setValue(0.002,1); + getField("VbarYawPI").setValue(0.005,0); + getField("VbarYawPI").setValue(0.002,1); + getField("VbarTau").setValue(0.5); getField("GyroTau").setValue(0.005); getField("WeakLevelingKp").setValue(0.1); getField("RollMax").setValue(55); getField("PitchMax").setValue(55); getField("YawMax").setValue(35); + getField("VbarGyroSuppress").setValue(30); + getField("VbarPiroComp").setValue("FALSE"); + getField("VbarMaxAngle").setValue(10); getField("MaxAxisLock").setValue(15); getField("MaxAxisLockRate").setValue(2); getField("MaxWeakLevelingRate").setValue(5); @@ -250,7 +302,7 @@ public class StabilizationSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x5F78C51E; + protected static final int OBJID = 0xBBC337D4; protected static final String NAME = "StabilizationSettings"; protected static String DESCRIPTION = "PID settings used by the Stabilization module to combine the @ref AttitudeActual and @ref AttitudeDesired to compute @ref ActuatorDesired"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java index bc4bf0625..3b34763fe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java @@ -56,7 +56,6 @@ public class SystemAlarms extends UAVDataObject { AlarmElemNames.add("StackOverflow"); AlarmElemNames.add("CPUOverload"); AlarmElemNames.add("EventSystem"); - AlarmElemNames.add("SDCard"); AlarmElemNames.add("Telemetry"); AlarmElemNames.add("ManualControl"); AlarmElemNames.add("Actuator"); @@ -64,12 +63,12 @@ public class SystemAlarms extends UAVDataObject { AlarmElemNames.add("Sensors"); AlarmElemNames.add("Stabilization"); AlarmElemNames.add("Guidance"); - AlarmElemNames.add("AHRSComms"); AlarmElemNames.add("Battery"); AlarmElemNames.add("FlightTime"); AlarmElemNames.add("I2C"); AlarmElemNames.add("GPS"); AlarmElemNames.add("BootFault"); + AlarmElemNames.add("Power"); List AlarmEnumOptions = new ArrayList(); AlarmEnumOptions.add("Uninitialised"); AlarmEnumOptions.add("OK"); @@ -101,18 +100,17 @@ public class SystemAlarms extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } @@ -140,7 +138,6 @@ public class SystemAlarms extends UAVDataObject { getField("Alarm").setValue("Uninitialised",14); getField("Alarm").setValue("Uninitialised",15); getField("Alarm").setValue("Uninitialised",16); - getField("Alarm").setValue("Uninitialised",17); } @@ -169,7 +166,7 @@ public class SystemAlarms extends UAVDataObject { } // Constants - protected static final int OBJID = 0x9C7CBFE; + protected static final int OBJID = 0x737ADCF2; protected static final String NAME = "SystemAlarms"; protected static String DESCRIPTION = "Alarms from OpenPilot to indicate failure conditions or warnings. Set by various modules."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java index e3c2cf0b0..bffbced31 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java @@ -54,6 +54,8 @@ public class SystemSettings extends UAVDataObject { List GUIConfigDataElemNames = new ArrayList(); GUIConfigDataElemNames.add("0"); GUIConfigDataElemNames.add("1"); + GUIConfigDataElemNames.add("2"); + GUIConfigDataElemNames.add("3"); fields.add( new UAVObjectField("GUIConfigData", "bits", UAVObjectField.FieldType.UINT32, GUIConfigDataElemNames, null) ); List AirframeTypeElemNames = new ArrayList(); @@ -75,6 +77,9 @@ public class SystemSettings extends UAVDataObject { AirframeTypeEnumOptions.add("OctoCoaxX"); AirframeTypeEnumOptions.add("HexaCoax"); AirframeTypeEnumOptions.add("Tri"); + AirframeTypeEnumOptions.add("GroundVehicleCar"); + AirframeTypeEnumOptions.add("GroundVehicleDifferential"); + AirframeTypeEnumOptions.add("GroundVehicleMotorcycle"); fields.add( new UAVObjectField("AirframeType", "", UAVObjectField.FieldType.ENUM, AirframeTypeElemNames, AirframeTypeEnumOptions) ); @@ -100,18 +105,17 @@ public class SystemSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -124,7 +128,9 @@ public class SystemSettings extends UAVDataObject { { getField("GUIConfigData").setValue(0,0); getField("GUIConfigData").setValue(0,1); - getField("AirframeType").setValue("FixedWing"); + getField("GUIConfigData").setValue(0,2); + getField("GUIConfigData").setValue(0,3); + getField("AirframeType").setValue("QuadX"); } @@ -153,7 +159,7 @@ public class SystemSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x30BD5D7C; + protected static final int OBJID = 0xC72A326E; protected static final String NAME = "SystemSettings"; protected static String DESCRIPTION = "Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java index 26d01f2a0..888474261 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java @@ -106,18 +106,17 @@ public class SystemStats extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java index eefcef6d9..9f530e6a9 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java @@ -62,11 +62,12 @@ public class TaskInfo extends UAVDataObject { StackRemainingElemNames.add("GPS"); StackRemainingElemNames.add("ManualControl"); StackRemainingElemNames.add("Altitude"); + StackRemainingElemNames.add("Airspeed"); StackRemainingElemNames.add("Stabilization"); StackRemainingElemNames.add("AltitudeHold"); - StackRemainingElemNames.add("Guidance"); - StackRemainingElemNames.add("FlightPlan"); StackRemainingElemNames.add("PathPlanner"); + StackRemainingElemNames.add("PathFollower"); + StackRemainingElemNames.add("FlightPlan"); StackRemainingElemNames.add("Com2UsbBridge"); StackRemainingElemNames.add("Usb2ComBridge"); StackRemainingElemNames.add("OveroSync"); @@ -83,11 +84,12 @@ public class TaskInfo extends UAVDataObject { RunningElemNames.add("GPS"); RunningElemNames.add("ManualControl"); RunningElemNames.add("Altitude"); + RunningElemNames.add("Airspeed"); RunningElemNames.add("Stabilization"); RunningElemNames.add("AltitudeHold"); - RunningElemNames.add("Guidance"); - RunningElemNames.add("FlightPlan"); RunningElemNames.add("PathPlanner"); + RunningElemNames.add("PathFollower"); + RunningElemNames.add("FlightPlan"); RunningElemNames.add("Com2UsbBridge"); RunningElemNames.add("Usb2ComBridge"); RunningElemNames.add("OveroSync"); @@ -107,11 +109,12 @@ public class TaskInfo extends UAVDataObject { RunningTimeElemNames.add("GPS"); RunningTimeElemNames.add("ManualControl"); RunningTimeElemNames.add("Altitude"); + RunningTimeElemNames.add("Airspeed"); RunningTimeElemNames.add("Stabilization"); RunningTimeElemNames.add("AltitudeHold"); - RunningTimeElemNames.add("Guidance"); - RunningTimeElemNames.add("FlightPlan"); RunningTimeElemNames.add("PathPlanner"); + RunningTimeElemNames.add("PathFollower"); + RunningTimeElemNames.add("FlightPlan"); RunningTimeElemNames.add("Com2UsbBridge"); RunningTimeElemNames.add("Usb2ComBridge"); RunningTimeElemNames.add("OveroSync"); @@ -140,18 +143,17 @@ public class TaskInfo extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 10000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 10000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } @@ -190,7 +192,7 @@ public class TaskInfo extends UAVDataObject { } // Constants - protected static final int OBJID = 0x498F54BA; + protected static final int OBJID = 0xB81CD2AE; protected static final String NAME = "TaskInfo"; protected static String DESCRIPTION = "Task information"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java index 823643130..7968c37c3 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java @@ -45,11 +45,15 @@ public class UAVObjectsInitialize { objMngr.registerObject( new AltitudeHoldSettings() ); objMngr.registerObject( new AttitudeActual() ); objMngr.registerObject( new AttitudeSettings() ); + objMngr.registerObject( new AttitudeSimulated() ); + objMngr.registerObject( new BaroAirspeed() ); objMngr.registerObject( new BaroAltitude() ); objMngr.registerObject( new CameraDesired() ); objMngr.registerObject( new CameraStabSettings() ); objMngr.registerObject( new FaultSettings() ); objMngr.registerObject( new FirmwareIAPObj() ); + objMngr.registerObject( new FixedWingPathFollowerSettings() ); + objMngr.registerObject( new FixedWingPathFollowerStatus() ); objMngr.registerObject( new FlightBatterySettings() ); objMngr.registerObject( new FlightBatteryState() ); objMngr.registerObject( new FlightPlanControl() ); @@ -61,38 +65,45 @@ public class UAVObjectsInitialize { objMngr.registerObject( new GCSTelemetryStats() ); objMngr.registerObject( new GPSPosition() ); objMngr.registerObject( new GPSSatellites() ); + objMngr.registerObject( new GPSSettings() ); objMngr.registerObject( new GPSTime() ); objMngr.registerObject( new GPSVelocity() ); objMngr.registerObject( new Gyros() ); objMngr.registerObject( new GyrosBias() ); - objMngr.registerObject( new GuidanceSettings() ); objMngr.registerObject( new HomeLocation() ); objMngr.registerObject( new HwSettings() ); objMngr.registerObject( new I2CStats() ); - objMngr.registerObject( new GPSPosition() ); + objMngr.registerObject( new MagBias() ); objMngr.registerObject( new Magnetometer() ); objMngr.registerObject( new ManualControlCommand() ); objMngr.registerObject( new ManualControlSettings() ); objMngr.registerObject( new MixerSettings() ); objMngr.registerObject( new MixerStatus() ); - objMngr.registerObject( new NEDPosition() ); objMngr.registerObject( new NedAccel() ); + objMngr.registerObject( new NEDPosition() ); objMngr.registerObject( new ObjectPersistence() ); + objMngr.registerObject( new OveroSyncSettings() ); + objMngr.registerObject( new OveroSyncStats() ); objMngr.registerObject( new PathDesired() ); + objMngr.registerObject( new PathPlannerSettings() ); + objMngr.registerObject( new PipXSettings() ); + objMngr.registerObject( new PipXStatus() ); objMngr.registerObject( new PositionActual() ); - objMngr.registerObject( new PositionDesired() ); objMngr.registerObject( new RateDesired() ); objMngr.registerObject( new ReceiverActivity() ); + objMngr.registerObject( new RevoCalibration() ); + objMngr.registerObject( new RevoSettings() ); objMngr.registerObject( new SonarAltitude() ); objMngr.registerObject( new StabilizationDesired() ); objMngr.registerObject( new StabilizationSettings() ); objMngr.registerObject( new SystemAlarms() ); objMngr.registerObject( new SystemSettings() ); objMngr.registerObject( new SystemStats() ); - objMngr.registerObject( new TxPIDSettings() ); objMngr.registerObject( new TaskInfo() ); + objMngr.registerObject( new TxPIDSettings() ); objMngr.registerObject( new VelocityActual() ); objMngr.registerObject( new VelocityDesired() ); + objMngr.registerObject( new VtolPathFollowerSettings() ); objMngr.registerObject( new WatchdogStatus() ); objMngr.registerObject( new Waypoint() ); objMngr.registerObject( new WaypointActive() ); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java index 2a8cd3754..a545bca16 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java @@ -86,18 +86,17 @@ public class VelocityActual extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java index 436ef6448..f506a594c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java @@ -86,18 +86,17 @@ public class VelocityDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java index acbdb43d1..94e85f57b 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java @@ -82,18 +82,17 @@ public class WatchdogStatus extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 5000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 5000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 5000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 5000; + return metadata; } diff --git a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java index 64e2461f5..1283f03cb 100644 --- a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java +++ b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java @@ -74,18 +74,17 @@ $(FIELDSINIT) */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.$(GCSACCESS); - metadata.gcsTelemetryAcked = UAVObject.Acked.$(GCSTELEM_ACKEDTF); - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.$(GCSTELEM_UPDATEMODE); - metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD); - - metadata.flightAccess = UAVObject.AccessMode.$(FLIGHTACCESS); - metadata.flightTelemetryAcked = UAVObject.Acked.$(FLIGHTTELEM_ACKEDTF); - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.$(FLIGHTTELEM_UPDATEMODE); - metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD); - - metadata.loggingUpdateMode = UAVObject.UpdateMode.$(LOGGING_UPDATEMODE); - metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.$(FLIGHTACCESS)) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.$(GCSACCESS)) << UAVOBJ_GCS_ACCESS_SHIFT | + $(FLIGHTTELEM_ACKED) << UAVOBJ_TELEMETRY_ACKED_SHIFT | + $(GCSTELEM_ACKED) << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.$(FLIGHTTELEM_UPDATEMODE)) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.$(GCSTELEM_UPDATEMODE)) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD); + metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD); + metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD); + return metadata; } From 4233c7da0da1da2efd929b658f958a13ce34272f Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 2 Aug 2012 13:08:47 -0500 Subject: [PATCH 061/284] Forgot to initialize the fields for metadata --- androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java index c57b6c2fe..98a3bf8df 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java @@ -27,7 +27,8 @@ public class UAVMetaObject extends UAVObject { modesBitField.add("FlightUpdateOnChange"); modesBitField.add("GCSUpdatePeriodic"); modesBitField.add("GCSUpdateOnChange"); - + + List fields = new ArrayList(); fields.add( new UAVObjectField("Modes", "", UAVObjectField.FieldType.BITFIELD, 1, modesBitField) ); fields.add( new UAVObjectField("Flight Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); fields.add( new UAVObjectField("GCS Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); From cfb9f1277e3beefcfc77d9eb67141a3a9aac0584 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Fri, 3 Aug 2012 13:49:16 -0500 Subject: [PATCH 062/284] Catch invalid number decoding to cover cases where there is no IP address. --- .../src/org/openpilot/androidgcs/OPTelemetryService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 1a4b61eb8..917dfb116 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -72,8 +72,14 @@ public class OPTelemetryService extends Service { break; case MSG_CONNECT: terminate = false; + int connection_type; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); - int connection_type = Integer.decode(prefs.getString("connection_type", "")); + try { + connection_type = Integer.decode(prefs.getString("connection_type", "")); + } catch (NumberFormatException e) { + connection_type = 0; + } + switch(connection_type) { case 0: // No connection return; From 851923e8b92d25203ffa46233170140183464b2d Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 01:35:49 -0500 Subject: [PATCH 063/284] Update the UAVO files --- .../openpilot/uavtalk/uavobjects/Accels.java | 150 ++++++++ .../uavtalk/uavobjects/AltHoldSmoothed.java | 146 ++++++++ .../uavobjects/AltitudeHoldDesired.java | 150 ++++++++ .../uavobjects/AltitudeHoldSettings.java | 169 +++++++++ .../uavtalk/uavobjects/AttitudeSimulated.java | 174 ++++++++++ .../uavtalk/uavobjects/BaroAirspeed.java | 153 ++++++++ .../FixedWingPathFollowerSettings.java | 239 +++++++++++++ .../FixedWingPathFollowerStatus.java | 164 +++++++++ .../uavtalk/uavobjects/GPSSettings.java | 142 ++++++++ .../uavtalk/uavobjects/GPSVelocity.java | 146 ++++++++ .../openpilot/uavtalk/uavobjects/Gyros.java | 150 ++++++++ .../uavtalk/uavobjects/GyrosBias.java | 146 ++++++++ .../openpilot/uavtalk/uavobjects/MagBias.java | 146 ++++++++ .../uavtalk/uavobjects/Magnetometer.java | 146 ++++++++ .../uavtalk/uavobjects/NEDPosition.java | 146 ++++++++ .../uavtalk/uavobjects/OveroSyncSettings.java | 143 ++++++++ .../uavtalk/uavobjects/OveroSyncStats.java | 165 +++++++++ .../uavtalk/uavobjects/PathDesired.java | 162 +++++++++ .../uavobjects/PathPlannerSettings.java | 151 ++++++++ .../uavtalk/uavobjects/PipXSettings.java | 326 ++++++++++++++++++ .../uavtalk/uavobjects/PipXStatus.java | 301 ++++++++++++++++ .../uavtalk/uavobjects/RevoCalibration.java | 249 +++++++++++++ .../uavtalk/uavobjects/RevoSettings.java | 143 ++++++++ .../uavtalk/uavobjects/TxPIDSettings.java | 225 ++++++++++++ .../uavobjects/VtolPathFollowerSettings.java | 232 +++++++++++++ .../uavtalk/uavobjects/Waypoint.java | 159 +++++++++ .../uavtalk/uavobjects/WaypointActive.java | 138 ++++++++ 27 files changed, 4761 insertions(+) create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/Accels.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AltHoldSmoothed.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSimulated.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAirspeed.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerStatus.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSVelocity.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/Gyros.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GyrosBias.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/MagBias.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/Magnetometer.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/NEDPosition.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncStats.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PathDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PathPlannerSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXStatus.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoCalibration.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/TxPIDSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/VtolPathFollowerSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/Waypoint.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/WaypointActive.java diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/Accels.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Accels.java new file mode 100644 index 000000000..32437e63e --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Accels.java @@ -0,0 +1,150 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The accel data. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The accel data. + +generated from accels.xml + **/ +public class Accels extends UAVDataObject { + + public Accels() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List xElemNames = new ArrayList(); + xElemNames.add("0"); + fields.add( new UAVObjectField("x", "m/s^2", UAVObjectField.FieldType.FLOAT32, xElemNames, null) ); + + List yElemNames = new ArrayList(); + yElemNames.add("0"); + fields.add( new UAVObjectField("y", "m/s^2", UAVObjectField.FieldType.FLOAT32, yElemNames, null) ); + + List zElemNames = new ArrayList(); + zElemNames.add("0"); + fields.add( new UAVObjectField("z", "m/s^2", UAVObjectField.FieldType.FLOAT32, zElemNames, null) ); + + List temperatureElemNames = new ArrayList(); + temperatureElemNames.add("0"); + fields.add( new UAVObjectField("temperature", "deg C", UAVObjectField.FieldType.FLOAT32, temperatureElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + Accels obj = new Accels(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public Accels GetInstance(UAVObjectManager objMngr, int instID) + { + return (Accels)(objMngr.getObject(Accels.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xDD9D5FC0; + protected static final String NAME = "Accels"; + protected static String DESCRIPTION = "The accel data."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltHoldSmoothed.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltHoldSmoothed.java new file mode 100644 index 000000000..46d03a544 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltHoldSmoothed.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The output on the kalman filter on altitude. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The output on the kalman filter on altitude. + +generated from altholdsmoothed.xml + **/ +public class AltHoldSmoothed extends UAVDataObject { + + public AltHoldSmoothed() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AltitudeElemNames = new ArrayList(); + AltitudeElemNames.add("0"); + fields.add( new UAVObjectField("Altitude", "m", UAVObjectField.FieldType.FLOAT32, AltitudeElemNames, null) ); + + List VelocityElemNames = new ArrayList(); + VelocityElemNames.add("0"); + fields.add( new UAVObjectField("Velocity", "m/s", UAVObjectField.FieldType.FLOAT32, VelocityElemNames, null) ); + + List AccelElemNames = new ArrayList(); + AccelElemNames.add("0"); + fields.add( new UAVObjectField("Accel", "m/s^2", UAVObjectField.FieldType.FLOAT32, AccelElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AltHoldSmoothed obj = new AltHoldSmoothed(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AltHoldSmoothed GetInstance(UAVObjectManager objMngr, int instID) + { + return (AltHoldSmoothed)(objMngr.getObject(AltHoldSmoothed.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x2BC6B9D2; + protected static final String NAME = "AltHoldSmoothed"; + protected static String DESCRIPTION = "The output on the kalman filter on altitude."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldDesired.java new file mode 100644 index 000000000..efe860340 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldDesired.java @@ -0,0 +1,150 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Holds the desired altitude (from manual control) as well as the desired attitude to pass through + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Holds the desired altitude (from manual control) as well as the desired attitude to pass through + +generated from altitudeholddesired.xml + **/ +public class AltitudeHoldDesired extends UAVDataObject { + + public AltitudeHoldDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AltitudeElemNames = new ArrayList(); + AltitudeElemNames.add("0"); + fields.add( new UAVObjectField("Altitude", "m", UAVObjectField.FieldType.FLOAT32, AltitudeElemNames, null) ); + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "deg", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "deg", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "deg/s", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AltitudeHoldDesired obj = new AltitudeHoldDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AltitudeHoldDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (AltitudeHoldDesired)(objMngr.getObject(AltitudeHoldDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x495BAD6E; + protected static final String NAME = "AltitudeHoldDesired"; + protected static String DESCRIPTION = "Holds the desired altitude (from manual control) as well as the desired attitude to pass through"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldSettings.java new file mode 100644 index 000000000..77b6774b9 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldSettings.java @@ -0,0 +1,169 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref AltitudeHold module + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref AltitudeHold module + +generated from altitudeholdsettings.xml + **/ +public class AltitudeHoldSettings extends UAVDataObject { + + public AltitudeHoldSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List KpElemNames = new ArrayList(); + KpElemNames.add("0"); + fields.add( new UAVObjectField("Kp", "throttle/m", UAVObjectField.FieldType.FLOAT32, KpElemNames, null) ); + + List KiElemNames = new ArrayList(); + KiElemNames.add("0"); + fields.add( new UAVObjectField("Ki", "throttle/m", UAVObjectField.FieldType.FLOAT32, KiElemNames, null) ); + + List KdElemNames = new ArrayList(); + KdElemNames.add("0"); + fields.add( new UAVObjectField("Kd", "throttle/m", UAVObjectField.FieldType.FLOAT32, KdElemNames, null) ); + + List KaElemNames = new ArrayList(); + KaElemNames.add("0"); + fields.add( new UAVObjectField("Ka", "throttle/(m/s^2)", UAVObjectField.FieldType.FLOAT32, KaElemNames, null) ); + + List PressureNoiseElemNames = new ArrayList(); + PressureNoiseElemNames.add("0"); + fields.add( new UAVObjectField("PressureNoise", "m", UAVObjectField.FieldType.FLOAT32, PressureNoiseElemNames, null) ); + + List AccelNoiseElemNames = new ArrayList(); + AccelNoiseElemNames.add("0"); + fields.add( new UAVObjectField("AccelNoise", "m/s^2", UAVObjectField.FieldType.FLOAT32, AccelNoiseElemNames, null) ); + + List AccelDriftElemNames = new ArrayList(); + AccelDriftElemNames.add("0"); + fields.add( new UAVObjectField("AccelDrift", "m/s^2", UAVObjectField.FieldType.FLOAT32, AccelDriftElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Kp").setValue(0.03); + getField("Ki").setValue(0); + getField("Kd").setValue(0.03); + getField("Ka").setValue(0.005); + getField("PressureNoise").setValue(0.4); + getField("AccelNoise").setValue(5); + getField("AccelDrift").setValue(0.001); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AltitudeHoldSettings obj = new AltitudeHoldSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AltitudeHoldSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (AltitudeHoldSettings)(objMngr.getObject(AltitudeHoldSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xFEC55B42; + protected static final String NAME = "AltitudeHoldSettings"; + protected static String DESCRIPTION = "Settings for the @ref AltitudeHold module"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSimulated.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSimulated.java new file mode 100644 index 000000000..3a713ab04 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSimulated.java @@ -0,0 +1,174 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The simulated Attitude estimation from @ref Sensors. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The simulated Attitude estimation from @ref Sensors. + +generated from attitudesimulated.xml + **/ +public class AttitudeSimulated extends UAVDataObject { + + public AttitudeSimulated() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List q1ElemNames = new ArrayList(); + q1ElemNames.add("0"); + fields.add( new UAVObjectField("q1", "", UAVObjectField.FieldType.FLOAT32, q1ElemNames, null) ); + + List q2ElemNames = new ArrayList(); + q2ElemNames.add("0"); + fields.add( new UAVObjectField("q2", "", UAVObjectField.FieldType.FLOAT32, q2ElemNames, null) ); + + List q3ElemNames = new ArrayList(); + q3ElemNames.add("0"); + fields.add( new UAVObjectField("q3", "", UAVObjectField.FieldType.FLOAT32, q3ElemNames, null) ); + + List q4ElemNames = new ArrayList(); + q4ElemNames.add("0"); + fields.add( new UAVObjectField("q4", "", UAVObjectField.FieldType.FLOAT32, q4ElemNames, null) ); + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "degrees", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "degrees", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "degrees", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + List VelocityElemNames = new ArrayList(); + VelocityElemNames.add("North"); + VelocityElemNames.add("East"); + VelocityElemNames.add("Down"); + fields.add( new UAVObjectField("Velocity", "m/s", UAVObjectField.FieldType.FLOAT32, VelocityElemNames, null) ); + + List PositionElemNames = new ArrayList(); + PositionElemNames.add("North"); + PositionElemNames.add("East"); + PositionElemNames.add("Down"); + fields.add( new UAVObjectField("Position", "m", UAVObjectField.FieldType.FLOAT32, PositionElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 100; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AttitudeSimulated obj = new AttitudeSimulated(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AttitudeSimulated GetInstance(UAVObjectManager objMngr, int instID) + { + return (AttitudeSimulated)(objMngr.getObject(AttitudeSimulated.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x9266CE74; + protected static final String NAME = "AttitudeSimulated"; + protected static String DESCRIPTION = "The simulated Attitude estimation from @ref Sensors."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAirspeed.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAirspeed.java new file mode 100644 index 000000000..439915741 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAirspeed.java @@ -0,0 +1,153 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The raw data from the dynamic pressure sensor with pressure, temperature and airspeed. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The raw data from the dynamic pressure sensor with pressure, temperature and airspeed. + +generated from baroairspeed.xml + **/ +public class BaroAirspeed extends UAVDataObject { + + public BaroAirspeed() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AirspeedElemNames = new ArrayList(); + AirspeedElemNames.add("0"); + fields.add( new UAVObjectField("Airspeed", "m/s", UAVObjectField.FieldType.FLOAT32, AirspeedElemNames, null) ); + + List SensorValueElemNames = new ArrayList(); + SensorValueElemNames.add("0"); + fields.add( new UAVObjectField("SensorValue", "raw", UAVObjectField.FieldType.UINT16, SensorValueElemNames, null) ); + + List ZeroPointElemNames = new ArrayList(); + ZeroPointElemNames.add("0"); + fields.add( new UAVObjectField("ZeroPoint", "raw", UAVObjectField.FieldType.UINT16, ZeroPointElemNames, null) ); + + List ConnectedElemNames = new ArrayList(); + ConnectedElemNames.add("0"); + List ConnectedEnumOptions = new ArrayList(); + ConnectedEnumOptions.add("False"); + ConnectedEnumOptions.add("True"); + fields.add( new UAVObjectField("Connected", "", UAVObjectField.FieldType.ENUM, ConnectedElemNames, ConnectedEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + BaroAirspeed obj = new BaroAirspeed(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public BaroAirspeed GetInstance(UAVObjectManager objMngr, int instID) + { + return (BaroAirspeed)(objMngr.getObject(BaroAirspeed.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x169EA4A; + protected static final String NAME = "BaroAirspeed"; + protected static String DESCRIPTION = "The raw data from the dynamic pressure sensor with pressure, temperature and airspeed."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerSettings.java new file mode 100644 index 000000000..00419bc4c --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerSettings.java @@ -0,0 +1,239 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref FixedWingPathFollowerModule + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref FixedWingPathFollowerModule + +generated from fixedwingpathfollowersettings.xml + **/ +public class FixedWingPathFollowerSettings extends UAVDataObject { + + public FixedWingPathFollowerSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AirSpeedMaxElemNames = new ArrayList(); + AirSpeedMaxElemNames.add("0"); + fields.add( new UAVObjectField("AirSpeedMax", "m/s", UAVObjectField.FieldType.FLOAT32, AirSpeedMaxElemNames, null) ); + + List AirSpeedMinElemNames = new ArrayList(); + AirSpeedMinElemNames.add("0"); + fields.add( new UAVObjectField("AirSpeedMin", "m/s", UAVObjectField.FieldType.FLOAT32, AirSpeedMinElemNames, null) ); + + List VerticalVelMaxElemNames = new ArrayList(); + VerticalVelMaxElemNames.add("0"); + fields.add( new UAVObjectField("VerticalVelMax", "m/s", UAVObjectField.FieldType.FLOAT32, VerticalVelMaxElemNames, null) ); + + List HorizontalPosPElemNames = new ArrayList(); + HorizontalPosPElemNames.add("0"); + fields.add( new UAVObjectField("HorizontalPosP", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, HorizontalPosPElemNames, null) ); + + List VerticalPosPElemNames = new ArrayList(); + VerticalPosPElemNames.add("0"); + fields.add( new UAVObjectField("VerticalPosP", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, VerticalPosPElemNames, null) ); + + List CoursePIElemNames = new ArrayList(); + CoursePIElemNames.add("Kp"); + CoursePIElemNames.add("Ki"); + CoursePIElemNames.add("ILimit"); + fields.add( new UAVObjectField("CoursePI", "deg/deg", UAVObjectField.FieldType.FLOAT32, CoursePIElemNames, null) ); + + List SpeedPElemNames = new ArrayList(); + SpeedPElemNames.add("Kp"); + SpeedPElemNames.add("Max"); + fields.add( new UAVObjectField("SpeedP", "(m/s^2) / ((m/s)/(m/s)", UAVObjectField.FieldType.FLOAT32, SpeedPElemNames, null) ); + + List AccelPIElemNames = new ArrayList(); + AccelPIElemNames.add("Kp"); + AccelPIElemNames.add("Ki"); + AccelPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("AccelPI", "deg / (m/s^2)", UAVObjectField.FieldType.FLOAT32, AccelPIElemNames, null) ); + + List VerticalToPitchCrossFeedElemNames = new ArrayList(); + VerticalToPitchCrossFeedElemNames.add("Kp"); + VerticalToPitchCrossFeedElemNames.add("Max"); + fields.add( new UAVObjectField("VerticalToPitchCrossFeed", "deg / ((m/s)/(m/s))", UAVObjectField.FieldType.FLOAT32, VerticalToPitchCrossFeedElemNames, null) ); + + List AirspeedToVerticalCrossFeedElemNames = new ArrayList(); + AirspeedToVerticalCrossFeedElemNames.add("Kp"); + AirspeedToVerticalCrossFeedElemNames.add("Max"); + fields.add( new UAVObjectField("AirspeedToVerticalCrossFeed", "(m/s) / ((m/s)/(m/s))", UAVObjectField.FieldType.FLOAT32, AirspeedToVerticalCrossFeedElemNames, null) ); + + List PowerPIElemNames = new ArrayList(); + PowerPIElemNames.add("Kp"); + PowerPIElemNames.add("Ki"); + PowerPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("PowerPI", "1/(m/s)", UAVObjectField.FieldType.FLOAT32, PowerPIElemNames, null) ); + + List RollLimitElemNames = new ArrayList(); + RollLimitElemNames.add("Min"); + RollLimitElemNames.add("Neutral"); + RollLimitElemNames.add("Max"); + fields.add( new UAVObjectField("RollLimit", "deg", UAVObjectField.FieldType.FLOAT32, RollLimitElemNames, null) ); + + List PitchLimitElemNames = new ArrayList(); + PitchLimitElemNames.add("Min"); + PitchLimitElemNames.add("Neutral"); + PitchLimitElemNames.add("Max"); + fields.add( new UAVObjectField("PitchLimit", "deg", UAVObjectField.FieldType.FLOAT32, PitchLimitElemNames, null) ); + + List ThrottleLimitElemNames = new ArrayList(); + ThrottleLimitElemNames.add("Min"); + ThrottleLimitElemNames.add("Neutral"); + ThrottleLimitElemNames.add("Max"); + fields.add( new UAVObjectField("ThrottleLimit", "", UAVObjectField.FieldType.FLOAT32, ThrottleLimitElemNames, null) ); + + List UpdatePeriodElemNames = new ArrayList(); + UpdatePeriodElemNames.add("0"); + fields.add( new UAVObjectField("UpdatePeriod", "ms", UAVObjectField.FieldType.INT32, UpdatePeriodElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("AirSpeedMax").setValue(15); + getField("AirSpeedMin").setValue(10); + getField("VerticalVelMax").setValue(10); + getField("HorizontalPosP").setValue(0.05); + getField("VerticalPosP").setValue(0.05); + getField("CoursePI").setValue(0.2,0); + getField("CoursePI").setValue(0,1); + getField("CoursePI").setValue(0,2); + getField("SpeedP").setValue(10,0); + getField("SpeedP").setValue(10,1); + getField("AccelPI").setValue(1.5,0); + getField("AccelPI").setValue(1.5,1); + getField("AccelPI").setValue(20,2); + getField("VerticalToPitchCrossFeed").setValue(50,0); + getField("VerticalToPitchCrossFeed").setValue(5,1); + getField("AirspeedToVerticalCrossFeed").setValue(100,0); + getField("AirspeedToVerticalCrossFeed").setValue(100,1); + getField("PowerPI").setValue(0.01,0); + getField("PowerPI").setValue(0.01,1); + getField("PowerPI").setValue(0.8,2); + getField("RollLimit").setValue(-35,0); + getField("RollLimit").setValue(0,1); + getField("RollLimit").setValue(35,2); + getField("PitchLimit").setValue(-10,0); + getField("PitchLimit").setValue(5,1); + getField("PitchLimit").setValue(20,2); + getField("ThrottleLimit").setValue(0.1,0); + getField("ThrottleLimit").setValue(0.5,1); + getField("ThrottleLimit").setValue(0.9,2); + getField("UpdatePeriod").setValue(100); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FixedWingPathFollowerSettings obj = new FixedWingPathFollowerSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FixedWingPathFollowerSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (FixedWingPathFollowerSettings)(objMngr.getObject(FixedWingPathFollowerSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x8A3F1E02; + protected static final String NAME = "FixedWingPathFollowerSettings"; + protected static String DESCRIPTION = "Settings for the @ref FixedWingPathFollowerModule"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerStatus.java new file mode 100644 index 000000000..a40be35cf --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerStatus.java @@ -0,0 +1,164 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Object Storing Debugging Information on PID internals + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Object Storing Debugging Information on PID internals + +generated from fixedwingpathfollowerstatus.xml + **/ +public class FixedWingPathFollowerStatus extends UAVDataObject { + + public FixedWingPathFollowerStatus() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List EElemNames = new ArrayList(); + EElemNames.add("Course"); + EElemNames.add("Speed"); + EElemNames.add("Accel"); + EElemNames.add("Power"); + fields.add( new UAVObjectField("E", "", UAVObjectField.FieldType.FLOAT32, EElemNames, null) ); + + List AElemNames = new ArrayList(); + AElemNames.add("Course"); + AElemNames.add("Speed"); + AElemNames.add("Accel"); + AElemNames.add("Power"); + fields.add( new UAVObjectField("A", "", UAVObjectField.FieldType.FLOAT32, AElemNames, null) ); + + List CElemNames = new ArrayList(); + CElemNames.add("Course"); + CElemNames.add("Speed"); + CElemNames.add("Accel"); + CElemNames.add("Power"); + fields.add( new UAVObjectField("C", "", UAVObjectField.FieldType.FLOAT32, CElemNames, null) ); + + List ErrorsElemNames = new ArrayList(); + ErrorsElemNames.add("Wind"); + ErrorsElemNames.add("Lowspeed"); + ErrorsElemNames.add("Highspeed"); + ErrorsElemNames.add("Lowpower"); + ErrorsElemNames.add("Highpower"); + ErrorsElemNames.add("Pitchcontrol"); + fields.add( new UAVObjectField("Errors", "", UAVObjectField.FieldType.UINT8, ErrorsElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 500; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FixedWingPathFollowerStatus obj = new FixedWingPathFollowerStatus(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FixedWingPathFollowerStatus GetInstance(UAVObjectManager objMngr, int instID) + { + return (FixedWingPathFollowerStatus)(objMngr.getObject(FixedWingPathFollowerStatus.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xA0D6F6D4; + protected static final String NAME = "FixedWingPathFollowerStatus"; + protected static String DESCRIPTION = "Object Storing Debugging Information on PID internals"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSettings.java new file mode 100644 index 000000000..f534fc89c --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSettings.java @@ -0,0 +1,142 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the GPS + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the GPS + +generated from gpssettings.xml + **/ +public class GPSSettings extends UAVDataObject { + + public GPSSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List DataProtocolElemNames = new ArrayList(); + DataProtocolElemNames.add("0"); + List DataProtocolEnumOptions = new ArrayList(); + DataProtocolEnumOptions.add("NMEA"); + DataProtocolEnumOptions.add("UBX"); + fields.add( new UAVObjectField("DataProtocol", "", UAVObjectField.FieldType.ENUM, DataProtocolElemNames, DataProtocolEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("DataProtocol").setValue("NMEA"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GPSSettings obj = new GPSSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GPSSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (GPSSettings)(objMngr.getObject(GPSSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xAC5F6370; + protected static final String NAME = "GPSSettings"; + protected static String DESCRIPTION = "Settings for the GPS"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSVelocity.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSVelocity.java new file mode 100644 index 000000000..2ce4a3c62 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSVelocity.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Raw GPS data from @ref GPSModule. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Raw GPS data from @ref GPSModule. + +generated from gpsvelocity.xml + **/ +public class GPSVelocity extends UAVDataObject { + + public GPSVelocity() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List NorthElemNames = new ArrayList(); + NorthElemNames.add("0"); + fields.add( new UAVObjectField("North", "m/s", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); + + List EastElemNames = new ArrayList(); + EastElemNames.add("0"); + fields.add( new UAVObjectField("East", "m/s", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); + + List DownElemNames = new ArrayList(); + DownElemNames.add("0"); + fields.add( new UAVObjectField("Down", "m/s", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GPSVelocity obj = new GPSVelocity(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GPSVelocity GetInstance(UAVObjectManager objMngr, int instID) + { + return (GPSVelocity)(objMngr.getObject(GPSVelocity.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x8245DC80; + protected static final String NAME = "GPSVelocity"; + protected static String DESCRIPTION = "Raw GPS data from @ref GPSModule."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/Gyros.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Gyros.java new file mode 100644 index 000000000..5c960d2e6 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Gyros.java @@ -0,0 +1,150 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The gyro data. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The gyro data. + +generated from gyros.xml + **/ +public class Gyros extends UAVDataObject { + + public Gyros() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List xElemNames = new ArrayList(); + xElemNames.add("0"); + fields.add( new UAVObjectField("x", "deg/s", UAVObjectField.FieldType.FLOAT32, xElemNames, null) ); + + List yElemNames = new ArrayList(); + yElemNames.add("0"); + fields.add( new UAVObjectField("y", "deg/s", UAVObjectField.FieldType.FLOAT32, yElemNames, null) ); + + List zElemNames = new ArrayList(); + zElemNames.add("0"); + fields.add( new UAVObjectField("z", "deg/s", UAVObjectField.FieldType.FLOAT32, zElemNames, null) ); + + List temperatureElemNames = new ArrayList(); + temperatureElemNames.add("0"); + fields.add( new UAVObjectField("temperature", "deg C", UAVObjectField.FieldType.FLOAT32, temperatureElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + Gyros obj = new Gyros(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public Gyros GetInstance(UAVObjectManager objMngr, int instID) + { + return (Gyros)(objMngr.getObject(Gyros.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x4228AF6; + protected static final String NAME = "Gyros"; + protected static String DESCRIPTION = "The gyro data."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GyrosBias.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GyrosBias.java new file mode 100644 index 000000000..00bc7da2d --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GyrosBias.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The gyro data. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The gyro data. + +generated from gyrosbias.xml + **/ +public class GyrosBias extends UAVDataObject { + + public GyrosBias() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List xElemNames = new ArrayList(); + xElemNames.add("0"); + fields.add( new UAVObjectField("x", "deg/s", UAVObjectField.FieldType.FLOAT32, xElemNames, null) ); + + List yElemNames = new ArrayList(); + yElemNames.add("0"); + fields.add( new UAVObjectField("y", "deg/s", UAVObjectField.FieldType.FLOAT32, yElemNames, null) ); + + List zElemNames = new ArrayList(); + zElemNames.add("0"); + fields.add( new UAVObjectField("z", "deg/s", UAVObjectField.FieldType.FLOAT32, zElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GyrosBias obj = new GyrosBias(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GyrosBias GetInstance(UAVObjectManager objMngr, int instID) + { + return (GyrosBias)(objMngr.getObject(GyrosBias.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xE4B6F980; + protected static final String NAME = "GyrosBias"; + protected static String DESCRIPTION = "The gyro data."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MagBias.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MagBias.java new file mode 100644 index 000000000..398f455d5 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MagBias.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The gyro data. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The gyro data. + +generated from magbias.xml + **/ +public class MagBias extends UAVDataObject { + + public MagBias() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List xElemNames = new ArrayList(); + xElemNames.add("0"); + fields.add( new UAVObjectField("x", "mGau", UAVObjectField.FieldType.FLOAT32, xElemNames, null) ); + + List yElemNames = new ArrayList(); + yElemNames.add("0"); + fields.add( new UAVObjectField("y", "mGau", UAVObjectField.FieldType.FLOAT32, yElemNames, null) ); + + List zElemNames = new ArrayList(); + zElemNames.add("0"); + fields.add( new UAVObjectField("z", "mGau", UAVObjectField.FieldType.FLOAT32, zElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + MagBias obj = new MagBias(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public MagBias GetInstance(UAVObjectManager objMngr, int instID) + { + return (MagBias)(objMngr.getObject(MagBias.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x5043E510; + protected static final String NAME = "MagBias"; + protected static String DESCRIPTION = "The gyro data."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/Magnetometer.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Magnetometer.java new file mode 100644 index 000000000..583817cca --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Magnetometer.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The mag data. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The mag data. + +generated from magnetometer.xml + **/ +public class Magnetometer extends UAVDataObject { + + public Magnetometer() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List xElemNames = new ArrayList(); + xElemNames.add("0"); + fields.add( new UAVObjectField("x", "mGa", UAVObjectField.FieldType.FLOAT32, xElemNames, null) ); + + List yElemNames = new ArrayList(); + yElemNames.add("0"); + fields.add( new UAVObjectField("y", "mGa", UAVObjectField.FieldType.FLOAT32, yElemNames, null) ); + + List zElemNames = new ArrayList(); + zElemNames.add("0"); + fields.add( new UAVObjectField("z", "mGa", UAVObjectField.FieldType.FLOAT32, zElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + Magnetometer obj = new Magnetometer(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public Magnetometer GetInstance(UAVObjectManager objMngr, int instID) + { + return (Magnetometer)(objMngr.getObject(Magnetometer.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x813B55DE; + protected static final String NAME = "Magnetometer"; + protected static String DESCRIPTION = "The mag data."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NEDPosition.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NEDPosition.java new file mode 100644 index 000000000..0aa67862e --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NEDPosition.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Contains the current position relative to @ref HomeLocation + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Contains the current position relative to @ref HomeLocation + +generated from nedposition.xml + **/ +public class NEDPosition extends UAVDataObject { + + public NEDPosition() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List NorthElemNames = new ArrayList(); + NorthElemNames.add("0"); + fields.add( new UAVObjectField("North", "m", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); + + List EastElemNames = new ArrayList(); + EastElemNames.add("0"); + fields.add( new UAVObjectField("East", "m", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); + + List DownElemNames = new ArrayList(); + DownElemNames.add("0"); + fields.add( new UAVObjectField("Down", "m", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + NEDPosition obj = new NEDPosition(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public NEDPosition GetInstance(UAVObjectManager objMngr, int instID) + { + return (NEDPosition)(objMngr.getObject(NEDPosition.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x1FB15A00; + protected static final String NAME = "NEDPosition"; + protected static String DESCRIPTION = "Contains the current position relative to @ref HomeLocation"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncSettings.java new file mode 100644 index 000000000..c680d230c --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncSettings.java @@ -0,0 +1,143 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings to control the behavior of the overo sync module + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings to control the behavior of the overo sync module + +generated from overosyncsettings.xml + **/ +public class OveroSyncSettings extends UAVDataObject { + + public OveroSyncSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List LogOnElemNames = new ArrayList(); + LogOnElemNames.add("0"); + List LogOnEnumOptions = new ArrayList(); + LogOnEnumOptions.add("Never"); + LogOnEnumOptions.add("Always"); + LogOnEnumOptions.add("Armed"); + fields.add( new UAVObjectField("LogOn", "", UAVObjectField.FieldType.ENUM, LogOnElemNames, LogOnEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("LogOn").setValue("Armed"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + OveroSyncSettings obj = new OveroSyncSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public OveroSyncSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (OveroSyncSettings)(objMngr.getObject(OveroSyncSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xA1ABC278; + protected static final String NAME = "OveroSyncSettings"; + protected static String DESCRIPTION = "Settings to control the behavior of the overo sync module"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncStats.java new file mode 100644 index 000000000..4c31f21dd --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncStats.java @@ -0,0 +1,165 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Maintains statistics on transfer rate to and from over + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Maintains statistics on transfer rate to and from over + +generated from overosyncstats.xml + **/ +public class OveroSyncStats extends UAVDataObject { + + public OveroSyncStats() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List SendElemNames = new ArrayList(); + SendElemNames.add("0"); + fields.add( new UAVObjectField("Send", "B/s", UAVObjectField.FieldType.UINT32, SendElemNames, null) ); + + List ReceivedElemNames = new ArrayList(); + ReceivedElemNames.add("0"); + fields.add( new UAVObjectField("Received", "B/s", UAVObjectField.FieldType.UINT32, ReceivedElemNames, null) ); + + List FramesyncErrorsElemNames = new ArrayList(); + FramesyncErrorsElemNames.add("0"); + fields.add( new UAVObjectField("FramesyncErrors", "count", UAVObjectField.FieldType.UINT32, FramesyncErrorsElemNames, null) ); + + List UnderrunErrorsElemNames = new ArrayList(); + UnderrunErrorsElemNames.add("0"); + fields.add( new UAVObjectField("UnderrunErrors", "count", UAVObjectField.FieldType.UINT32, UnderrunErrorsElemNames, null) ); + + List DroppedUpdatesElemNames = new ArrayList(); + DroppedUpdatesElemNames.add("0"); + fields.add( new UAVObjectField("DroppedUpdates", "", UAVObjectField.FieldType.UINT32, DroppedUpdatesElemNames, null) ); + + List PacketsElemNames = new ArrayList(); + PacketsElemNames.add("0"); + fields.add( new UAVObjectField("Packets", "", UAVObjectField.FieldType.UINT32, PacketsElemNames, null) ); + + List ConnectedElemNames = new ArrayList(); + ConnectedElemNames.add("0"); + List ConnectedEnumOptions = new ArrayList(); + ConnectedEnumOptions.add("False"); + ConnectedEnumOptions.add("True"); + fields.add( new UAVObjectField("Connected", "", UAVObjectField.FieldType.ENUM, ConnectedElemNames, ConnectedEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + OveroSyncStats obj = new OveroSyncStats(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public OveroSyncStats GetInstance(UAVObjectManager objMngr, int instID) + { + return (OveroSyncStats)(objMngr.getObject(OveroSyncStats.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xD2085FAC; + protected static final String NAME = "OveroSyncStats"; + protected static String DESCRIPTION = "Maintains statistics on transfer rate to and from over"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathDesired.java new file mode 100644 index 000000000..38e710477 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathDesired.java @@ -0,0 +1,162 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The endpoint or path the craft is trying to achieve. Can come from @ref ManualControl or @ref PathPlanner + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The endpoint or path the craft is trying to achieve. Can come from @ref ManualControl or @ref PathPlanner + +generated from pathdesired.xml + **/ +public class PathDesired extends UAVDataObject { + + public PathDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List StartElemNames = new ArrayList(); + StartElemNames.add("North"); + StartElemNames.add("East"); + StartElemNames.add("Down"); + fields.add( new UAVObjectField("Start", "m", UAVObjectField.FieldType.FLOAT32, StartElemNames, null) ); + + List EndElemNames = new ArrayList(); + EndElemNames.add("North"); + EndElemNames.add("East"); + EndElemNames.add("Down"); + fields.add( new UAVObjectField("End", "m", UAVObjectField.FieldType.FLOAT32, EndElemNames, null) ); + + List StartingVelocityElemNames = new ArrayList(); + StartingVelocityElemNames.add("0"); + fields.add( new UAVObjectField("StartingVelocity", "m/s", UAVObjectField.FieldType.FLOAT32, StartingVelocityElemNames, null) ); + + List EndingVelocityElemNames = new ArrayList(); + EndingVelocityElemNames.add("0"); + fields.add( new UAVObjectField("EndingVelocity", "m/s", UAVObjectField.FieldType.FLOAT32, EndingVelocityElemNames, null) ); + + List ModeElemNames = new ArrayList(); + ModeElemNames.add("0"); + List ModeEnumOptions = new ArrayList(); + ModeEnumOptions.add("Endpoint"); + ModeEnumOptions.add("Path"); + ModeEnumOptions.add("Land"); + fields.add( new UAVObjectField("Mode", "", UAVObjectField.FieldType.ENUM, ModeElemNames, ModeEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + PathDesired obj = new PathDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public PathDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (PathDesired)(objMngr.getObject(PathDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x5A4DC71A; + protected static final String NAME = "PathDesired"; + protected static String DESCRIPTION = "The endpoint or path the craft is trying to achieve. Can come from @ref ManualControl or @ref PathPlanner "; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathPlannerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathPlannerSettings.java new file mode 100644 index 000000000..fb6b66e19 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathPlannerSettings.java @@ -0,0 +1,151 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref PathPlanner Module + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref PathPlanner Module + +generated from pathplannersettings.xml + **/ +public class PathPlannerSettings extends UAVDataObject { + + public PathPlannerSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List PathModeElemNames = new ArrayList(); + PathModeElemNames.add("0"); + List PathModeEnumOptions = new ArrayList(); + PathModeEnumOptions.add("ENDPOINT"); + PathModeEnumOptions.add("PATH"); + fields.add( new UAVObjectField("PathMode", "", UAVObjectField.FieldType.ENUM, PathModeElemNames, PathModeEnumOptions) ); + + List PreprogrammedPathElemNames = new ArrayList(); + PreprogrammedPathElemNames.add("0"); + List PreprogrammedPathEnumOptions = new ArrayList(); + PreprogrammedPathEnumOptions.add("NONE"); + PreprogrammedPathEnumOptions.add("10M_BOX"); + PreprogrammedPathEnumOptions.add("LOGO"); + fields.add( new UAVObjectField("PreprogrammedPath", "", UAVObjectField.FieldType.ENUM, PreprogrammedPathElemNames, PreprogrammedPathEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("PathMode").setValue("PATH"); + getField("PreprogrammedPath").setValue("NONE"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + PathPlannerSettings obj = new PathPlannerSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public PathPlannerSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (PathPlannerSettings)(objMngr.getObject(PathPlannerSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x290E45DA; + protected static final String NAME = "PathPlannerSettings"; + protected static String DESCRIPTION = "Settings for the @ref PathPlanner Module"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXSettings.java new file mode 100644 index 000000000..aa5387148 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXSettings.java @@ -0,0 +1,326 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * PipXtreme configurations options. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +PipXtreme configurations options. + +generated from pipxsettings.xml + **/ +public class PipXSettings extends UAVDataObject { + + public PipXSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List PairIDElemNames = new ArrayList(); + PairIDElemNames.add("0"); + fields.add( new UAVObjectField("PairID", "", UAVObjectField.FieldType.UINT32, PairIDElemNames, null) ); + + List FrequencyElemNames = new ArrayList(); + FrequencyElemNames.add("0"); + fields.add( new UAVObjectField("Frequency", "", UAVObjectField.FieldType.UINT32, FrequencyElemNames, null) ); + + List SendTimeoutElemNames = new ArrayList(); + SendTimeoutElemNames.add("0"); + fields.add( new UAVObjectField("SendTimeout", "ms", UAVObjectField.FieldType.UINT16, SendTimeoutElemNames, null) ); + + List TelemetryConfigElemNames = new ArrayList(); + TelemetryConfigElemNames.add("0"); + List TelemetryConfigEnumOptions = new ArrayList(); + TelemetryConfigEnumOptions.add("Disabled"); + TelemetryConfigEnumOptions.add("Serial"); + TelemetryConfigEnumOptions.add("UAVTalk"); + TelemetryConfigEnumOptions.add("GCS"); + TelemetryConfigEnumOptions.add("Debug"); + fields.add( new UAVObjectField("TelemetryConfig", "function", UAVObjectField.FieldType.ENUM, TelemetryConfigElemNames, TelemetryConfigEnumOptions) ); + + List TelemetrySpeedElemNames = new ArrayList(); + TelemetrySpeedElemNames.add("0"); + List TelemetrySpeedEnumOptions = new ArrayList(); + TelemetrySpeedEnumOptions.add("2400"); + TelemetrySpeedEnumOptions.add("4800"); + TelemetrySpeedEnumOptions.add("9600"); + TelemetrySpeedEnumOptions.add("19200"); + TelemetrySpeedEnumOptions.add("38400"); + TelemetrySpeedEnumOptions.add("57600"); + TelemetrySpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("TelemetrySpeed", "bps", UAVObjectField.FieldType.ENUM, TelemetrySpeedElemNames, TelemetrySpeedEnumOptions) ); + + List FlexiConfigElemNames = new ArrayList(); + FlexiConfigElemNames.add("0"); + List FlexiConfigEnumOptions = new ArrayList(); + FlexiConfigEnumOptions.add("Disabled"); + FlexiConfigEnumOptions.add("Serial"); + FlexiConfigEnumOptions.add("UAVTalk"); + FlexiConfigEnumOptions.add("GCS"); + FlexiConfigEnumOptions.add("PPM_In"); + FlexiConfigEnumOptions.add("PPM_Out"); + FlexiConfigEnumOptions.add("RSSI"); + FlexiConfigEnumOptions.add("Debug"); + fields.add( new UAVObjectField("FlexiConfig", "function", UAVObjectField.FieldType.ENUM, FlexiConfigElemNames, FlexiConfigEnumOptions) ); + + List FlexiSpeedElemNames = new ArrayList(); + FlexiSpeedElemNames.add("0"); + List FlexiSpeedEnumOptions = new ArrayList(); + FlexiSpeedEnumOptions.add("2400"); + FlexiSpeedEnumOptions.add("4800"); + FlexiSpeedEnumOptions.add("9600"); + FlexiSpeedEnumOptions.add("19200"); + FlexiSpeedEnumOptions.add("38400"); + FlexiSpeedEnumOptions.add("57600"); + FlexiSpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("FlexiSpeed", "bps", UAVObjectField.FieldType.ENUM, FlexiSpeedElemNames, FlexiSpeedEnumOptions) ); + + List VCPConfigElemNames = new ArrayList(); + VCPConfigElemNames.add("0"); + List VCPConfigEnumOptions = new ArrayList(); + VCPConfigEnumOptions.add("Disabled"); + VCPConfigEnumOptions.add("Serial"); + VCPConfigEnumOptions.add("Debug"); + fields.add( new UAVObjectField("VCPConfig", "function", UAVObjectField.FieldType.ENUM, VCPConfigElemNames, VCPConfigEnumOptions) ); + + List VCPSpeedElemNames = new ArrayList(); + VCPSpeedElemNames.add("0"); + List VCPSpeedEnumOptions = new ArrayList(); + VCPSpeedEnumOptions.add("2400"); + VCPSpeedEnumOptions.add("4800"); + VCPSpeedEnumOptions.add("9600"); + VCPSpeedEnumOptions.add("19200"); + VCPSpeedEnumOptions.add("38400"); + VCPSpeedEnumOptions.add("57600"); + VCPSpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("VCPSpeed", "bps", UAVObjectField.FieldType.ENUM, VCPSpeedElemNames, VCPSpeedEnumOptions) ); + + List RFSpeedElemNames = new ArrayList(); + RFSpeedElemNames.add("0"); + List RFSpeedEnumOptions = new ArrayList(); + RFSpeedEnumOptions.add("2400"); + RFSpeedEnumOptions.add("4800"); + RFSpeedEnumOptions.add("9600"); + RFSpeedEnumOptions.add("19200"); + RFSpeedEnumOptions.add("38400"); + RFSpeedEnumOptions.add("57600"); + RFSpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("RFSpeed", "bps", UAVObjectField.FieldType.ENUM, RFSpeedElemNames, RFSpeedEnumOptions) ); + + List MaxRFPowerElemNames = new ArrayList(); + MaxRFPowerElemNames.add("0"); + List MaxRFPowerEnumOptions = new ArrayList(); + MaxRFPowerEnumOptions.add("1.25"); + MaxRFPowerEnumOptions.add("1.6"); + MaxRFPowerEnumOptions.add("3.16"); + MaxRFPowerEnumOptions.add("6.3"); + MaxRFPowerEnumOptions.add("12.6"); + MaxRFPowerEnumOptions.add("25"); + MaxRFPowerEnumOptions.add("50"); + MaxRFPowerEnumOptions.add("100"); + fields.add( new UAVObjectField("MaxRFPower", "mW", UAVObjectField.FieldType.ENUM, MaxRFPowerElemNames, MaxRFPowerEnumOptions) ); + + List MinPacketSizeElemNames = new ArrayList(); + MinPacketSizeElemNames.add("0"); + fields.add( new UAVObjectField("MinPacketSize", "bytes", UAVObjectField.FieldType.UINT8, MinPacketSizeElemNames, null) ); + + List FrequencyCalibrationElemNames = new ArrayList(); + FrequencyCalibrationElemNames.add("0"); + fields.add( new UAVObjectField("FrequencyCalibration", "", UAVObjectField.FieldType.UINT8, FrequencyCalibrationElemNames, null) ); + + List AESKeyElemNames = new ArrayList(); + AESKeyElemNames.add("0"); + AESKeyElemNames.add("1"); + AESKeyElemNames.add("2"); + AESKeyElemNames.add("3"); + AESKeyElemNames.add("4"); + AESKeyElemNames.add("5"); + AESKeyElemNames.add("6"); + AESKeyElemNames.add("7"); + AESKeyElemNames.add("8"); + AESKeyElemNames.add("9"); + AESKeyElemNames.add("10"); + AESKeyElemNames.add("11"); + AESKeyElemNames.add("12"); + AESKeyElemNames.add("13"); + AESKeyElemNames.add("14"); + AESKeyElemNames.add("15"); + AESKeyElemNames.add("16"); + AESKeyElemNames.add("17"); + AESKeyElemNames.add("18"); + AESKeyElemNames.add("19"); + AESKeyElemNames.add("20"); + AESKeyElemNames.add("21"); + AESKeyElemNames.add("22"); + AESKeyElemNames.add("23"); + AESKeyElemNames.add("24"); + AESKeyElemNames.add("25"); + AESKeyElemNames.add("26"); + AESKeyElemNames.add("27"); + AESKeyElemNames.add("28"); + AESKeyElemNames.add("29"); + AESKeyElemNames.add("30"); + AESKeyElemNames.add("31"); + fields.add( new UAVObjectField("AESKey", "", UAVObjectField.FieldType.UINT8, AESKeyElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("PairID").setValue(0); + getField("Frequency").setValue(434000000); + getField("SendTimeout").setValue(50); + getField("TelemetryConfig").setValue("UAVTalk"); + getField("TelemetrySpeed").setValue("57600"); + getField("FlexiConfig").setValue("Disabled"); + getField("FlexiSpeed").setValue("57600"); + getField("VCPConfig").setValue("Disabled"); + getField("VCPSpeed").setValue("57600"); + getField("RFSpeed").setValue("115200"); + getField("MaxRFPower").setValue("100"); + getField("MinPacketSize").setValue(50); + getField("FrequencyCalibration").setValue(127); + getField("AESKey").setValue(0,0); + getField("AESKey").setValue(0,1); + getField("AESKey").setValue(0,2); + getField("AESKey").setValue(0,3); + getField("AESKey").setValue(0,4); + getField("AESKey").setValue(0,5); + getField("AESKey").setValue(0,6); + getField("AESKey").setValue(0,7); + getField("AESKey").setValue(0,8); + getField("AESKey").setValue(0,9); + getField("AESKey").setValue(0,10); + getField("AESKey").setValue(0,11); + getField("AESKey").setValue(0,12); + getField("AESKey").setValue(0,13); + getField("AESKey").setValue(0,14); + getField("AESKey").setValue(0,15); + getField("AESKey").setValue(0,16); + getField("AESKey").setValue(0,17); + getField("AESKey").setValue(0,18); + getField("AESKey").setValue(0,19); + getField("AESKey").setValue(0,20); + getField("AESKey").setValue(0,21); + getField("AESKey").setValue(0,22); + getField("AESKey").setValue(0,23); + getField("AESKey").setValue(0,24); + getField("AESKey").setValue(0,25); + getField("AESKey").setValue(0,26); + getField("AESKey").setValue(0,27); + getField("AESKey").setValue(0,28); + getField("AESKey").setValue(0,29); + getField("AESKey").setValue(0,30); + getField("AESKey").setValue(0,31); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + PipXSettings obj = new PipXSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public PipXSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (PipXSettings)(objMngr.getObject(PipXSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xBA192BCA; + protected static final String NAME = "PipXSettings"; + protected static String DESCRIPTION = "PipXtreme configurations options."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXStatus.java new file mode 100644 index 000000000..fb6a91e33 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXStatus.java @@ -0,0 +1,301 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * PipXtreme device status. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +PipXtreme device status. + +generated from pipxstatus.xml + **/ +public class PipXStatus extends UAVDataObject { + + public PipXStatus() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List MinFrequencyElemNames = new ArrayList(); + MinFrequencyElemNames.add("0"); + fields.add( new UAVObjectField("MinFrequency", "Hz", UAVObjectField.FieldType.UINT32, MinFrequencyElemNames, null) ); + + List MaxFrequencyElemNames = new ArrayList(); + MaxFrequencyElemNames.add("0"); + fields.add( new UAVObjectField("MaxFrequency", "Hz", UAVObjectField.FieldType.UINT32, MaxFrequencyElemNames, null) ); + + List FrequencyStepSizeElemNames = new ArrayList(); + FrequencyStepSizeElemNames.add("0"); + fields.add( new UAVObjectField("FrequencyStepSize", "", UAVObjectField.FieldType.FLOAT32, FrequencyStepSizeElemNames, null) ); + + List DeviceIDElemNames = new ArrayList(); + DeviceIDElemNames.add("0"); + fields.add( new UAVObjectField("DeviceID", "", UAVObjectField.FieldType.UINT32, DeviceIDElemNames, null) ); + + List AFCElemNames = new ArrayList(); + AFCElemNames.add("0"); + fields.add( new UAVObjectField("AFC", "", UAVObjectField.FieldType.INT32, AFCElemNames, null) ); + + List PairIDsElemNames = new ArrayList(); + PairIDsElemNames.add("0"); + PairIDsElemNames.add("1"); + PairIDsElemNames.add("2"); + PairIDsElemNames.add("3"); + fields.add( new UAVObjectField("PairIDs", "", UAVObjectField.FieldType.UINT32, PairIDsElemNames, null) ); + + List BoardRevisionElemNames = new ArrayList(); + BoardRevisionElemNames.add("0"); + fields.add( new UAVObjectField("BoardRevision", "", UAVObjectField.FieldType.UINT16, BoardRevisionElemNames, null) ); + + List RetriesElemNames = new ArrayList(); + RetriesElemNames.add("0"); + fields.add( new UAVObjectField("Retries", "", UAVObjectField.FieldType.UINT16, RetriesElemNames, null) ); + + List ErrorsElemNames = new ArrayList(); + ErrorsElemNames.add("0"); + fields.add( new UAVObjectField("Errors", "", UAVObjectField.FieldType.UINT16, ErrorsElemNames, null) ); + + List UAVTalkErrorsElemNames = new ArrayList(); + UAVTalkErrorsElemNames.add("0"); + fields.add( new UAVObjectField("UAVTalkErrors", "", UAVObjectField.FieldType.UINT16, UAVTalkErrorsElemNames, null) ); + + List DroppedElemNames = new ArrayList(); + DroppedElemNames.add("0"); + fields.add( new UAVObjectField("Dropped", "", UAVObjectField.FieldType.UINT16, DroppedElemNames, null) ); + + List ResetsElemNames = new ArrayList(); + ResetsElemNames.add("0"); + fields.add( new UAVObjectField("Resets", "", UAVObjectField.FieldType.UINT16, ResetsElemNames, null) ); + + List TXRateElemNames = new ArrayList(); + TXRateElemNames.add("0"); + fields.add( new UAVObjectField("TXRate", "Bps", UAVObjectField.FieldType.UINT16, TXRateElemNames, null) ); + + List RXRateElemNames = new ArrayList(); + RXRateElemNames.add("0"); + fields.add( new UAVObjectField("RXRate", "Bps", UAVObjectField.FieldType.UINT16, RXRateElemNames, null) ); + + List DescriptionElemNames = new ArrayList(); + DescriptionElemNames.add("0"); + DescriptionElemNames.add("1"); + DescriptionElemNames.add("2"); + DescriptionElemNames.add("3"); + DescriptionElemNames.add("4"); + DescriptionElemNames.add("5"); + DescriptionElemNames.add("6"); + DescriptionElemNames.add("7"); + DescriptionElemNames.add("8"); + DescriptionElemNames.add("9"); + DescriptionElemNames.add("10"); + DescriptionElemNames.add("11"); + DescriptionElemNames.add("12"); + DescriptionElemNames.add("13"); + DescriptionElemNames.add("14"); + DescriptionElemNames.add("15"); + DescriptionElemNames.add("16"); + DescriptionElemNames.add("17"); + DescriptionElemNames.add("18"); + DescriptionElemNames.add("19"); + DescriptionElemNames.add("20"); + DescriptionElemNames.add("21"); + DescriptionElemNames.add("22"); + DescriptionElemNames.add("23"); + DescriptionElemNames.add("24"); + DescriptionElemNames.add("25"); + DescriptionElemNames.add("26"); + DescriptionElemNames.add("27"); + DescriptionElemNames.add("28"); + DescriptionElemNames.add("29"); + DescriptionElemNames.add("30"); + DescriptionElemNames.add("31"); + DescriptionElemNames.add("32"); + DescriptionElemNames.add("33"); + DescriptionElemNames.add("34"); + DescriptionElemNames.add("35"); + DescriptionElemNames.add("36"); + DescriptionElemNames.add("37"); + DescriptionElemNames.add("38"); + DescriptionElemNames.add("39"); + fields.add( new UAVObjectField("Description", "", UAVObjectField.FieldType.UINT8, DescriptionElemNames, null) ); + + List CPUSerialElemNames = new ArrayList(); + CPUSerialElemNames.add("0"); + CPUSerialElemNames.add("1"); + CPUSerialElemNames.add("2"); + CPUSerialElemNames.add("3"); + CPUSerialElemNames.add("4"); + CPUSerialElemNames.add("5"); + CPUSerialElemNames.add("6"); + CPUSerialElemNames.add("7"); + CPUSerialElemNames.add("8"); + CPUSerialElemNames.add("9"); + CPUSerialElemNames.add("10"); + CPUSerialElemNames.add("11"); + fields.add( new UAVObjectField("CPUSerial", "", UAVObjectField.FieldType.UINT8, CPUSerialElemNames, null) ); + + List BoardTypeElemNames = new ArrayList(); + BoardTypeElemNames.add("0"); + fields.add( new UAVObjectField("BoardType", "", UAVObjectField.FieldType.UINT8, BoardTypeElemNames, null) ); + + List FrequencyBandElemNames = new ArrayList(); + FrequencyBandElemNames.add("0"); + fields.add( new UAVObjectField("FrequencyBand", "", UAVObjectField.FieldType.UINT8, FrequencyBandElemNames, null) ); + + List RSSIElemNames = new ArrayList(); + RSSIElemNames.add("0"); + fields.add( new UAVObjectField("RSSI", "dBm", UAVObjectField.FieldType.INT8, RSSIElemNames, null) ); + + List LinkStateElemNames = new ArrayList(); + LinkStateElemNames.add("0"); + List LinkStateEnumOptions = new ArrayList(); + LinkStateEnumOptions.add("Disconnected"); + LinkStateEnumOptions.add("Connecting"); + LinkStateEnumOptions.add("Connected"); + fields.add( new UAVObjectField("LinkState", "function", UAVObjectField.FieldType.ENUM, LinkStateElemNames, LinkStateEnumOptions) ); + + List PairSignalStrengthsElemNames = new ArrayList(); + PairSignalStrengthsElemNames.add("0"); + PairSignalStrengthsElemNames.add("1"); + PairSignalStrengthsElemNames.add("2"); + PairSignalStrengthsElemNames.add("3"); + fields.add( new UAVObjectField("PairSignalStrengths", "dBm", UAVObjectField.FieldType.INT8, PairSignalStrengthsElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READONLY) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("MinFrequency").setValue(0); + getField("MaxFrequency").setValue(0); + getField("FrequencyStepSize").setValue(0); + getField("DeviceID").setValue(0); + getField("AFC").setValue(0); + getField("PairIDs").setValue(0,0); + getField("PairIDs").setValue(0,1); + getField("PairIDs").setValue(0,2); + getField("PairIDs").setValue(0,3); + getField("Retries").setValue(0); + getField("Errors").setValue(0); + getField("UAVTalkErrors").setValue(0); + getField("Dropped").setValue(0); + getField("Resets").setValue(0); + getField("TXRate").setValue(0); + getField("RXRate").setValue(0); + getField("FrequencyBand").setValue(0); + getField("RSSI").setValue(0); + getField("LinkState").setValue("Disconnected"); + getField("PairSignalStrengths").setValue(-127,0); + getField("PairSignalStrengths").setValue(-127,1); + getField("PairSignalStrengths").setValue(-127,2); + getField("PairSignalStrengths").setValue(-127,3); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + PipXStatus obj = new PipXStatus(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public PipXStatus GetInstance(UAVObjectManager objMngr, int instID) + { + return (PipXStatus)(objMngr.getObject(PipXStatus.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x3FC68A86; + protected static final String NAME = "PipXStatus"; + protected static String DESCRIPTION = "PipXtreme device status."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoCalibration.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoCalibration.java new file mode 100644 index 000000000..940f78875 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoCalibration.java @@ -0,0 +1,249 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the INS to control the algorithm and what is updated + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the INS to control the algorithm and what is updated + +generated from revocalibration.xml + **/ +public class RevoCalibration extends UAVDataObject { + + public RevoCalibration() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List accel_biasElemNames = new ArrayList(); + accel_biasElemNames.add("X"); + accel_biasElemNames.add("Y"); + accel_biasElemNames.add("Z"); + fields.add( new UAVObjectField("accel_bias", "m/s", UAVObjectField.FieldType.FLOAT32, accel_biasElemNames, null) ); + + List accel_scaleElemNames = new ArrayList(); + accel_scaleElemNames.add("X"); + accel_scaleElemNames.add("Y"); + accel_scaleElemNames.add("Z"); + fields.add( new UAVObjectField("accel_scale", "gain", UAVObjectField.FieldType.FLOAT32, accel_scaleElemNames, null) ); + + List accel_varElemNames = new ArrayList(); + accel_varElemNames.add("X"); + accel_varElemNames.add("Y"); + accel_varElemNames.add("Z"); + fields.add( new UAVObjectField("accel_var", "(m/s)^2", UAVObjectField.FieldType.FLOAT32, accel_varElemNames, null) ); + + List gyro_biasElemNames = new ArrayList(); + gyro_biasElemNames.add("X"); + gyro_biasElemNames.add("Y"); + gyro_biasElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_bias", "deg/s", UAVObjectField.FieldType.FLOAT32, gyro_biasElemNames, null) ); + + List gyro_scaleElemNames = new ArrayList(); + gyro_scaleElemNames.add("X"); + gyro_scaleElemNames.add("Y"); + gyro_scaleElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_scale", "gain", UAVObjectField.FieldType.FLOAT32, gyro_scaleElemNames, null) ); + + List gyro_varElemNames = new ArrayList(); + gyro_varElemNames.add("X"); + gyro_varElemNames.add("Y"); + gyro_varElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_var", "(deg/s)^2", UAVObjectField.FieldType.FLOAT32, gyro_varElemNames, null) ); + + List gyro_tempcoeffElemNames = new ArrayList(); + gyro_tempcoeffElemNames.add("X"); + gyro_tempcoeffElemNames.add("Y"); + gyro_tempcoeffElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_tempcoeff", "(deg/s)/deg", UAVObjectField.FieldType.FLOAT32, gyro_tempcoeffElemNames, null) ); + + List mag_biasElemNames = new ArrayList(); + mag_biasElemNames.add("X"); + mag_biasElemNames.add("Y"); + mag_biasElemNames.add("Z"); + fields.add( new UAVObjectField("mag_bias", "mGau", UAVObjectField.FieldType.FLOAT32, mag_biasElemNames, null) ); + + List mag_scaleElemNames = new ArrayList(); + mag_scaleElemNames.add("X"); + mag_scaleElemNames.add("Y"); + mag_scaleElemNames.add("Z"); + fields.add( new UAVObjectField("mag_scale", "gain", UAVObjectField.FieldType.FLOAT32, mag_scaleElemNames, null) ); + + List mag_varElemNames = new ArrayList(); + mag_varElemNames.add("X"); + mag_varElemNames.add("Y"); + mag_varElemNames.add("Z"); + fields.add( new UAVObjectField("mag_var", "mGau^2", UAVObjectField.FieldType.FLOAT32, mag_varElemNames, null) ); + + List gps_varElemNames = new ArrayList(); + gps_varElemNames.add("Pos"); + gps_varElemNames.add("Vel"); + fields.add( new UAVObjectField("gps_var", "m^2", UAVObjectField.FieldType.FLOAT32, gps_varElemNames, null) ); + + List baro_varElemNames = new ArrayList(); + baro_varElemNames.add("0"); + fields.add( new UAVObjectField("baro_var", "m^2", UAVObjectField.FieldType.FLOAT32, baro_varElemNames, null) ); + + List MagBiasNullingRateElemNames = new ArrayList(); + MagBiasNullingRateElemNames.add("0"); + fields.add( new UAVObjectField("MagBiasNullingRate", "", UAVObjectField.FieldType.FLOAT32, MagBiasNullingRateElemNames, null) ); + + List BiasCorrectedRawElemNames = new ArrayList(); + BiasCorrectedRawElemNames.add("0"); + List BiasCorrectedRawEnumOptions = new ArrayList(); + BiasCorrectedRawEnumOptions.add("FALSE"); + BiasCorrectedRawEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("BiasCorrectedRaw", "", UAVObjectField.FieldType.ENUM, BiasCorrectedRawElemNames, BiasCorrectedRawEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("accel_bias").setValue(0,0); + getField("accel_bias").setValue(0,1); + getField("accel_bias").setValue(0,2); + getField("accel_scale").setValue(1,0); + getField("accel_scale").setValue(1,1); + getField("accel_scale").setValue(1,2); + getField("accel_var").setValue(0.01,0); + getField("accel_var").setValue(0.01,1); + getField("accel_var").setValue(0.01,2); + getField("gyro_bias").setValue(0,0); + getField("gyro_bias").setValue(0,1); + getField("gyro_bias").setValue(0,2); + getField("gyro_scale").setValue(1,0); + getField("gyro_scale").setValue(1,1); + getField("gyro_scale").setValue(1,2); + getField("gyro_var").setValue(0.01,0); + getField("gyro_var").setValue(0.01,1); + getField("gyro_var").setValue(0.01,2); + getField("gyro_tempcoeff").setValue(1,0); + getField("gyro_tempcoeff").setValue(1,1); + getField("gyro_tempcoeff").setValue(1,2); + getField("mag_bias").setValue(0,0); + getField("mag_bias").setValue(0,1); + getField("mag_bias").setValue(0,2); + getField("mag_scale").setValue(1,0); + getField("mag_scale").setValue(1,1); + getField("mag_scale").setValue(1,2); + getField("mag_var").setValue(0.01,0); + getField("mag_var").setValue(0.01,1); + getField("mag_var").setValue(10,2); + getField("gps_var").setValue(1,0); + getField("gps_var").setValue(1,1); + getField("baro_var").setValue(1); + getField("MagBiasNullingRate").setValue(0); + getField("BiasCorrectedRaw").setValue("TRUE"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + RevoCalibration obj = new RevoCalibration(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public RevoCalibration GetInstance(UAVObjectManager objMngr, int instID) + { + return (RevoCalibration)(objMngr.getObject(RevoCalibration.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xA2A63C7C; + protected static final String NAME = "RevoCalibration"; + protected static String DESCRIPTION = "Settings for the INS to control the algorithm and what is updated"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoSettings.java new file mode 100644 index 000000000..5e36565b2 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoSettings.java @@ -0,0 +1,143 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the revo to control the algorithm and what is updated + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the revo to control the algorithm and what is updated + +generated from revosettings.xml + **/ +public class RevoSettings extends UAVDataObject { + + public RevoSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List FusionAlgorithmElemNames = new ArrayList(); + FusionAlgorithmElemNames.add("0"); + List FusionAlgorithmEnumOptions = new ArrayList(); + FusionAlgorithmEnumOptions.add("Complimentary"); + FusionAlgorithmEnumOptions.add("INSIndoor"); + FusionAlgorithmEnumOptions.add("INSOutdoor"); + fields.add( new UAVObjectField("FusionAlgorithm", "", UAVObjectField.FieldType.ENUM, FusionAlgorithmElemNames, FusionAlgorithmEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("FusionAlgorithm").setValue("Complimentary"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + RevoSettings obj = new RevoSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public RevoSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (RevoSettings)(objMngr.getObject(RevoSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xE2DA70EA; + protected static final String NAME = "RevoSettings"; + protected static String DESCRIPTION = "Settings for the revo to control the algorithm and what is updated"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TxPIDSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TxPIDSettings.java new file mode 100644 index 000000000..789f31b3f --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TxPIDSettings.java @@ -0,0 +1,225 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings used by @ref TxPID optional module to tune PID settings using R/C transmitter + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings used by @ref TxPID optional module to tune PID settings using R/C transmitter + +generated from txpidsettings.xml + **/ +public class TxPIDSettings extends UAVDataObject { + + public TxPIDSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List ThrottleRangeElemNames = new ArrayList(); + ThrottleRangeElemNames.add("Min"); + ThrottleRangeElemNames.add("Max"); + fields.add( new UAVObjectField("ThrottleRange", "%", UAVObjectField.FieldType.FLOAT32, ThrottleRangeElemNames, null) ); + + List MinPIDElemNames = new ArrayList(); + MinPIDElemNames.add("Instance1"); + MinPIDElemNames.add("Instance2"); + MinPIDElemNames.add("Instance3"); + fields.add( new UAVObjectField("MinPID", "", UAVObjectField.FieldType.FLOAT32, MinPIDElemNames, null) ); + + List MaxPIDElemNames = new ArrayList(); + MaxPIDElemNames.add("Instance1"); + MaxPIDElemNames.add("Instance2"); + MaxPIDElemNames.add("Instance3"); + fields.add( new UAVObjectField("MaxPID", "", UAVObjectField.FieldType.FLOAT32, MaxPIDElemNames, null) ); + + List UpdateModeElemNames = new ArrayList(); + UpdateModeElemNames.add("0"); + List UpdateModeEnumOptions = new ArrayList(); + UpdateModeEnumOptions.add("Never"); + UpdateModeEnumOptions.add("When Armed"); + UpdateModeEnumOptions.add("Always"); + fields.add( new UAVObjectField("UpdateMode", "option", UAVObjectField.FieldType.ENUM, UpdateModeElemNames, UpdateModeEnumOptions) ); + + List InputsElemNames = new ArrayList(); + InputsElemNames.add("Instance1"); + InputsElemNames.add("Instance2"); + InputsElemNames.add("Instance3"); + List InputsEnumOptions = new ArrayList(); + InputsEnumOptions.add("Throttle"); + InputsEnumOptions.add("Accessory0"); + InputsEnumOptions.add("Accessory1"); + InputsEnumOptions.add("Accessory2"); + InputsEnumOptions.add("Accessory3"); + InputsEnumOptions.add("Accessory4"); + InputsEnumOptions.add("Accessory5"); + fields.add( new UAVObjectField("Inputs", "channel", UAVObjectField.FieldType.ENUM, InputsElemNames, InputsEnumOptions) ); + + List PIDsElemNames = new ArrayList(); + PIDsElemNames.add("Instance1"); + PIDsElemNames.add("Instance2"); + PIDsElemNames.add("Instance3"); + List PIDsEnumOptions = new ArrayList(); + PIDsEnumOptions.add("Disabled"); + PIDsEnumOptions.add("Roll Rate.Kp"); + PIDsEnumOptions.add("Pitch Rate.Kp"); + PIDsEnumOptions.add("Roll+Pitch Rate.Kp"); + PIDsEnumOptions.add("Yaw Rate.Kp"); + PIDsEnumOptions.add("Roll Rate.Ki"); + PIDsEnumOptions.add("Pitch Rate.Ki"); + PIDsEnumOptions.add("Roll+Pitch Rate.Ki"); + PIDsEnumOptions.add("Yaw Rate.Ki"); + PIDsEnumOptions.add("Roll Rate.Kd"); + PIDsEnumOptions.add("Pitch Rate.Kd"); + PIDsEnumOptions.add("Roll+Pitch Rate.Kd"); + PIDsEnumOptions.add("Yaw Rate.Kd"); + PIDsEnumOptions.add("Roll Rate.ILimit"); + PIDsEnumOptions.add("Pitch Rate.ILimit"); + PIDsEnumOptions.add("Roll+Pitch Rate.ILimit"); + PIDsEnumOptions.add("Yaw Rate.ILimit"); + PIDsEnumOptions.add("Roll Attitude.Kp"); + PIDsEnumOptions.add("Pitch Attitude.Kp"); + PIDsEnumOptions.add("Roll+Pitch Attitude.Kp"); + PIDsEnumOptions.add("Yaw Attitude.Kp"); + PIDsEnumOptions.add("Roll Attitude.Ki"); + PIDsEnumOptions.add("Pitch Attitude.Ki"); + PIDsEnumOptions.add("Roll+Pitch Attitude.Ki"); + PIDsEnumOptions.add("Yaw Attitude.Ki"); + PIDsEnumOptions.add("Roll Attitude.ILimit"); + PIDsEnumOptions.add("Pitch Attitude.ILimit"); + PIDsEnumOptions.add("Roll+Pitch Attitude.ILimit"); + PIDsEnumOptions.add("Yaw Attitude.ILimit"); + PIDsEnumOptions.add("GyroTau"); + fields.add( new UAVObjectField("PIDs", "option", UAVObjectField.FieldType.ENUM, PIDsElemNames, PIDsEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("ThrottleRange").setValue(0.2,0); + getField("ThrottleRange").setValue(0.8,1); + getField("MinPID").setValue(0,0); + getField("MinPID").setValue(0,1); + getField("MinPID").setValue(0,2); + getField("MaxPID").setValue(0,0); + getField("MaxPID").setValue(0,1); + getField("MaxPID").setValue(0,2); + getField("UpdateMode").setValue("When Armed"); + getField("Inputs").setValue("Throttle",0); + getField("Inputs").setValue("Accessory0",1); + getField("Inputs").setValue("Accessory1",2); + getField("PIDs").setValue("Disabled",0); + getField("PIDs").setValue("Disabled",1); + getField("PIDs").setValue("Disabled",2); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + TxPIDSettings obj = new TxPIDSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public TxPIDSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (TxPIDSettings)(objMngr.getObject(TxPIDSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x42B2D2AE; + protected static final String NAME = "TxPIDSettings"; + protected static String DESCRIPTION = "Settings used by @ref TxPID optional module to tune PID settings using R/C transmitter"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VtolPathFollowerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VtolPathFollowerSettings.java new file mode 100644 index 000000000..b3c01dc8a --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VtolPathFollowerSettings.java @@ -0,0 +1,232 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref VtolPathFollower module + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref VtolPathFollower module + +generated from vtolpathfollowersettings.xml + **/ +public class VtolPathFollowerSettings extends UAVDataObject { + + public VtolPathFollowerSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List HorizontalPosPIElemNames = new ArrayList(); + HorizontalPosPIElemNames.add("Kp"); + HorizontalPosPIElemNames.add("Ki"); + HorizontalPosPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("HorizontalPosPI", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) ); + + List HorizontalVelPIDElemNames = new ArrayList(); + HorizontalVelPIDElemNames.add("Kp"); + HorizontalVelPIDElemNames.add("Ki"); + HorizontalVelPIDElemNames.add("Kd"); + HorizontalVelPIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("HorizontalVelPID", "deg/(m/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); + + List VerticalPosPIElemNames = new ArrayList(); + VerticalPosPIElemNames.add("Kp"); + VerticalPosPIElemNames.add("Ki"); + VerticalPosPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("VerticalPosPI", "", UAVObjectField.FieldType.FLOAT32, VerticalPosPIElemNames, null) ); + + List VerticalVelPIDElemNames = new ArrayList(); + VerticalVelPIDElemNames.add("Kp"); + VerticalVelPIDElemNames.add("Ki"); + VerticalVelPIDElemNames.add("Kd"); + VerticalVelPIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("VerticalVelPID", "", UAVObjectField.FieldType.FLOAT32, VerticalVelPIDElemNames, null) ); + + List VelocityFeedforwardElemNames = new ArrayList(); + VelocityFeedforwardElemNames.add("0"); + fields.add( new UAVObjectField("VelocityFeedforward", "deg/(m/s)", UAVObjectField.FieldType.FLOAT32, VelocityFeedforwardElemNames, null) ); + + List MaxRollPitchElemNames = new ArrayList(); + MaxRollPitchElemNames.add("0"); + fields.add( new UAVObjectField("MaxRollPitch", "deg", UAVObjectField.FieldType.FLOAT32, MaxRollPitchElemNames, null) ); + + List UpdatePeriodElemNames = new ArrayList(); + UpdatePeriodElemNames.add("0"); + fields.add( new UAVObjectField("UpdatePeriod", "ms", UAVObjectField.FieldType.INT32, UpdatePeriodElemNames, null) ); + + List HorizontalVelMaxElemNames = new ArrayList(); + HorizontalVelMaxElemNames.add("0"); + fields.add( new UAVObjectField("HorizontalVelMax", "m/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) ); + + List VerticalVelMaxElemNames = new ArrayList(); + VerticalVelMaxElemNames.add("0"); + fields.add( new UAVObjectField("VerticalVelMax", "m/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) ); + + List GuidanceModeElemNames = new ArrayList(); + GuidanceModeElemNames.add("0"); + List GuidanceModeEnumOptions = new ArrayList(); + GuidanceModeEnumOptions.add("DUAL_LOOP"); + GuidanceModeEnumOptions.add("VELOCITY_CONTROL"); + fields.add( new UAVObjectField("GuidanceMode", "", UAVObjectField.FieldType.ENUM, GuidanceModeElemNames, GuidanceModeEnumOptions) ); + + List ThrottleControlElemNames = new ArrayList(); + ThrottleControlElemNames.add("0"); + List ThrottleControlEnumOptions = new ArrayList(); + ThrottleControlEnumOptions.add("FALSE"); + ThrottleControlEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("ThrottleControl", "", UAVObjectField.FieldType.ENUM, ThrottleControlElemNames, ThrottleControlEnumOptions) ); + + List VelocitySourceElemNames = new ArrayList(); + VelocitySourceElemNames.add("0"); + List VelocitySourceEnumOptions = new ArrayList(); + VelocitySourceEnumOptions.add("EKF"); + VelocitySourceEnumOptions.add("NEDVEL"); + VelocitySourceEnumOptions.add("GPSPOS"); + fields.add( new UAVObjectField("VelocitySource", "", UAVObjectField.FieldType.ENUM, VelocitySourceElemNames, VelocitySourceEnumOptions) ); + + List PositionSourceElemNames = new ArrayList(); + PositionSourceElemNames.add("0"); + List PositionSourceEnumOptions = new ArrayList(); + PositionSourceEnumOptions.add("EKF"); + PositionSourceEnumOptions.add("GPSPOS"); + fields.add( new UAVObjectField("PositionSource", "", UAVObjectField.FieldType.ENUM, PositionSourceElemNames, PositionSourceEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("HorizontalPosPI").setValue(1,0); + getField("HorizontalPosPI").setValue(0,1); + getField("HorizontalPosPI").setValue(0,2); + getField("HorizontalVelPID").setValue(5,0); + getField("HorizontalVelPID").setValue(0,1); + getField("HorizontalVelPID").setValue(1,2); + getField("HorizontalVelPID").setValue(0,3); + getField("VerticalPosPI").setValue(0.1,0); + getField("VerticalPosPI").setValue(0.001,1); + getField("VerticalPosPI").setValue(200,2); + getField("VerticalVelPID").setValue(0.1,0); + getField("VerticalVelPID").setValue(0,1); + getField("VerticalVelPID").setValue(0,2); + getField("VerticalVelPID").setValue(0,3); + getField("VelocityFeedforward").setValue(0); + getField("MaxRollPitch").setValue(20); + getField("UpdatePeriod").setValue(100); + getField("HorizontalVelMax").setValue(10); + getField("VerticalVelMax").setValue(1); + getField("GuidanceMode").setValue("DUAL_LOOP"); + getField("ThrottleControl").setValue("FALSE"); + getField("VelocitySource").setValue("EKF"); + getField("PositionSource").setValue("EKF"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + VtolPathFollowerSettings obj = new VtolPathFollowerSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public VtolPathFollowerSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (VtolPathFollowerSettings)(objMngr.getObject(VtolPathFollowerSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x973991F6; + protected static final String NAME = "VtolPathFollowerSettings"; + protected static String DESCRIPTION = "Settings for the @ref VtolPathFollower module"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/Waypoint.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Waypoint.java new file mode 100644 index 000000000..4db7179ad --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Waypoint.java @@ -0,0 +1,159 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * A waypoint the aircraft can try and hit. Used by the @ref PathPlanner module + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +A waypoint the aircraft can try and hit. Used by the @ref PathPlanner module + +generated from waypoint.xml + **/ +public class Waypoint extends UAVDataObject { + + public Waypoint() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List PositionElemNames = new ArrayList(); + PositionElemNames.add("North"); + PositionElemNames.add("East"); + PositionElemNames.add("Down"); + fields.add( new UAVObjectField("Position", "m", UAVObjectField.FieldType.FLOAT32, PositionElemNames, null) ); + + List VelocityElemNames = new ArrayList(); + VelocityElemNames.add("North"); + VelocityElemNames.add("East"); + VelocityElemNames.add("Down"); + fields.add( new UAVObjectField("Velocity", "m/s", UAVObjectField.FieldType.FLOAT32, VelocityElemNames, null) ); + + List YawDesiredElemNames = new ArrayList(); + YawDesiredElemNames.add("0"); + fields.add( new UAVObjectField("YawDesired", "deg", UAVObjectField.FieldType.FLOAT32, YawDesiredElemNames, null) ); + + List ActionElemNames = new ArrayList(); + ActionElemNames.add("0"); + List ActionEnumOptions = new ArrayList(); + ActionEnumOptions.add("PathToNext"); + ActionEnumOptions.add("EndpointToNext"); + ActionEnumOptions.add("Land"); + ActionEnumOptions.add("Stop"); + fields.add( new UAVObjectField("Action", "", UAVObjectField.FieldType.ENUM, ActionElemNames, ActionEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 4000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + Waypoint obj = new Waypoint(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public Waypoint GetInstance(UAVObjectManager objMngr, int instID) + { + return (Waypoint)(objMngr.getObject(Waypoint.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x338C5F90; + protected static final String NAME = "Waypoint"; + protected static String DESCRIPTION = "A waypoint the aircraft can try and hit. Used by the @ref PathPlanner module"; + protected static final boolean ISSINGLEINST = 0 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WaypointActive.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WaypointActive.java new file mode 100644 index 000000000..06f3ab6c4 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WaypointActive.java @@ -0,0 +1,138 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Indicates the currently active waypoint + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Indicates the currently active waypoint + +generated from waypointactive.xml + **/ +public class WaypointActive extends UAVDataObject { + + public WaypointActive() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List IndexElemNames = new ArrayList(); + IndexElemNames.add("0"); + fields.add( new UAVObjectField("Index", "", UAVObjectField.FieldType.UINT8, IndexElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + WaypointActive obj = new WaypointActive(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public WaypointActive GetInstance(UAVObjectManager objMngr, int instID) + { + return (WaypointActive)(objMngr.getObject(WaypointActive.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x1EA5B192; + protected static final String NAME = "WaypointActive"; + protected static String DESCRIPTION = "Indicates the currently active waypoint"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file From 2881a4573fd514b54c7bd31befbba7f8ea2917d1 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 02:14:12 -0500 Subject: [PATCH 064/284] Allow selecting the IP address from the preferences --- androidgcs/res/xml/preferences.xml | 2 +- .../src/org/openpilot/androidgcs/TcpUAVTalk.java | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/androidgcs/res/xml/preferences.xml b/androidgcs/res/xml/preferences.xml index 24fd43b5e..285e7b6d7 100644 --- a/androidgcs/res/xml/preferences.xml +++ b/androidgcs/res/xml/preferences.xml @@ -10,6 +10,6 @@ + android:key="ip_address" />
diff --git a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java index 47074f968..f5d40040b 100644 --- a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java +++ b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java @@ -8,6 +8,8 @@ import org.openpilot.uavtalk.UAVObjectManager; import org.openpilot.uavtalk.UAVTalk; import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import android.util.Log; public class TcpUAVTalk { @@ -17,14 +19,17 @@ public class TcpUAVTalk { public static boolean DEBUG = LOGLEVEL > 0; // Temporarily define fixed device name - public final static String IP_ADDRESS = "10.21.18.120"; + private String ip_address = "1"; public final static int PORT = 9001; private UAVTalk uavTalk; private boolean connected; public TcpUAVTalk(Context caller) { - if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + IP_ADDRESS); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(caller); + ip_address = prefs.getString("ip_address","127.0.0.1"); + + if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + ip_address); connected = false; } @@ -47,11 +52,11 @@ public class TcpUAVTalk { private boolean openTelemetryTcp(UAVObjectManager objMngr) { - Log.d(TAG, "Opening conncetion to " + IP_ADDRESS + " at address " + PORT); + Log.d(TAG, "Opening connection to " + ip_address + " at address " + PORT); InetAddress serverAddr = null; try { - serverAddr = InetAddress.getByName(IP_ADDRESS); + serverAddr = InetAddress.getByName(ip_address); } catch (UnknownHostException e1) { // TODO Auto-generated catch block e1.printStackTrace(); From c6073772fb2f5506977e6a121f31f807e47227b0 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 03:18:26 -0500 Subject: [PATCH 065/284] Make port and bluetooth adapter be listed in the preferences. Using the BT adapter not working yet. --- androidgcs/res/xml/preferences.xml | 8 ++++++++ .../openpilot/androidgcs/BluetoothUAVTalk.java | 17 ++++++++++++----- .../androidgcs/OPTelemetryService.java | 2 +- .../org/openpilot/androidgcs/TcpUAVTalk.java | 12 ++++++++---- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/androidgcs/res/xml/preferences.xml b/androidgcs/res/xml/preferences.xml index 285e7b6d7..3a9103b49 100644 --- a/androidgcs/res/xml/preferences.xml +++ b/androidgcs/res/xml/preferences.xml @@ -11,5 +11,13 @@ android:summary="Enter a TCP/IP address here" android:defaultValue="192.168.0.1" android:title="IP address:" android:key="ip_address" /> + + diff --git a/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java index b240f3adc..c00db0bea 100644 --- a/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java +++ b/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java @@ -7,6 +7,7 @@ import java.util.UUID; import org.openpilot.uavtalk.UAVObjectManager; import org.openpilot.uavtalk.UAVTalk; +import android.annotation.TargetApi; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -14,16 +15,18 @@ import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import android.util.Log; -public class BluetoothUAVTalk { +@TargetApi(10) public class BluetoothUAVTalk { private final String TAG = "BluetoothUAVTalk"; public static int LOGLEVEL = 2; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; // Temporarily define fixed device name - public final static String DEVICE_NAME = "RN42-222D"; + private String device_name = "RN42-222D"; private final static UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private BluetoothAdapter mBluetoothAdapter; @@ -32,8 +35,12 @@ public class BluetoothUAVTalk { private UAVTalk uavTalk; private boolean connected; - public BluetoothUAVTalk(Context caller, String deviceName) { - if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + deviceName); + public BluetoothUAVTalk(Context caller) { + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(caller); + device_name = prefs.getString("bluetooth_mac",""); + + if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + device_name); connected = false; device = null; @@ -93,7 +100,7 @@ public class BluetoothUAVTalk { // Add the name and address to an array adapter to show in a ListView //mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); Log.d(TAG, "Paired device: " + device.getName()); - if(device.getName().compareTo(DEVICE_NAME) == 0) { + if(device.getName().compareTo(device_name) == 0) { this.device = device; return; } diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 917dfb116..13e415c54 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -277,7 +277,7 @@ public class OPTelemetryService extends Service { Looper.prepare(); - BluetoothUAVTalk bt = new BluetoothUAVTalk(OPTelemetryService.this, BluetoothUAVTalk.DEVICE_NAME); + BluetoothUAVTalk bt = new BluetoothUAVTalk(OPTelemetryService.this); for( int i = 0; i < 10; i++ ) { if (DEBUG) Log.d(TAG, "Attempting Bluetooth Connection"); diff --git a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java index f5d40040b..1f647bd99 100644 --- a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java +++ b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java @@ -20,7 +20,7 @@ public class TcpUAVTalk { // Temporarily define fixed device name private String ip_address = "1"; - public final static int PORT = 9001; + private int port = 9001; private UAVTalk uavTalk; private boolean connected; @@ -28,8 +28,12 @@ public class TcpUAVTalk { public TcpUAVTalk(Context caller) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(caller); ip_address = prefs.getString("ip_address","127.0.0.1"); + try { + port = Integer.decode(prefs.getString("port", "")); + } catch (NumberFormatException e) { + } - if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + ip_address); + if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + ip_address); connected = false; } @@ -52,7 +56,7 @@ public class TcpUAVTalk { private boolean openTelemetryTcp(UAVObjectManager objMngr) { - Log.d(TAG, "Opening connection to " + ip_address + " at address " + PORT); + Log.d(TAG, "Opening connection to " + ip_address + " at address " + port); InetAddress serverAddr = null; try { @@ -65,7 +69,7 @@ public class TcpUAVTalk { Socket socket = null; try { - socket = new Socket(serverAddr,PORT); + socket = new Socket(serverAddr,port); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); From 4e7d8bffc4268e4420b24e6933c19a53a5ce547f Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 21:00:25 -0500 Subject: [PATCH 066/284] Update the sdk version --- androidgcs/AndroidManifest.xml | 2 +- androidgcs/project.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index c18dc0cb1..40b08c328 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -2,7 +2,7 @@ - + diff --git a/androidgcs/project.properties b/androidgcs/project.properties index 5d85d779c..a43ea8cdc 100644 --- a/androidgcs/project.properties +++ b/androidgcs/project.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=Google Inc.:Google APIs:13 +target=Google Inc.:Google APIs:16 From 8f98383fa598fd00bbd4f5f2765b0c1f28e5ae08 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 21:00:54 -0500 Subject: [PATCH 067/284] Check in a joystick gadget class --- .../Android/Widgets/DockPanel/DockPanel.java | 319 +++++++++++ .../Widgets/DockPanel/DockPosition.java | 5 + .../DragAndDrop/DragAndDropManager.java | 124 +++++ .../Widgets/DragAndDrop/DragSurface.java | 94 ++++ .../Widgets/DragAndDrop/DraggableItem.java | 44 ++ .../DragAndDrop/DraggableViewsFactory.java | 19 + .../Android/Widgets/DragAndDrop/DropZone.java | 67 +++ .../DragAndDrop/DropZoneEventsListener.java | 9 + .../Widgets/Joystick/DualJoystickView.java | 147 +++++ .../Joystick/JoystickClickedListener.java | 6 + .../Joystick/JoystickMovedListener.java | 7 + .../Widgets/Joystick/JoystickView.java | 521 ++++++++++++++++++ .../ThresholdEditText/ThresholdEditText.java | 169 ++++++ .../ThresholdTextChanged.java | 7 + .../Widgets/TilesLayout/SingleTileLayout.java | 68 +++ .../Widgets/TilesLayout/TilePosition.java | 63 +++ .../Widgets/TilesLayout/TilesLayout.java | 299 ++++++++++ .../TilesLayout/TilesLayoutPreset.java | 157 ++++++ 18 files changed, 2125 insertions(+) create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPanel.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPosition.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragAndDropManager.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragSurface.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableItem.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableViewsFactory.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZone.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZoneEventsListener.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/DualJoystickView.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickClickedListener.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickMovedListener.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickView.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdEditText.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdTextChanged.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/SingleTileLayout.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilePosition.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayout.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayoutPreset.java diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPanel.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPanel.java new file mode 100644 index 000000000..e2397394e --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPanel.java @@ -0,0 +1,319 @@ +package com.MobileAnarchy.Android.Widgets.DockPanel; + +import android.content.Context; +import android.graphics.Color; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.Animation; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.TranslateAnimation; +import android.view.animation.Animation.AnimationListener; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.LinearLayout; + +public class DockPanel extends LinearLayout { + + // ========================================= + // Private members + // ========================================= + + private static final String TAG = "DockPanel"; + private DockPosition position; + private int contentLayoutId; + private int handleButtonDrawableId; + private Boolean isOpen; + private Boolean animationRunning; + private FrameLayout contentPlaceHolder; + private ImageButton toggleButton; + private int animationDuration; + + // ========================================= + // Constructors + // ========================================= + + public DockPanel(Context context, int contentLayoutId, + int handleButtonDrawableId, Boolean isOpen) { + super(context); + + this.contentLayoutId = contentLayoutId; + this.handleButtonDrawableId = handleButtonDrawableId; + this.isOpen = isOpen; + + Init(null); + } + + public DockPanel(Context context, AttributeSet attrs) { + super(context, attrs); + + // to prevent from crashing the designer + try { + Init(attrs); + } catch (Exception ex) { + } + } + + // ========================================= + // Initialization + // ========================================= + + private void Init(AttributeSet attrs) { + setDefaultValues(attrs); + + createHandleToggleButton(); + + // create the handle container + FrameLayout handleContainer = new FrameLayout(getContext()); + handleContainer.addView(toggleButton); + + // create and populate the panel's container, and inflate it + contentPlaceHolder = new FrameLayout(getContext()); + String infService = Context.LAYOUT_INFLATER_SERVICE; + LayoutInflater li = (LayoutInflater) getContext().getSystemService( + infService); + li.inflate(contentLayoutId, contentPlaceHolder, true); + + // setting the layout of the panel parameters according to the docking + // position + if (position == DockPosition.LEFT || position == DockPosition.RIGHT) { + handleContainer.setLayoutParams(new LayoutParams( + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, + android.view.ViewGroup.LayoutParams.FILL_PARENT, 1)); + contentPlaceHolder.setLayoutParams(new LayoutParams( + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, + android.view.ViewGroup.LayoutParams.FILL_PARENT, 1)); + } else { + handleContainer.setLayoutParams(new LayoutParams( + android.view.ViewGroup.LayoutParams.FILL_PARENT, + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, 1)); + contentPlaceHolder.setLayoutParams(new LayoutParams( + android.view.ViewGroup.LayoutParams.FILL_PARENT, + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, 1)); + } + + // adding the view to the parent layout according to docking position + if (position == DockPosition.RIGHT || position == DockPosition.BOTTOM) { + this.addView(handleContainer); + this.addView(contentPlaceHolder); + } else { + this.addView(contentPlaceHolder); + this.addView(handleContainer); + } + + if (!isOpen) { + contentPlaceHolder.setVisibility(GONE); + } + } + + private void setDefaultValues(AttributeSet attrs) { + // set default values + isOpen = true; + animationRunning = false; + animationDuration = 500; + setPosition(DockPosition.RIGHT); + + // Try to load values set by xml markup + if (attrs != null) { + String namespace = "http://com.MobileAnarchy.Android.Widgets"; + + animationDuration = attrs.getAttributeIntValue(namespace, + "animationDuration", 500); + contentLayoutId = attrs.getAttributeResourceValue(namespace, + "contentLayoutId", 0); + handleButtonDrawableId = attrs.getAttributeResourceValue( + namespace, "handleButtonDrawableResourceId", 0); + isOpen = attrs.getAttributeBooleanValue(namespace, "isOpen", true); + + // Enums are a bit trickier (needs to be parsed) + try { + position = DockPosition.valueOf(attrs.getAttributeValue( + namespace, "dockPosition").toUpperCase()); + setPosition(position); + } catch (Exception ex) { + // Docking to the left is the default behavior + setPosition(DockPosition.LEFT); + } + } + } + + private void createHandleToggleButton() { + toggleButton = new ImageButton(getContext()); + toggleButton.setPadding(0, 0, 0, 0); + toggleButton.setLayoutParams(new FrameLayout.LayoutParams( + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, + Gravity.CENTER)); + toggleButton.setBackgroundColor(Color.TRANSPARENT); + toggleButton.setImageResource(handleButtonDrawableId); + toggleButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + toggle(); + } + }); + } + + private void setPosition(DockPosition position) { + this.position = position; + switch (position) { + case TOP: + setOrientation(LinearLayout.VERTICAL); + setGravity(Gravity.TOP); + break; + case RIGHT: + setOrientation(LinearLayout.HORIZONTAL); + setGravity(Gravity.RIGHT); + break; + case BOTTOM: + setOrientation(LinearLayout.VERTICAL); + setGravity(Gravity.BOTTOM); + break; + case LEFT: + setOrientation(LinearLayout.HORIZONTAL); + setGravity(Gravity.LEFT); + break; + } + } + + // ========================================= + // Public methods + // ========================================= + + public int getAnimationDuration() { + return animationDuration; + } + + public void setAnimationDuration(int milliseconds) { + animationDuration = milliseconds; + } + + public Boolean getIsRunning() { + return animationRunning; + } + + public void open() { + if (!animationRunning) { + Log.d(TAG, "Opening..."); + + Animation animation = createShowAnimation(); + this.setAnimation(animation); + animation.start(); + + isOpen = true; + } + } + + public void close() { + if (!animationRunning) { + Log.d(TAG, "Closing..."); + + Animation animation = createHideAnimation(); + this.setAnimation(animation); + animation.start(); + isOpen = false; + } + } + + public void toggle() { + if (isOpen) { + close(); + } else { + open(); + } + } + + // ========================================= + // Private methods + // ========================================= + + private Animation createHideAnimation() { + Animation animation = null; + switch (position) { + case TOP: + animation = new TranslateAnimation(0, 0, 0, -contentPlaceHolder + .getHeight()); + break; + case RIGHT: + animation = new TranslateAnimation(0, contentPlaceHolder + .getWidth(), 0, 0); + break; + case BOTTOM: + animation = new TranslateAnimation(0, 0, 0, contentPlaceHolder + .getHeight()); + break; + case LEFT: + animation = new TranslateAnimation(0, -contentPlaceHolder + .getWidth(), 0, 0); + break; + } + + animation.setDuration(animationDuration); + animation.setInterpolator(new AccelerateInterpolator()); + animation.setAnimationListener(new AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + animationRunning = true; + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + contentPlaceHolder.setVisibility(View.GONE); + animationRunning = false; + } + }); + return animation; + } + + private Animation createShowAnimation() { + Animation animation = null; + switch (position) { + case TOP: + animation = new TranslateAnimation(0, 0, -contentPlaceHolder + .getHeight(), 0); + break; + case RIGHT: + animation = new TranslateAnimation(contentPlaceHolder.getWidth(), + 0, 0, 0); + break; + case BOTTOM: + animation = new TranslateAnimation(0, 0, contentPlaceHolder + .getHeight(), 0); + break; + case LEFT: + animation = new TranslateAnimation(-contentPlaceHolder.getWidth(), + 0, 0, 0); + break; + } + Log.d(TAG, "Animation duration: " + animationDuration); + animation.setDuration(animationDuration); + animation.setInterpolator(new DecelerateInterpolator()); + animation.setAnimationListener(new AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + animationRunning = true; + contentPlaceHolder.setVisibility(View.VISIBLE); + Log.d(TAG, "\"Show\" Animation started"); + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + animationRunning = false; + Log.d(TAG, "\"Show\" Animation ended"); + } + }); + return animation; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPosition.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPosition.java new file mode 100644 index 000000000..59643dfc6 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPosition.java @@ -0,0 +1,5 @@ +package com.MobileAnarchy.Android.Widgets.DockPanel; + +public enum DockPosition { + TOP, BOTTOM, LEFT, RIGHT +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragAndDropManager.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragAndDropManager.java new file mode 100644 index 000000000..d7e0c5e44 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragAndDropManager.java @@ -0,0 +1,124 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +import java.util.ArrayList; + +import android.content.Context; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnTouchListener; + +public class DragAndDropManager { + + // ========================================= + // Private members + // ========================================= + + protected static final String TAG = "DragAndDropManager"; + private static DragAndDropManager instance = null; + private ArrayList dropZones; + private OnTouchListener originalTouchListener; + private DragSurface dragSurface; + private DraggableItem draggedItem; + private DropZone activeDropZone; + + // ========================================= + // Protected Constructor + // ========================================= + + protected DragAndDropManager() { + // Exists only to defeat instantiation. + dropZones = new ArrayList(); + } + + // ========================================= + // Public Properties + // ========================================= + + public static DragAndDropManager getInstance() { + if (instance == null) { + instance = new DragAndDropManager(); + } + return instance; + } + + public Context getContext() { + if (dragSurface == null) + return null; + + return dragSurface.getContext(); + } + + // ========================================= + // Public Methods + // ========================================= + + public void init(DragSurface surface) { + dragSurface = surface; + clearDropZones(); + } + + public void clearDropZones() { + dropZones.clear(); + } + + public void addDropZone(DropZone dropZone) { + dropZones.add(dropZone); + } + + + public void startDragging(OnTouchListener originalListener, DraggableItem draggedItem) { + originalTouchListener = originalListener; + this.draggedItem = draggedItem; + draggedItem.getSource().setOnTouchListener(new OnTouchListener() { + + @Override + public boolean onTouch(View v, MotionEvent event) { + int[] location = new int[2]; + v.getLocationOnScreen(location); + event.offsetLocation(location[0], location[1]); + invalidateDropZones((int)event.getX(), (int)event.getY()); + return dragSurface.onTouchEvent(event); + } + }); + + dragSurface.startDragging(draggedItem); + } + + + // ========================================= + // Protected Methods + // ========================================= + + protected void invalidateDropZones(int x, int y) { + if (activeDropZone != null) { + if (!activeDropZone.isOver(x, y)) { + activeDropZone.getListener().OnDragZoneLeft(activeDropZone, draggedItem); + activeDropZone = null; + } + else { + // we are still over the same drop zone, no need to check other drop zones + return; + } + } + + for (DropZone dropZone : dropZones) { + if (dropZone.isOver(x, y)) { + activeDropZone = dropZone; + dropZone.getListener().OnDragZoneEntered(activeDropZone, draggedItem); + break; + } + } + } + + protected void stoppedDragging() { + if (activeDropZone != null) { + activeDropZone.getListener().OnDropped(activeDropZone, draggedItem); + } + + // Registering the "old" listener to the view that initiated this drag session + draggedItem.getSource().setOnTouchListener(originalTouchListener); + draggedItem = null; + activeDropZone = null; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragSurface.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragSurface.java new file mode 100644 index 000000000..aebb9d481 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragSurface.java @@ -0,0 +1,94 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.MotionEvent; +import android.widget.FrameLayout; + +public class DragSurface extends FrameLayout { + + private float draggedViewHalfHeight; + private float draggedViewHalfWidth; + private int framesCount; + + private Boolean isDragging; + private DraggableItem draggedItem; + + public DragSurface(Context context, AttributeSet attrs) { + super(context, attrs); + isDragging = false; + } + + // ========================================= + // Touch Events Listener + // ========================================= + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (isDragging && event.getAction() == MotionEvent.ACTION_UP) { + // Dragging ended + removeAllViews(); + isDragging = false; + + DragAndDropManager.getInstance().stoppedDragging(); + } + + if (isDragging && event.getAction() == MotionEvent.ACTION_MOVE) { + // Move the dragged view to it's new position + repositionView(event.getX(), event.getY()); + + // Mark this event as handled (so that other UI elements will not intercept it) + return true; + } + + return false; + } + + public void startDragging(DraggableItem draggableItem) { + this.draggedItem = draggableItem; + this.draggedItem.getDraggedView().setVisibility(INVISIBLE); + isDragging = true; + addView(this.draggedItem.getDraggedView()); + //repositionView(x, y); + framesCount = 0; + } + + private void repositionView(float x, float y) { + draggedViewHalfHeight = draggedItem.getDraggedView().getHeight() / 2f; + draggedViewHalfWidth = draggedItem.getDraggedView().getWidth() / 2f; + + // If the dragged view was not drawn yet, skip this phase + if (draggedViewHalfHeight == 0 || draggedViewHalfWidth == 0) + return; + + framesCount++; + + //Log.d(TAG, "Original = (x=" + x + ", y=" + y + ")"); + //Log.d(TAG, "Size (W=" + draggedViewHalfWidth + ", H=" + draggedViewHalfHeight + ")"); + + x = x - draggedViewHalfWidth; + y = y - draggedViewHalfHeight; + + x = Math.max(x, 0); + x = Math.min(x, getWidth() - draggedViewHalfWidth * 2); + + y = Math.max(y, 0); + y = Math.min(y, getHeight() - draggedViewHalfHeight * 2); + + //Log.d(TAG, "Moving view to (x=" + x + ", y=" + y + ")"); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT, Gravity.TOP + Gravity.LEFT); + + lp.setMargins((int)x, (int)y, 0, 0); + draggedItem.getDraggedView().setLayoutParams(lp); + + // hte first couple of dragged frame's positions are not calculated correctly, + // so we have a threshold before making the dragged view visible again + if (framesCount < 2) + return; + + draggedItem.getDraggedView().setVisibility(VISIBLE); + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableItem.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableItem.java new file mode 100644 index 000000000..d0c8b7e25 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableItem.java @@ -0,0 +1,44 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +import android.view.View; + +public class DraggableItem { + + // ========================================= + // Private members + // ========================================= + + private View source; + private View draggedView; + private Object tag; + + // ========================================= + // Constructor + // ========================================= + + public DraggableItem(View source, View draggedItem) { + this.source = source; + this.draggedView = draggedItem; + } + + // ========================================= + // Public properties + // ========================================= + + public Object getTag() { + return tag; + } + + public void setTag(Object tag) { + this.tag = tag; + } + + public View getSource() { + return source; + } + + public View getDraggedView() { + return draggedView; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableViewsFactory.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableViewsFactory.java new file mode 100644 index 000000000..246b2392f --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableViewsFactory.java @@ -0,0 +1,19 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +import android.content.Context; +import android.view.View; +import android.widget.TextView; +import android.widget.TableLayout.LayoutParams; + +public class DraggableViewsFactory { + + public static View getLabel(String text) { + Context context = DragAndDropManager.getInstance().getContext(); + TextView textView = new TextView(context); + textView.setText(text); + textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + //textView.setGravity(Gravity.TOP + Gravity.LEFT); + return textView; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZone.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZone.java new file mode 100644 index 000000000..06a8caa17 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZone.java @@ -0,0 +1,67 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +import android.view.View; + +public class DropZone { + + // ========================================= + // Private members + // ========================================= + + private View view; + private DropZoneEventsListener listener; + private int left, top, width, height; + private Boolean dimansionsCalculated; + + // ========================================= + // Constructor + // ========================================= + + public DropZone(View view, DropZoneEventsListener listener) { + this.view = view; + this.listener = listener; + dimansionsCalculated = false; + } + + // ========================================= + // Public properties + // ========================================= + + public View getView() { + return view; + } + + // ========================================= + // Public methods + // ========================================= + + public Boolean isOver(int x, int y) { + if (!dimansionsCalculated) + calculateDimensions(); + + Boolean isOver = (x >= left && x <= (left + width)) && + (y >= top && y <= (top + height)); + + //Log.d("DragZone", "x=" +x + ", left=" + left + ", y=" + y + ", top=" + top + " width=" + width + ", height=" + height + ", isover=" + isOver); + + return isOver; + } + + // ========================================= + // Protected & Private methods + // ========================================= + + protected DropZoneEventsListener getListener() { + return listener; + } + + private void calculateDimensions() { + int[] location = new int[2]; + view.getLocationOnScreen(location); + left = location[0]; + top = location[1]; + width = view.getWidth(); + height = view.getHeight(); + dimansionsCalculated = true; + } +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZoneEventsListener.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZoneEventsListener.java new file mode 100644 index 000000000..828a1cbf2 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZoneEventsListener.java @@ -0,0 +1,9 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +public interface DropZoneEventsListener { + + void OnDragZoneEntered(DropZone zone, DraggableItem item); + void OnDragZoneLeft(DropZone zone, DraggableItem item); + void OnDropped(DropZone zone, DraggableItem item); + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/DualJoystickView.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/DualJoystickView.java new file mode 100644 index 000000000..bb419d404 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/DualJoystickView.java @@ -0,0 +1,147 @@ +package com.MobileAnarchy.Android.Widgets.Joystick; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +public class DualJoystickView extends LinearLayout { + @SuppressWarnings("unused") + private static final String TAG = DualJoystickView.class.getSimpleName(); + + private final boolean D = false; + private Paint dbgPaint1; + + private JoystickView stickL; + private JoystickView stickR; + + private View pad; + + public DualJoystickView(Context context) { + super(context); + stickL = new JoystickView(context); + stickR = new JoystickView(context); + initDualJoystickView(); + } + + public DualJoystickView(Context context, AttributeSet attrs) { + super(context, attrs); + stickL = new JoystickView(context, attrs); + stickR = new JoystickView(context, attrs); + initDualJoystickView(); + } + + private void initDualJoystickView() { + setOrientation(LinearLayout.HORIZONTAL); + + if ( D ) { + dbgPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG); + dbgPaint1.setColor(Color.CYAN); + dbgPaint1.setStrokeWidth(1); + dbgPaint1.setStyle(Paint.Style.STROKE); + } + + pad = new View(getContext()); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + removeView(stickL); + removeView(stickR); + + float padW = getMeasuredWidth()-(getMeasuredHeight()*2); + int joyWidth = (int) ((getMeasuredWidth()-padW)/2); + LayoutParams joyLParams = new LayoutParams(joyWidth,getMeasuredHeight()); + + stickL.setLayoutParams(joyLParams); + stickR.setLayoutParams(joyLParams); + + stickL.TAG = "L"; + stickR.TAG = "R"; + stickL.setPointerId(JoystickView.INVALID_POINTER_ID); + stickR.setPointerId(JoystickView.INVALID_POINTER_ID); + + addView(stickL); + + ViewGroup.LayoutParams padLParams = new ViewGroup.LayoutParams((int) padW,getMeasuredHeight()); + removeView(pad); + pad.setLayoutParams(padLParams); + addView(pad); + + addView(stickR); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + stickR.setTouchOffset(stickR.getLeft(), stickR.getTop()); + } + + public void setAutoReturnToCenter(boolean left, boolean right) { + stickL.setAutoReturnToCenter(left); + stickR.setAutoReturnToCenter(right); + } + + public void setOnJostickMovedListener(JoystickMovedListener left, JoystickMovedListener right) { + stickL.setOnJostickMovedListener(left); + stickR.setOnJostickMovedListener(right); + } + + public void setOnJostickClickedListener(JoystickClickedListener left, JoystickClickedListener right) { + stickL.setOnJostickClickedListener(left); + stickR.setOnJostickClickedListener(right); + } + + public void setYAxisInverted(boolean leftYAxisInverted, boolean rightYAxisInverted) { + stickL.setYAxisInverted(leftYAxisInverted); + stickL.setYAxisInverted(rightYAxisInverted); + } + + public void setMovementConstraint(int movementConstraint) { + stickL.setMovementConstraint(movementConstraint); + stickR.setMovementConstraint(movementConstraint); + } + + public void setMovementRange(float movementRangeLeft, float movementRangeRight) { + stickL.setMovementRange(movementRangeLeft); + stickR.setMovementRange(movementRangeRight); + } + + public void setMoveResolution(float leftMoveResolution, float rightMoveResolution) { + stickL.setMoveResolution(leftMoveResolution); + stickR.setMoveResolution(rightMoveResolution); + } + + public void setUserCoordinateSystem(int leftCoordinateSystem, int rightCoordinateSystem) { + stickL.setUserCoordinateSystem(leftCoordinateSystem); + stickR.setUserCoordinateSystem(rightCoordinateSystem); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (D) { + canvas.drawRect(1, 1, getMeasuredWidth()-1, getMeasuredHeight()-1, dbgPaint1); + } + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + boolean l = stickL.dispatchTouchEvent(ev); + boolean r = stickR.dispatchTouchEvent(ev); + return l || r; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + boolean l = stickL.onTouchEvent(ev); + boolean r = stickR.onTouchEvent(ev); + return l || r; + } +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickClickedListener.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickClickedListener.java new file mode 100644 index 000000000..128828980 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickClickedListener.java @@ -0,0 +1,6 @@ +package com.MobileAnarchy.Android.Widgets.Joystick; + +public interface JoystickClickedListener { + public void OnClicked(); + public void OnReleased(); +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickMovedListener.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickMovedListener.java new file mode 100644 index 000000000..346f2efed --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickMovedListener.java @@ -0,0 +1,7 @@ +package com.MobileAnarchy.Android.Widgets.Joystick; + +public interface JoystickMovedListener { + public void OnMoved(int pan, int tilt); + public void OnReleased(); + public void OnReturnedToCenter(); +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickView.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickView.java new file mode 100644 index 000000000..bab74e5a7 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickView.java @@ -0,0 +1,521 @@ +package com.MobileAnarchy.Android.Widgets.Joystick; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Handler; +import android.util.AttributeSet; +import android.util.Log; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.View; + +public class JoystickView extends View { + public static final int INVALID_POINTER_ID = -1; + + // ========================================= + // Private Members + // ========================================= + private final boolean D = false; + String TAG = "JoystickView"; + + private Paint dbgPaint1; + private Paint dbgPaint2; + + private Paint bgPaint; + private Paint handlePaint; + + private int innerPadding; + private int bgRadius; + private int handleRadius; + private int movementRadius; + private int handleInnerBoundaries; + + private JoystickMovedListener moveListener; + private JoystickClickedListener clickListener; + + //# of pixels movement required between reporting to the listener + private float moveResolution; + + private boolean yAxisInverted; + private boolean autoReturnToCenter; + + //Max range of movement in user coordinate system + public final static int CONSTRAIN_BOX = 0; + public final static int CONSTRAIN_CIRCLE = 1; + private int movementConstraint; + private float movementRange; + + public final static int COORDINATE_CARTESIAN = 0; //Regular cartesian coordinates + public final static int COORDINATE_DIFFERENTIAL = 1; //Uses polar rotation of 45 degrees to calc differential drive paramaters + private int userCoordinateSystem; + + //Records touch pressure for click handling + private float touchPressure; + private boolean clicked; + private float clickThreshold; + + //Last touch point in view coordinates + private int pointerId = INVALID_POINTER_ID; + private float touchX, touchY; + + //Last reported position in view coordinates (allows different reporting sensitivities) + private float reportX, reportY; + + //Handle center in view coordinates + private float handleX, handleY; + + //Center of the view in view coordinates + private int cX, cY; + + //Size of the view in view coordinates + private int dimX, dimY; + + //Cartesian coordinates of last touch point - joystick center is (0,0) + private int cartX, cartY; + + //Polar coordinates of the touch point from joystick center + private double radial; + private double angle; + + //User coordinates of last touch point + private int userX, userY; + + //Offset co-ordinates (used when touch events are received from parent's coordinate origin) + private int offsetX; + private int offsetY; + + // ========================================= + // Constructors + // ========================================= + + public JoystickView(Context context) { + super(context); + initJoystickView(); + } + + public JoystickView(Context context, AttributeSet attrs) { + super(context, attrs); + initJoystickView(); + } + + public JoystickView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initJoystickView(); + } + + // ========================================= + // Initialization + // ========================================= + + private void initJoystickView() { + setFocusable(true); + + dbgPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG); + dbgPaint1.setColor(Color.RED); + dbgPaint1.setStrokeWidth(1); + dbgPaint1.setStyle(Paint.Style.STROKE); + + dbgPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG); + dbgPaint2.setColor(Color.GREEN); + dbgPaint2.setStrokeWidth(1); + dbgPaint2.setStyle(Paint.Style.STROKE); + + bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + bgPaint.setColor(Color.GRAY); + bgPaint.setStrokeWidth(1); + bgPaint.setStyle(Paint.Style.FILL_AND_STROKE); + + handlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + handlePaint.setColor(Color.DKGRAY); + handlePaint.setStrokeWidth(1); + handlePaint.setStyle(Paint.Style.FILL_AND_STROKE); + + innerPadding = 10; + + setMovementRange(10); + setMoveResolution(1.0f); + setClickThreshold(0.4f); + setYAxisInverted(true); + setUserCoordinateSystem(COORDINATE_CARTESIAN); + setAutoReturnToCenter(true); + } + + public void setAutoReturnToCenter(boolean autoReturnToCenter) { + this.autoReturnToCenter = autoReturnToCenter; + } + + public boolean isAutoReturnToCenter() { + return autoReturnToCenter; + } + + public void setUserCoordinateSystem(int userCoordinateSystem) { + if (userCoordinateSystem < COORDINATE_CARTESIAN || movementConstraint > COORDINATE_DIFFERENTIAL) + Log.e(TAG, "invalid value for userCoordinateSystem"); + else + this.userCoordinateSystem = userCoordinateSystem; + } + + public int getUserCoordinateSystem() { + return userCoordinateSystem; + } + + public void setMovementConstraint(int movementConstraint) { + if (movementConstraint < CONSTRAIN_BOX || movementConstraint > CONSTRAIN_CIRCLE) + Log.e(TAG, "invalid value for movementConstraint"); + else + this.movementConstraint = movementConstraint; + } + + public int getMovementConstraint() { + return movementConstraint; + } + + public boolean isYAxisInverted() { + return yAxisInverted; + } + + public void setYAxisInverted(boolean yAxisInverted) { + this.yAxisInverted = yAxisInverted; + } + + /** + * Set the pressure sensitivity for registering a click + * @param clickThreshold threshold 0...1.0f inclusive. 0 will cause clicks to never be reported, 1.0 is a very hard click + */ + public void setClickThreshold(float clickThreshold) { + if (clickThreshold < 0 || clickThreshold > 1.0f) + Log.e(TAG, "clickThreshold must range from 0...1.0f inclusive"); + else + this.clickThreshold = clickThreshold; + } + + public float getClickThreshold() { + return clickThreshold; + } + + public void setMovementRange(float movementRange) { + this.movementRange = movementRange; + } + + public float getMovementRange() { + return movementRange; + } + + public void setMoveResolution(float moveResolution) { + this.moveResolution = moveResolution; + } + + public float getMoveResolution() { + return moveResolution; + } + + // ========================================= + // Public Methods + // ========================================= + + public void setOnJostickMovedListener(JoystickMovedListener listener) { + this.moveListener = listener; + } + + public void setOnJostickClickedListener(JoystickClickedListener listener) { + this.clickListener = listener; + } + + // ========================================= + // Drawing Functionality + // ========================================= + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Here we make sure that we have a perfect circle + int measuredWidth = measure(widthMeasureSpec); + int measuredHeight = measure(heightMeasureSpec); + setMeasuredDimension(measuredWidth, measuredHeight); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + int d = Math.min(getMeasuredWidth(), getMeasuredHeight()); + + dimX = d; + dimY = d; + + cX = d / 2; + cY = d / 2; + + bgRadius = dimX/2 - innerPadding; + handleRadius = (int)(d * 0.25); + handleInnerBoundaries = handleRadius; + movementRadius = Math.min(cX, cY) - handleInnerBoundaries; + } + + private int measure(int measureSpec) { + int result = 0; + // Decode the measurement specifications. + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + if (specMode == MeasureSpec.UNSPECIFIED) { + // Return a default size of 200 if no bounds are specified. + result = 200; + } else { + // As you want to fill the available space + // always return the full available bounds. + result = specSize; + } + return result; + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.save(); + // Draw the background + canvas.drawCircle(cX, cY, bgRadius, bgPaint); + + // Draw the handle + handleX = touchX + cX; + handleY = touchY + cY; + canvas.drawCircle(handleX, handleY, handleRadius, handlePaint); + + if (D) { + canvas.drawRect(1, 1, getMeasuredWidth()-1, getMeasuredHeight()-1, dbgPaint1); + + canvas.drawCircle(handleX, handleY, 3, dbgPaint1); + + if ( movementConstraint == CONSTRAIN_CIRCLE ) { + canvas.drawCircle(cX, cY, this.movementRadius, dbgPaint1); + } + else { + canvas.drawRect(cX-movementRadius, cY-movementRadius, cX+movementRadius, cY+movementRadius, dbgPaint1); + } + + //Origin to touch point + canvas.drawLine(cX, cY, handleX, handleY, dbgPaint2); + + int baseY = (int) (touchY < 0 ? cY + handleRadius : cY - handleRadius); + canvas.drawText(String.format("%s (%.0f,%.0f)", TAG, touchX, touchY), handleX-20, baseY-7, dbgPaint2); + canvas.drawText("("+ String.format("%.0f, %.1f", radial, angle * 57.2957795) + (char) 0x00B0 + ")", handleX-20, baseY+15, dbgPaint2); + } + +// Log.d(TAG, String.format("touch(%f,%f)", touchX, touchY)); +// Log.d(TAG, String.format("onDraw(%.1f,%.1f)\n\n", handleX, handleY)); + canvas.restore(); + } + + // Constrain touch within a box + private void constrainBox() { + touchX = Math.max(Math.min(touchX, movementRadius), -movementRadius); + touchY = Math.max(Math.min(touchY, movementRadius), -movementRadius); + } + + // Constrain touch within a circle + private void constrainCircle() { + float diffX = touchX; + float diffY = touchY; + double radial = Math.sqrt((diffX*diffX) + (diffY*diffY)); + if ( radial > movementRadius ) { + touchX = (int)((diffX / radial) * movementRadius); + touchY = (int)((diffY / radial) * movementRadius); + } + } + + public void setPointerId(int id) { + this.pointerId = id; + } + + public int getPointerId() { + return pointerId; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + final int action = ev.getAction(); + switch (action & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_MOVE: { + return processMoveEvent(ev); + } + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: { + if ( pointerId != INVALID_POINTER_ID ) { +// Log.d(TAG, "ACTION_UP"); + returnHandleToCenter(); + setPointerId(INVALID_POINTER_ID); + } + break; + } + case MotionEvent.ACTION_POINTER_UP: { + if ( pointerId != INVALID_POINTER_ID ) { + final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + final int pointerId = ev.getPointerId(pointerIndex); + if ( pointerId == this.pointerId ) { +// Log.d(TAG, "ACTION_POINTER_UP: " + pointerId); + returnHandleToCenter(); + setPointerId(INVALID_POINTER_ID); + return true; + } + } + break; + } + case MotionEvent.ACTION_DOWN: { + if ( pointerId == INVALID_POINTER_ID ) { + int x = (int) ev.getX(); + if ( x >= offsetX && x < offsetX + dimX ) { + setPointerId(ev.getPointerId(0)); +// Log.d(TAG, "ACTION_DOWN: " + getPointerId()); + return true; + } + } + break; + } + case MotionEvent.ACTION_POINTER_DOWN: { + if ( pointerId == INVALID_POINTER_ID ) { + final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + final int pointerId = ev.getPointerId(pointerIndex); + int x = (int) ev.getX(pointerId); + if ( x >= offsetX && x < offsetX + dimX ) { +// Log.d(TAG, "ACTION_POINTER_DOWN: " + pointerId); + setPointerId(pointerId); + return true; + } + } + break; + } + } + return false; + } + + private boolean processMoveEvent(MotionEvent ev) { + if ( pointerId != INVALID_POINTER_ID ) { + final int pointerIndex = ev.findPointerIndex(pointerId); + + // Translate touch position to center of view + float x = ev.getX(pointerIndex); + touchX = x - cX - offsetX; + float y = ev.getY(pointerIndex); + touchY = y - cY - offsetY; + +// Log.d(TAG, String.format("ACTION_MOVE: (%03.0f, %03.0f) => (%03.0f, %03.0f)", x, y, touchX, touchY)); + + reportOnMoved(); + invalidate(); + + touchPressure = ev.getPressure(pointerIndex); + reportOnPressure(); + + return true; + } + return false; + } + + private void reportOnMoved() { + if ( movementConstraint == CONSTRAIN_CIRCLE ) + constrainCircle(); + else + constrainBox(); + + calcUserCoordinates(); + + if (moveListener != null) { + boolean rx = Math.abs(touchX - reportX) >= moveResolution; + boolean ry = Math.abs(touchY - reportY) >= moveResolution; + if (rx || ry) { + this.reportX = touchX; + this.reportY = touchY; + +// Log.d(TAG, String.format("moveListener.OnMoved(%d,%d)", (int)userX, (int)userY)); + moveListener.OnMoved(userX, userY); + } + } + } + + private void calcUserCoordinates() { + //First convert to cartesian coordinates + cartX = (int)(touchX / movementRadius * movementRange); + cartY = (int)(touchY / movementRadius * movementRange); + + radial = Math.sqrt((cartX*cartX) + (cartY*cartY)); + angle = Math.atan2(cartY, cartX); + + //Invert Y axis if requested + if ( !yAxisInverted ) + cartY *= -1; + + if ( userCoordinateSystem == COORDINATE_CARTESIAN ) { + userX = cartX; + userY = cartY; + } + else if ( userCoordinateSystem == COORDINATE_DIFFERENTIAL ) { + userX = cartY + cartX / 4; + userY = cartY - cartX / 4; + + if ( userX < -movementRange ) + userX = (int)-movementRange; + if ( userX > movementRange ) + userX = (int)movementRange; + + if ( userY < -movementRange ) + userY = (int)-movementRange; + if ( userY > movementRange ) + userY = (int)movementRange; + } + + } + + //Simple pressure click + private void reportOnPressure() { +// Log.d(TAG, String.format("touchPressure=%.2f", this.touchPressure)); + if ( clickListener != null ) { + if ( clicked && touchPressure < clickThreshold ) { + clickListener.OnReleased(); + this.clicked = false; +// Log.d(TAG, "reset click"); + invalidate(); + } + else if ( !clicked && touchPressure >= clickThreshold ) { + clicked = true; + clickListener.OnClicked(); +// Log.d(TAG, "click"); + invalidate(); + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + } + } + } + + private void returnHandleToCenter() { + if ( autoReturnToCenter ) { + final int numberOfFrames = 5; + final double intervalsX = (0 - touchX) / numberOfFrames; + final double intervalsY = (0 - touchY) / numberOfFrames; + + for (int i = 0; i < numberOfFrames; i++) { + final int j = i; + postDelayed(new Runnable() { + @Override + public void run() { + touchX += intervalsX; + touchY += intervalsY; + + reportOnMoved(); + invalidate(); + + if (moveListener != null && j == numberOfFrames - 1) { + moveListener.OnReturnedToCenter(); + } + } + }, i * 40); + } + + if (moveListener != null) { + moveListener.OnReleased(); + } + } + } + + public void setTouchOffset(int x, int y) { + offsetX = x; + offsetY = y; + } +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdEditText.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdEditText.java new file mode 100644 index 000000000..5fbd76f46 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdEditText.java @@ -0,0 +1,169 @@ +package com.MobileAnarchy.Android.Widgets.ThresholdEditText; + +import android.content.Context; +import android.os.Handler; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.widget.EditText; + +public class ThresholdEditText extends EditText { + + // ========================================= + // Private members + // ========================================= + + private int threshold; + private ThresholdTextChanged thresholdTextChanged; + private Handler handler; + private Runnable invoker; + private boolean thresholdDisabledOnEmptyInput; + + + // ========================================= + // Constructors + // ========================================= + + public ThresholdEditText(Context context) { + super(context); + initAttributes(null); + init(); + } + + public ThresholdEditText(Context context, AttributeSet attrs) { + super(context, attrs); + initAttributes(attrs); + init(); + } + + + // ========================================= + // Public properties + // ========================================= + + /** + * Get the current threshold value + */ + public int getThreshold() { + return threshold; + } + + /** + * Set the threshold value (in milliseconds) + * + * @param threshold + * Threshold value + */ + public void setThreshold(int threshold) { + this.threshold = threshold; + } + + /** + * @return True = the callback will fire immediately when the content of the + * EditText is emptied False = The threshold will be used even on + * empty input + */ + public boolean getThresholdDisabledOnEmptyInput() { + return thresholdDisabledOnEmptyInput; + } + + /** + * @param thresholdDisabledOnEmptyInput + * Set to true if you want the callback to fire immediately when + * the content of the EditText is emptied + */ + public void setThresholdDisabledOnEmptyInput( + boolean thresholdDisabledOnEmptyInput) { + this.thresholdDisabledOnEmptyInput = thresholdDisabledOnEmptyInput; + } + + /** + * Set the callback to the OnThresholdTextChanged event + * + * @param listener + */ + public void setOnThresholdTextChanged(ThresholdTextChanged listener) { + this.thresholdTextChanged = listener; + } + + // ========================================= + // Private / Protected methods + // ========================================= + + /** + * Load properties values from xml layout + */ + private void initAttributes(AttributeSet attrs) { + if (attrs != null) { + String namespace = "http://com.MobileAnarchy.Android.Widgets"; + + // Load values to local members + this.threshold = attrs.getAttributeIntValue(namespace, "threshold", + 500); + this.thresholdDisabledOnEmptyInput = attrs.getAttributeBooleanValue( + namespace, "disableThresholdOnEmptyInput", true); + } else { + // Default threshold value is 0.5 seconds + threshold = 500; + + // Default behaviour on emptied text - no threshold + thresholdDisabledOnEmptyInput = true; + } + } + + /** + * Initialize the private members with default values + */ + private void init() { + + handler = new Handler(); + + invoker = new Runnable() { + + @Override + public void run() { + invokeCallback(); + } + + }; + + this.addTextChangedListener(new TextWatcher() { + + @Override + public void afterTextChanged(Editable s) { + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + // Remove any existing pending callbacks + handler.removeCallbacks(invoker); + + if (s.length() == 0 && thresholdDisabledOnEmptyInput) { + // The text is empty, so invoke the callback immediately + invoker.run(); + } else { + // Post a new delayed callback + handler.postDelayed(invoker, threshold); + } + } + + }); + } + + /** + * Invoking the callback on the listener provided (if provided) + */ + private void invokeCallback() { + if (thresholdTextChanged != null) { + thresholdTextChanged.onThersholdTextChanged(this.getText()); + } + } + +} \ No newline at end of file diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdTextChanged.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdTextChanged.java new file mode 100644 index 000000000..145f6547b --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdTextChanged.java @@ -0,0 +1,7 @@ +package com.MobileAnarchy.Android.Widgets.ThresholdEditText; + +import android.text.Editable; + +public interface ThresholdTextChanged { + void onThersholdTextChanged(Editable text); +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/SingleTileLayout.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/SingleTileLayout.java new file mode 100644 index 000000000..d2f3be2d3 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/SingleTileLayout.java @@ -0,0 +1,68 @@ +package com.MobileAnarchy.Android.Widgets.TilesLayout; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; + +public class SingleTileLayout extends FrameLayout { + + // ========================================= + // Private members + // ========================================= + + private TilePosition position; + private long timestamp; + + // ========================================= + // Constructors + // ========================================= + + public SingleTileLayout(Context context) { + super(context); + } + + public SingleTileLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + + // ========================================= + // Public Methods + // ========================================= + + public TilePosition getPosition() { + return position; + } + + public void setPosition(TilePosition position) { + this.position = position; + } + + public long getTimestamp() { + return this.timestamp; + } + + // ========================================= + // Overrides + // ========================================= + + @Override + public void addView(View child) { + super.addView(child); + timestamp = java.lang.System.currentTimeMillis(); + } + + @Override + public void removeAllViews() { + super.removeAllViews(); + timestamp = 0; + } + + @Override + public void removeView(View view) { + super.removeView(view); + timestamp = 0; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilePosition.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilePosition.java new file mode 100644 index 000000000..04bf0c1d4 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilePosition.java @@ -0,0 +1,63 @@ +package com.MobileAnarchy.Android.Widgets.TilesLayout; + + +public class TilePosition { + + // ========================================= + // Private Members + // ========================================= + + private float x, y, height, width; + + // ========================================= + // Constructors + // ========================================= + + public TilePosition(float x, float y, float width, float height) { + this.x = x; + this.y = y; + this.height = height; + this.width = width; + } + + // ========================================= + // Public Properties + // ========================================= + + public float getX() { + return x; + } + + public float getY() { + return y; + } + + public float getHeight() { + return height; + } + + public float getWidth() { + return width; + } + + + // ========================================= + // Public Methods + // ========================================= + + public Boolean equals(TilePosition position) { + if (position == null) + return false; + + return this.x == position.x && + this.y == position.y && + this.height == position.height && + this.width == position.width; + } + + @Override + public String toString() { + return "TilePosition = [X: " + x + ", Y: " + y + ", Height: " + height + ", Width: " + width + "]"; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayout.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayout.java new file mode 100644 index 000000000..c1728faff --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayout.java @@ -0,0 +1,299 @@ +package com.MobileAnarchy.Android.Widgets.TilesLayout; + +import java.util.ArrayList; +import java.util.List; + +import android.R; +import android.content.Context; +import android.graphics.Color; +import android.os.Handler; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.ScaleAnimation; +import android.view.animation.TranslateAnimation; +import android.view.animation.Animation.AnimationListener; +import android.widget.FrameLayout; + +public class TilesLayout extends FrameLayout { + + // ========================================= + // Private members + // ========================================= + + private static final String TAG = "TilesLayout"; + private int animatedTransitionDuration; + private List tiles; + private TilesLayoutPreset preset; + private int tileBackgroundResourceId; + + // ========================================= + // Constructors + // ========================================= + + public TilesLayout(Context context) { + super(context); + Init(null); + } + + public TilesLayout(Context context, AttributeSet attrs) { + super(context, attrs); + Init(attrs); + } + + + // ========================================= + // Public Properties + // ========================================= + + public void setPreset(TilesLayoutPreset preset) { + try { + rebuildLayout(preset); + this.preset = preset; + } + catch (Exception ex) { + Log.e(TAG, "Failed to set layout preset", ex); + } + } + + public TilesLayoutPreset getPreset() { + return this.preset; + } + + public int getAnimatedTransitionDuration() { + return animatedTransitionDuration; + } + + public void setAnimatedTransitionDuration(int animatedTransitionDuration) { + this.animatedTransitionDuration = animatedTransitionDuration; + } + + public int getTileBackgroundResourceId() { + return tileBackgroundResourceId; + } + + public void setTileBackgroundResourceId(int tileBackgroundResourceId) { + this.tileBackgroundResourceId = tileBackgroundResourceId; + } + + // ========================================= + // Public Methods + // ========================================= + + public void addContent(View view) { + for (int i = 0; i < tiles.size(); i++) { + if (tiles.get(i).getChildCount() == 0) { + tiles.get(i).addView(view); + return; + } + } + // No available space for the new view... + // TODO: Take the tile with the smallest time stamp and place the new view in it + } + + public void clearView(int tileId) { + if (tiles.size() < tileId) { + tiles.get(tileId).removeAllViews(); + } + } + + // ========================================= + // Private Methods + // ========================================= + + private void Init(AttributeSet attrs) { + animatedTransitionDuration = 750; + tileBackgroundResourceId = R.drawable.edit_text; + tiles = new ArrayList(); + } + + + private void rebuildLayout(TilesLayoutPreset preset) { + ArrayList positions = buildViewsPositions(preset); + + // We need to transform the current layout, to the new layout + int extraViews = tiles.size() - positions.size(); + if (extraViews > 0) { + // Remove the extra views + while(tiles.size() - positions.size() > 0) { + int lastViewPosition = tiles.size() - 1; + removeView(tiles.get(lastViewPosition)); + tiles.remove(lastViewPosition); + } + } else { + // Add the extra views + for (int i = tiles.size(); i< positions.size(); i++) { + TilePosition newTilePosition = positions.get(i); + SingleTileLayout tile = new SingleTileLayout(getContext()); + tile.setBackgroundResource(tileBackgroundResourceId); + + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( + (int)newTilePosition.getWidth(), + (int)newTilePosition.getHeight(), + Gravity.TOP + Gravity.LEFT); + lp.setMargins((int)newTilePosition.getX(), + (int)newTilePosition.getY(), 0, 0); + + tile.setLayoutParams(lp); + + tiles.add(tile); + addView(tile); + } + } + // There is a bug in the animation-set, so we'll not animate + animateChange(positions); + + // Regular repositioning (no animation) + //processChange(positions); + } + + + + private ArrayList buildViewsPositions(TilesLayoutPreset preset) { + int width = getWidth(); + int height = getHeight(); + + Log.d(TAG, "Container's Dimensions = Width: " + width + ", Height: " + height); + ArrayList actualPositions = new ArrayList(); + for (TilePosition position : preset.getTilePositions()) { + + int tileX = (int) Math.round(width * ((float)position.getX() / 100.0)); + int tileY = (int) Math.round(height * ((float)position.getY() / 100.0)); + int tileWidth = (int) Math.round(width * ((float)position.getWidth() / 100.0)); + int tileHeight = (int) Math.round(height * ((float)position.getHeight() / 100.0)); + + TilePosition actualPosition = new TilePosition(tileX, tileY, tileWidth, tileHeight); + actualPositions.add(actualPosition); + + Log.d(TAG, "New tile created - X: " + tileX + ", Y: " + tileY + ", Width: " + tileWidth + ", Height: " + tileHeight); + } + return actualPositions; + } + + + @SuppressWarnings("unused") + private void processChange(ArrayList positions) { + for (int i = 0; i < tiles.size(); i++) { + final SingleTileLayout currentTile = tiles.get(i); + final TilePosition targetPosition = positions.get(i); + currentTile.setPosition(targetPosition); + + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( + (int)targetPosition.getWidth(), + (int)targetPosition.getHeight(), + Gravity.TOP + Gravity.LEFT); + lp.setMargins((int)targetPosition.getX(), + (int)targetPosition.getY(), 0, 0); + + currentTile.setLayoutParams(lp); + } + } + + + private void animateChange(ArrayList positions) { + AnimationSet animationSet = new AnimationSet(true); + DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); + + for (int i = 0; i < tiles.size(); i++) { + AnimationSet scaleAndMove = new AnimationSet(true); + scaleAndMove.setFillAfter(true); + + final SingleTileLayout currentTile = tiles.get(i); + TilePosition currentPosition = currentTile.getPosition(); + final TilePosition targetPosition = positions.get(i); + + if (currentPosition == null) { + AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1); + alphaAnimation.setDuration(animatedTransitionDuration); + alphaAnimation.setStartOffset(0); + currentTile.setAnimation(alphaAnimation); + + scaleAndMove.addAnimation(alphaAnimation); + } + + currentTile.setPosition(targetPosition); + + if (!targetPosition.equals(currentPosition)) { + float toXDelta = 0, toYDelta = 0; + if (currentPosition != null) { + // Calculate new position + toXDelta = targetPosition.getX() - currentPosition.getX(); + toYDelta = targetPosition.getY() - currentPosition.getY(); + + // Factor in the scaling animation + toXDelta = toXDelta / (targetPosition.getWidth() / currentPosition.getWidth()); + toYDelta = toYDelta / (targetPosition.getHeight() / currentPosition.getHeight()); + } + + // Move + TranslateAnimation moveAnimation = new TranslateAnimation(0, toXDelta, 0, toYDelta); + moveAnimation.setDuration(animatedTransitionDuration); + moveAnimation.setStartOffset(0); + moveAnimation.setFillAfter(true); + moveAnimation.setInterpolator(decelerateInterpolator); + scaleAndMove.addAnimation(moveAnimation); + + // Physically move the tile when the animation ends + scaleAndMove.setAnimationListener(new AnimationListener() { + + @Override + public void onAnimationStart(Animation animation) { } + + @Override + public void onAnimationRepeat(Animation animation) { } + + @Override + public void onAnimationEnd(Animation animation) { + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( + (int)targetPosition.getWidth(), + (int)targetPosition.getHeight(), + Gravity.TOP + Gravity.LEFT); + lp.setMargins((int)targetPosition.getX(), + (int)targetPosition.getY(), 0, 0); + + currentTile.setLayoutParams(lp); + + // The following null animation just gets rid of screen flicker + animation = new TranslateAnimation(0.0f, 0.0f, 0.0f, 0.0f); + animation.setDuration(1); + currentTile.startAnimation(animation); + } + }); + + // Scale + if (currentPosition != null) { + ScaleAnimation scaleAnimation = + new ScaleAnimation(1, + targetPosition.getWidth() / currentPosition.getWidth(), + 1, + targetPosition.getHeight() / currentPosition.getHeight(), + Animation.ABSOLUTE, 0, + Animation.ABSOLUTE, 0); + + scaleAnimation.setDuration(animatedTransitionDuration); + scaleAnimation.setStartOffset(0); + scaleAnimation.setFillAfter(true); + scaleAndMove.addAnimation(scaleAnimation); + } + + // Set animation to the tile + currentTile.setAnimation(scaleAndMove); + } + // Add to the total animation set + animationSet.addAnimation(scaleAndMove); + } + + if (animationSet.getAnimations().size() > 0) { + Log.d(TAG, "Starting animation"); + animationSet.setFillAfter(true); + animationSet.start(); + } + } + + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayoutPreset.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayoutPreset.java new file mode 100644 index 000000000..76a13d73b --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayoutPreset.java @@ -0,0 +1,157 @@ +package com.MobileAnarchy.Android.Widgets.TilesLayout; + +import java.util.LinkedList; +import java.util.List; + +/** + * Describes the positioning of a tiles in a 100x100 environment + */ +public class TilesLayoutPreset { + + // ========================================= + // Private Members + // ========================================= + + private List _positions; + private String _presetName; + + // ========================================= + // Constructors + // ========================================= + + public TilesLayoutPreset(String name) { + _presetName = name; + _positions = new LinkedList(); + } + + // ========================================= + // Public Methods + // ========================================= + + public void add(float x, float y, float width, float height) { + TilePosition tilePosition = new TilePosition(x, y, height, width); + add(tilePosition); + } + + public void add(TilePosition tilePosition) { + _positions.add(tilePosition); + } + + public Iterable getTilePositions() { + return _positions; + } + + public int getCount() { + return _positions.size(); + } + + // ========================================= + // Static Presets Factories + // ========================================= + + public static TilesLayoutPreset get1x1() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 1X1"); + preset.add(0, 0, 100, 100); + return preset; + } + + + public static TilesLayoutPreset get1x2() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 1X2"); + preset.add(0, 0, 50, 100); + preset.add(0, 50, 50, 100); + return preset; + } + + + public static TilesLayoutPreset get2x1() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 2X1"); + preset.add(0, 0, 100, 50); + preset.add(50, 0, 100, 50); + return preset; + } + + + public static TilesLayoutPreset get2x2() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 2X2"); + preset.add(0, 0, 50, 50); + preset.add(50, 0, 50, 50); + preset.add(0, 50, 50, 50); + preset.add(50, 50, 50, 50); + return preset; + } + + public static TilesLayoutPreset get3x3() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 3X3"); + preset.add(0, 0, 100/3f, 100/3f); + preset.add(100/3f, 0, 100/3f, 100/3f); + preset.add(200/3f, 0, 100/3f, 100/3f); + preset.add(0, 100/3f, 100/3f, 100/3f); + preset.add(100/3f, 100/3f, 100/3f, 100/3f); + preset.add(200/3f, 100/3f, 100/3f, 100/3f); + preset.add(0, 200/3f, 100/3f, 100/3f); + preset.add(100/3f, 200/3f, 100/3f, 100/3f); + preset.add(200/3f, 200/3f, 100/3f, 100/3f); + return preset; + } + + public static TilesLayoutPreset get3x2() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 3X2"); + preset.add(0, 0, 50, 100/3f); + preset.add(100/3f, 0, 50, 100/3f); + preset.add(200/3f, 0, 50, 100/3f); + preset.add(0, 50, 50, 100/3f); + preset.add(100/3f, 50, 50, 100/3f); + preset.add(200/3f, 50, 50, 100/3f); + return preset; + } + + public static TilesLayoutPreset get2x3() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 2X3"); + preset.add(0, 0, 100/3f, 50); + preset.add(50, 0, 100/3f, 50); + preset.add(0, 100/3f, 100/3f, 50); + preset.add(50, 100/3f, 100/3f, 50); + preset.add(0, 200/3f, 100/3f, 50); + preset.add(50, 200/3f, 100/3f, 50); + return preset; + } + + + public static TilesLayoutPreset get4x4() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 2X2"); + preset.add(0, 0, 25, 25); + preset.add(25, 0, 25, 25); + preset.add(50, 0, 25, 25); + preset.add(75, 0, 25, 25); + preset.add(0, 25, 25, 25); + preset.add(25, 25, 25, 25); + preset.add(50, 25, 25, 25); + preset.add(75, 25, 25, 25); + preset.add(0, 50, 25, 25); + preset.add(25, 50, 25, 25); + preset.add(50, 50, 25, 25); + preset.add(75, 50, 25, 25); + preset.add(0, 75, 25, 25); + preset.add(25, 75, 25, 25); + preset.add(50, 75, 25, 25); + preset.add(75, 75, 25, 25); + return preset; + } + + public static TilesLayoutPreset get2x3x3() { + TilesLayoutPreset preset = new TilesLayoutPreset("Custom 2X4X4"); + preset.add(0, 0, 50, 50); + preset.add(50, 0, 50, 50); + preset.add(0, 50, 50, 50); + + preset.add(50, 50, 25, 25); + preset.add(75, 50, 25, 25); + preset.add(50, 75, 25, 25); + preset.add(75, 75, 25, 25); + + return preset; + } + + +} From c3b5f90b506e8cc14fadf9a914306b732011f4f8 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 21:02:05 -0500 Subject: [PATCH 068/284] AndroidGCS: Refactor the UAVO browser to use a split view - objects names on the side and content on the other side. Add a filter for settings versus data. --- androidgcs/res/layout/object_browser.xml | 54 +++++++++++- androidgcs/res/layout/pfd.xml | 34 ++++++-- .../openpilot/androidgcs/ObjectBrowser.java | 84 +++++++++++++------ .../src/org/openpilot/uavtalk/UAVObject.java | 9 +- .../org/openpilot/uavtalk/UAVObjectField.java | 6 +- 5 files changed, 151 insertions(+), 36 deletions(-) diff --git a/androidgcs/res/layout/object_browser.xml b/androidgcs/res/layout/object_browser.xml index 9c7456915..67dc0af76 100644 --- a/androidgcs/res/layout/object_browser.xml +++ b/androidgcs/res/layout/object_browser.xml @@ -2,6 +2,56 @@ - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/androidgcs/res/layout/pfd.xml b/androidgcs/res/layout/pfd.xml index 191a80eb9..5291f2724 100644 --- a/androidgcs/res/layout/pfd.xml +++ b/androidgcs/res/layout/pfd.xml @@ -1,8 +1,30 @@ - - - + + + + + + + + + + + + + diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index a6ed177a2..1a7495ada 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -16,8 +16,12 @@ import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ListView; import android.widget.Spinner; +import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; @@ -27,6 +31,7 @@ import org.openpilot.uavtalk.UAVObject; public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPreferenceChangeListener { private final String TAG = "ObjectBrower"; + int selected_index = -1; boolean connected; SharedPreferences prefs; ArrayAdapter adapter; @@ -35,10 +40,15 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref final Handler uavobjHandler = new Handler(); final Runnable updateText = new Runnable() { public void run() { - Log.d(TAG,"Update"); - update(); + updateObject(); } }; + + private final Observer updatedObserver = new Observer() { + public void update(Observable observable, Object data) { + uavobjHandler.post(updateText); + } + }; /** Called when the activity is first created. */ @Override @@ -47,20 +57,48 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref setContentView(R.layout.object_browser); prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); - - Spinner objectFilter = (Spinner) findViewById(R.id.object_list_filter); } @Override void onOPConnected() { Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT); Log.d(TAG, "onOPConnected()"); + + OnCheckedChangeListener checkListener = new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + updateList(); + } + }; + + ((CheckBox) findViewById(R.id.dataCheck)).setOnCheckedChangeListener(checkListener); + ((CheckBox) findViewById(R.id.settingsCheck)).setOnCheckedChangeListener(checkListener); + + updateList(); + } + + /** + * Populate the list of UAVO objects based on the selected filter + */ + private void updateList() { + // Disconnect any previous signals + if (selected_index > 0) + allObjects.get(selected_index).removeUpdatedObserver(updatedObserver); + selected_index = -1; + + boolean includeData = ((CheckBox) findViewById(R.id.dataCheck)).isChecked(); + boolean includeSettings = ((CheckBox) findViewById(R.id.settingsCheck)).isChecked(); List> allobjects = objMngr.getDataObjects(); allObjects = new ArrayList(); ListIterator> li = allobjects.listIterator(); while(li.hasNext()) { - allObjects.addAll(li.next()); + List objects = li.next(); + if(includeSettings && objects.get(0).isSettings()) + allObjects.addAll(objects); + else if (includeData && !objects.get(0).isSettings()) + allObjects.addAll(objects); } adapter = new ArrayAdapter(this,R.layout.object_view, allObjects); @@ -70,29 +108,25 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref objects.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View view, int position, long id) { - /*Toast.makeText(getApplicationContext(), ((TextView) view).getText(), - Toast.LENGTH_SHORT).show();*/ - Intent intent = new Intent(ObjectBrowser.this, ObjectEditor.class); - intent.putExtra("org.openpilot.androidgcs.ObjectName", allObjects.get(position).getName()); - intent.putExtra("org.openpilot.androidgcs.ObjectId", allObjects.get(position).getObjID()); - intent.putExtra("org.openpilot.androidgcs.InstId", allObjects.get(position).getInstID()); - startActivity(intent); + + if (selected_index > 0) + allObjects.get(selected_index).removeUpdatedObserver(updatedObserver); + + selected_index = position; + allObjects.get(position).addUpdatedObserver(updatedObserver); + updateObject(); } }); - - - UAVObject obj = objMngr.getObject("SystemStats"); - if(obj != null) - obj.addUpdatedObserver(new Observer() { - public void update(Observable observable, Object data) { - uavobjHandler.post(updateText); - } - }); - + } - - public void update() { - adapter.notifyDataSetChanged(); + + private void updateObject() { + //adapter.notifyDataSetChanged(); + TextView text = (TextView) findViewById(R.id.object_information); + if (selected_index >= 0 && selected_index < allObjects.size()) + text.setText(allObjects.get(selected_index).toStringData()); + else + Log.d(TAG,"Update called but invalid index: " + selected_index); } public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 28c279040..087d2b808 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -52,6 +52,11 @@ public abstract class UAVObject { } private CallbackListener updatedListeners = new CallbackListener(this); + public void removeUpdatedObserver(Observer o) { + synchronized(updatedListeners) { + updatedListeners.deleteObserver(o); + } + } public void addUpdatedObserver(Observer o) { synchronized(updatedListeners) { updatedListeners.addObserver(o); @@ -730,14 +735,14 @@ public abstract class UAVObject { */ @Override public String toString() { - return toStringBrief() + toStringData(); + return toStringBrief(); // + toStringData(); } /** * Return a string with the object information (only the header) */ public String toStringBrief() { - return getName() + " (" + Integer.toHexString(getObjID()) + " " + Integer.toHexString(getInstID()) + " " + getNumBytes() + ")\n"; + return getName(); // + " (" + Integer.toHexString(getObjID()) + " " + Integer.toHexString(getInstID()) + " " + getNumBytes() + ")\n"; } /** diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 3ed221079..af707d3a0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -469,7 +469,11 @@ public class UAVObjectField { public String toString() { String sout = new String(); - sout += name + ": " + data.toString() + " (" + units + ")\n"; + sout += name + ": " + getValue().toString(); + if (units.length() > 0) + sout += " (" + units + ")\n"; + else + sout += "\n"; return sout; } From ad496ab8a35b206c67f23ae87d8d22f4f50efa4b Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 22:20:00 -0500 Subject: [PATCH 069/284] AndroidGCS: Output all fields from the UAVObjects --- androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index af707d3a0..988642ff0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -469,7 +469,14 @@ public class UAVObjectField { public String toString() { String sout = new String(); - sout += name + ": " + getValue().toString(); + sout += name + ": "; + for (int i = 0; i < numElements; i++) { + sout += getValue(i).toString(); + if (i != numElements-1) + sout += ", "; + else + sout += " "; + } if (units.length() > 0) sout += " (" + units + ")\n"; else From 7fe8e314a78b44ab195001ad5bc79cceb01d3575 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 23:00:25 -0500 Subject: [PATCH 070/284] AndroidGCS: Refine the graphics of the object editor --- androidgcs/AndroidManifest.xml | 4 +- androidgcs/res/layout/object_browser.xml | 71 ++++++++--- androidgcs/res/layout/object_edit.xml | 9 -- androidgcs/res/layout/object_editor.xml | 49 +++++++- .../openpilot/androidgcs/ObjectBrowser.java | 19 ++- .../openpilot/androidgcs/ObjectEditView.java | 117 ++++++++---------- .../openpilot/androidgcs/ObjectEditor.java | 18 ++- 7 files changed, 179 insertions(+), 108 deletions(-) delete mode 100644 androidgcs/res/layout/object_edit.xml diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index 40b08c328..52bf9cb30 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -2,14 +2,14 @@ - + - + diff --git a/androidgcs/res/layout/object_browser.xml b/androidgcs/res/layout/object_browser.xml index 67dc0af76..567c04f15 100644 --- a/androidgcs/res/layout/object_browser.xml +++ b/androidgcs/res/layout/object_browser.xml @@ -1,10 +1,13 @@ - + - + + + - - - + android:drawSelectorOnTop="true" + android:choiceMode="singleChoice"/> + + + + + + + + + + + - - diff --git a/androidgcs/res/layout/object_editor.xml b/androidgcs/res/layout/object_editor.xml index d93b1a097..be6e219e8 100644 --- a/androidgcs/res/layout/object_editor.xml +++ b/androidgcs/res/layout/object_editor.xml @@ -1,6 +1,45 @@ - - + + + + + + + + + + + + + + + android:layout_column="1" + android:layout_gravity="center" + android:layout_row="0" + android:layout_rowSpan="2" + android:background="@android:color/transparent" + android:drawableTop="@drawable/ic_map" + android:text="@string/location_name" /> + android:layout_column="2" + android:layout_gravity="center" + android:layout_row="0" + android:layout_rowSpan="2" + android:background="@android:color/transparent" + android:drawableTop="@drawable/ic_pfd" + android:text="@string/pfd_name" /> - \ No newline at end of file +
+ diff --git a/androidgcs/res/values/arrays.xml b/androidgcs/res/values/arrays.xml new file mode 100644 index 000000000..18ee52298 --- /dev/null +++ b/androidgcs/res/values/arrays.xml @@ -0,0 +1,15 @@ + + + + None + Fake + Bluetooth + Network + + + 0 + 1 + 2 + 3 + + \ No newline at end of file diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index 8daa0ec36..e9b66a312 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -1,8 +1,13 @@ - OpenPilot GCS + OpenPilot GCS Home + OpenPilot Object Browser Settings Connect Disconnect - OpenPilot Object Browser + Settings + Automatically Connect + Connection Type + Bluetooth + Select the connection method diff --git a/androidgcs/res/xml/preferences.xml b/androidgcs/res/xml/preferences.xml new file mode 100644 index 000000000..d731f59dd --- /dev/null +++ b/androidgcs/res/xml/preferences.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/androidgcs/src/org/openpilot/androidgcs/HomePage.java b/androidgcs/src/org/openpilot/androidgcs/HomePage.java new file mode 100644 index 000000000..478c7cdca --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/HomePage.java @@ -0,0 +1,23 @@ +package org.openpilot.androidgcs; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; + +public class HomePage extends ObjectManagerActivity { + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.gcs_home); + Button objectBrowser = (Button) findViewById(R.id.launch_object_browser); + objectBrowser.setOnClickListener(new OnClickListener() { + public void onClick(View arg0) { + startActivity(new Intent(HomePage.this, ObjectBrowser.class)); + } + }); + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 7b3030d4f..5af7c7d60 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -16,6 +16,7 @@ import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Binder; import android.os.Handler; @@ -24,6 +25,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Process; +import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; @@ -48,8 +50,7 @@ public class OPTelemetryService extends Service { // Message ids static final int MSG_START = 0; - static final int MSG_CONNECT_BT = 1; - static final int MSG_CONNECT_FAKE = 2; + static final int MSG_CONNECT = 1; static final int MSG_DISCONNECT = 3; static final int MSG_TOAST = 100; @@ -70,14 +71,22 @@ public class OPTelemetryService extends Service { Toast.makeText(OPTelemetryService.this, "HERE", Toast.LENGTH_SHORT); System.out.println("HERE"); stopSelf(msg.arg2); - case MSG_CONNECT_BT: + case MSG_CONNECT: terminate = false; - activeTelem = new BTTelemetryThread(); - activeTelem.start(); - break; - case MSG_CONNECT_FAKE: - terminate = false; - activeTelem = new FakeTelemetryThread(); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); + int connection_type = Integer.decode(prefs.getString("connection_type", "")); + switch(connection_type) { + case 0: // No connection + return; + case 1: + activeTelem = new FakeTelemetryThread(); + break; + case 2: + activeTelem = new BTTelemetryThread(); + break; + case 3: + throw new Error("Unsupported"); + } activeTelem.start(); break; case MSG_DISCONNECT: @@ -146,14 +155,9 @@ public class OPTelemetryService extends Service { public TelemTask getTelemTask(int id) { return (TelemTask) activeTelem; } - public void openFakeConnection() { + public void openConnection() { Message msg = mServiceHandler.obtainMessage(); - msg.arg1 = MSG_CONNECT_FAKE; - mServiceHandler.sendMessage(msg); - } - public void openBTConnection() { - Message msg = mServiceHandler.obtainMessage(); - msg.arg1 = MSG_CONNECT_BT; + msg.arg1 = MSG_CONNECT; mServiceHandler.sendMessage(msg); } public void stopConnection() { @@ -161,6 +165,9 @@ public class OPTelemetryService extends Service { msg.arg1 = MSG_DISCONNECT; mServiceHandler.sendMessage(msg); } + public boolean isConnected() { + return activeTelem != null; + } }; public void toastMessage(String msgText) { diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index f68e839c1..f3cc56d47 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -6,15 +6,20 @@ import java.util.ListIterator; import java.util.Observable; import java.util.Observer; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.database.DataSetObserver; import android.os.Bundle; import android.os.Handler; +import android.preference.PreferenceManager; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.Adapter; import android.widget.ArrayAdapter; import android.widget.ExpandableListAdapter; import android.widget.ExpandableListView; @@ -27,36 +32,13 @@ import android.widget.Toast; import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObject; -public class ObjectBrowser extends ObjectManagerActivity { - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch(item.getItemId()) { - case R.id.menu_connect: - binder.openBTConnection(); - return true; - case R.id.menu_disconnect: - binder.stopConnection(); - updateText.run(); - return true; - case R.id.menu_settings: - return true; - default: - return super.onOptionsItemSelected(item); - } - - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.options_menu, menu); - return true; - } +public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPreferenceChangeListener { private final String TAG = "ObjectBrower"; boolean connected; - + SharedPreferences prefs; + ArrayAdapter adapter; + final Handler uavobjHandler = new Handler(); final Runnable updateText = new Runnable() { public void run() { @@ -70,6 +52,8 @@ public class ObjectBrowser extends ObjectManagerActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); + prefs = PreferenceManager.getDefaultSharedPreferences(this); + prefs.registerOnSharedPreferenceChangeListener(this); } @Override @@ -77,6 +61,17 @@ public class ObjectBrowser extends ObjectManagerActivity { Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT); Log.d(TAG, "onOPConnected()"); + List> allobjects = objMngr.getDataObjects(); + List linearized = new ArrayList(); + ListIterator> li = allobjects.listIterator(); + while(li.hasNext()) { + linearized.addAll(li.next()); + } + + adapter = new ArrayAdapter(this,R.layout.object_view, linearized); + ListView objects = (ListView) findViewById(R.id.object_list); + objects.setAdapter(adapter); + UAVObject obj = objMngr.getObject("SystemStats"); if(obj != null) obj.addUpdatedObserver(new Observer() { @@ -88,16 +83,12 @@ public class ObjectBrowser extends ObjectManagerActivity { } public void update() { - List> allobjects = objMngr.getDataObjects(); - List linearized = new ArrayList(); - ListIterator> li = allobjects.listIterator(); - while(li.hasNext()) { - linearized.addAll(li.next()); - } - - ArrayAdapter adapter = new ArrayAdapter(this,R.layout.object_view, linearized); - ListView objects = (ListView) findViewById(R.id.object_list); - objects.setAdapter(adapter); + adapter.notifyDataSetChanged(); + } + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + // TODO Auto-generated method stub + } } diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java index 12a072de7..d91946b92 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java @@ -14,6 +14,9 @@ import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; public abstract class ObjectManagerActivity extends Activity { @@ -72,6 +75,31 @@ public abstract class ObjectManagerActivity extends Activity { } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.menu_connect: + binder.openConnection(); + return true; + case R.id.menu_disconnect: + binder.stopConnection(); + return true; + case R.id.menu_settings: + startActivity(new Intent(this, Preferences.class)); + return true; + default: + return super.onOptionsItemSelected(item); + } + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.options_menu, menu); + return true; + } + @Override public void onStart() { super.onStart(); diff --git a/androidgcs/src/org/openpilot/androidgcs/Preferences.java b/androidgcs/src/org/openpilot/androidgcs/Preferences.java new file mode 100644 index 000000000..913de0f73 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/Preferences.java @@ -0,0 +1,12 @@ +package org.openpilot.androidgcs; + +import android.os.Bundle; +import android.preference.PreferenceActivity; + +public class Preferences extends PreferenceActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + } +} From fd3a02eb92ddd89d6b1faefe8c2382f1570167a1 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Mon, 21 Mar 2011 18:33:47 -0500 Subject: [PATCH 154/284] More work on the object browser/editor. Hard to make it resize itself though. --- androidgcs/AndroidManifest.xml | 1 + androidgcs/Doc/.AndroidArchitecture.txt.swp | Bin 12288 -> 0 bytes .../layout/{main.xml => object_browser.xml} | 0 androidgcs/res/layout/object_edit.xml | 9 +++ .../openpilot/androidgcs/ObjectBrowser.java | 44 ++++++++------- .../openpilot/androidgcs/ObjectEditor.java | 52 ++++++++++++++++++ .../androidgcs/ObjectManagerActivity.java | 23 +++++++- 7 files changed, 108 insertions(+), 21 deletions(-) delete mode 100644 androidgcs/Doc/.AndroidArchitecture.txt.swp rename androidgcs/res/layout/{main.xml => object_browser.xml} (100%) create mode 100644 androidgcs/res/layout/object_edit.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index a791d0fbb..fe8c6ae9a 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -26,6 +26,7 @@ + diff --git a/androidgcs/Doc/.AndroidArchitecture.txt.swp b/androidgcs/Doc/.AndroidArchitecture.txt.swp deleted file mode 100644 index 167a072526a8207b396d71d6dd7d3e7a417cba19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeHNzmFS56rMwnA3z`iK>^J`id>>QJ0S%T4RS8dVU#03?7Kh}jd#cP-0jXRGqdLy zB_JeP;2%IhK?4;OL^LQ=G-;^`1>rxSqu_h9yY}UZv?yp!`Qr2bn0fDe-}~N1+2N_J z-UffYb%x>RC}UrI^6`eazqIt*H;ip3#(SgBo~CmT`FUIA`E0F~nM7m{xr}`{U$A}N zBxNqOckRp8jIGFXrN`|{h18c-W_(-d)EbqJ6GxY}JJr{YO(x3A#FtjK{0;xG&EmPp zKxAOSK2dF}KmI(Y2WSNQYKZ7$Bo-y#E%fyh8)ATkgchzvvqA_I|u|2+e~ zSYjU`%g5?WFVvq)`#$Th@gp)28Hfx-1|kEIfyh8)ATkgchzvvqA_I|uN00%LGPe3S zW8w(}kN^K~{{8>wvy6QWdgNH7@GiVz&YUWBaGb!egqV740sWE0XPKw z{4`@0=mO_~lfb>F82cRP0!M*ofjdt!whJr+$AP~NGj<=i3)}=&fZq=>_6u+am;%ed z%fL&(-Ghw%0DKSJ0&W6r;2>}SxP5@J?|^TC1b7#?2Al(q0{?)6KY)9{ufSKpm%uIH zCJ;D!1Zx~ajtoQw{v!rDLzO8%3N*zup~i9E8`N zJjt(=($1ROmC@XJ;Y%0Jt%)q-ixtDMb+s$`1g~IalEU^A$uAAJvEPQ!Vk~WlMhc{| z+1bJ!d>}KKOOH)@=af#RWz3aDVXT*Fi}iSFw8t_^?}Wu_0x0t`OR*ESqfJcV5uM{= zXiCqg6IJbi16DEy2JlW;QP7eDT)l4K9sH7M5==$7f5Rz69N4eGEt)$7oa0aK>dR<<+V;*EZhkKkq=f0;#uJWRh7h|Lk)@Mia*XtyY#&& zZ&P+!eJnl81(K?`_p@bp0t|FA4-tfozxuZv%GMYV5G@j`J6 zy5|AVh8{o$Lu5PWw$TtDS(68fK+`@G=y$Jf_13zT3-nFZvp2l7T4daWb|zs;NP;A2 z<(RC7`h?s^4AJ|}YlBe!Esc)S*+4( zVXz0Jx=DhbcZh^O(6Wiip%Xq8!7NiU9#D!uWPYRr+*Jk6mt6^O5H9GbdN-7=fY?G2 zKqZt<w>-1wnI&T9)>r`IggCxCM`qiRMFH(r;p=PLhmUW2tq;~>J3K{ zE@~y3gMwQW(#?=$4srAA~;j1tIlNGZG^8G*3NuIRz$>-_K0|9#2o7)E zy0$aPj`Sd1^D6_g-Fh==!;D$w8{K}tv)<*GJN z%~W%*a@k^KkwQ03=yfqrhy(^WMiQ{XP&Dw5tf{9ObFD)iG$zf~s?3mXt&3{yFhFYt zLUMI{W)!}SFonYu2;1PDnASejO27?lH&?XqC1*CKB2< zJRd2H4ssgICx|G+fTt48MX*tgmL`RI(p33h$kce^=a=@Oe8i7VUSI1!c$Bh$@MKO} z)yAt)QxAH8;9x{Ma{lmmg0?`p(M<5NMIcQCRwfb;P%hM!HY3^6{aAa>5fmB5hHtb? zVZnXGHoT4&hb!U1?v2pE^H6zZEvPGvF2pr&X_;cKVK49(?j|=txdk7|DGdht+4F>0 I9l+o0U$ht(TmS$7 diff --git a/androidgcs/res/layout/main.xml b/androidgcs/res/layout/object_browser.xml similarity index 100% rename from androidgcs/res/layout/main.xml rename to androidgcs/res/layout/object_browser.xml diff --git a/androidgcs/res/layout/object_edit.xml b/androidgcs/res/layout/object_edit.xml new file mode 100644 index 000000000..62a482be9 --- /dev/null +++ b/androidgcs/res/layout/object_edit.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index f3cc56d47..df2d114a4 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -9,25 +9,16 @@ import java.util.Observer; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.database.DataSetObserver; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; -import android.widget.Adapter; +import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.ExpandableListAdapter; -import android.widget.ExpandableListView; import android.widget.ListView; -import android.widget.SimpleAdapter; -import android.widget.SimpleExpandableListAdapter; -import android.widget.TextView; import android.widget.Toast; +import android.widget.AdapterView.OnItemClickListener; import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObject; @@ -38,6 +29,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref boolean connected; SharedPreferences prefs; ArrayAdapter adapter; + List allObjects; final Handler uavobjHandler = new Handler(); final Runnable updateText = new Runnable() { @@ -51,7 +43,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.main); + setContentView(R.layout.object_browser); prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); } @@ -60,18 +52,32 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref void onOPConnected() { Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT); Log.d(TAG, "onOPConnected()"); - + List> allobjects = objMngr.getDataObjects(); - List linearized = new ArrayList(); + allObjects = new ArrayList(); ListIterator> li = allobjects.listIterator(); while(li.hasNext()) { - linearized.addAll(li.next()); + allObjects.addAll(li.next()); } - - adapter = new ArrayAdapter(this,R.layout.object_view, linearized); + + adapter = new ArrayAdapter(this,R.layout.object_view, allObjects); ListView objects = (ListView) findViewById(R.id.object_list); objects.setAdapter(adapter); + objects.setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, + int position, long id) { + /*Toast.makeText(getApplicationContext(), ((TextView) view).getText(), + Toast.LENGTH_SHORT).show();*/ + Intent intent = new Intent(ObjectBrowser.this, ObjectEditor.class); + intent.putExtra("org.openpilot.androidgcs.ObjectName", allObjects.get(position).getName()); + intent.putExtra("org.openpilot.androidgcs.ObjectId", allObjects.get(position).getObjID()); + intent.putExtra("org.openpilot.androidgcs.InstId", allObjects.get(position).getInstID()); + startActivity(intent); + } + }); + + UAVObject obj = objMngr.getObject("SystemStats"); if(obj != null) obj.addUpdatedObserver(new Observer() { @@ -81,7 +87,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref }); } - + public void update() { adapter.notifyDataSetChanged(); } @@ -89,6 +95,6 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // TODO Auto-generated method stub - + } } diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java b/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java new file mode 100644 index 000000000..33d0e2f8e --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java @@ -0,0 +1,52 @@ +package org.openpilot.androidgcs; + +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVObjectField; + +import android.os.Bundle; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +public class ObjectEditor extends ObjectManagerActivity { + + String objectName; + int objectID; + int instID; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.object_edit); + + System.out.println("Started. Intent:" + getIntent()); + Bundle extras = getIntent().getExtras(); + if(extras != null){ + objectName = extras.getString("org.openpilot.androidgcs.ObjectName"); + objectID = extras.getInt("org.openpilot.androidgcs.ObjectId"); + instID = extras.getInt("org.openpilot.androidgcs.InstId"); + } + } + + public void onOPConnected() { + UAVObject obj = objMngr.getObject(objectID, instID); + Toast.makeText(getApplicationContext(), obj.toString(), Toast.LENGTH_SHORT); + + TextView objectName = (TextView) findViewById(R.id.object_edit_name); + objectName.setText(obj.getName()); + + LinearLayout fieldViewList = (LinearLayout) findViewById(R.id.object_edit_fields); + List fields = obj.getFields(); + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + UAVObjectField field = li.next(); + TextView fieldName = new TextView(this); + fieldName.setText(field.getName()); + fieldViewList.addView(fieldName); + } + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java index d91946b92..5027d4d24 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java @@ -21,7 +21,7 @@ import android.view.MenuItem; public abstract class ObjectManagerActivity extends Activity { private final String TAG = "ObjectManagerActivity"; - private static int LOGLEVEL = 2; + private static int LOGLEVEL = 0; // private static boolean WARN = LOGLEVEL > 1; private static boolean DEBUG = LOGLEVEL > 0; @@ -106,19 +106,38 @@ public abstract class ObjectManagerActivity extends Activity { Intent intent = new Intent(this, OPTelemetryService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } + + public void onBind() { + + } /** Defines callbacks for service binding, passed to bindService() */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName arg0, IBinder service) { // We've bound to LocalService, cast the IBinder and attempt to open a connection if (DEBUG) Log.d(TAG,"Service bound"); - binder = (LocalBinder) service; + mBound = true; + binder = (LocalBinder) service; + + if(binder.isConnected()) { + TelemTask task; + if((task = binder.getTelemTask(0)) != null) { + objMngr = task.getObjectManager(); + mConnected = true; + onOPConnected(); + } + + } } public void onServiceDisconnected(ComponentName name) { mBound = false; + binder = null; mConnected = false; objMngr = null; + objMngr = null; + mConnected = false; + onOPDisconnected(); } }; } From bee57409835e2faea5b4f28bb8e3ef4d0a612ff8 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 12:59:01 -0500 Subject: [PATCH 155/284] Added a simple PFD --- androidgcs/AndroidManifest.xml | 9 +- androidgcs/res/drawable-hdpi/browser_icon.png | Bin 0 -> 456 bytes androidgcs/res/drawable-ldpi/browser_icon.png | Bin 0 -> 456 bytes androidgcs/res/drawable-mdpi/browser_icon.png | Bin 0 -> 456 bytes androidgcs/res/layout/gcs_home.xml | 9 +- androidgcs/res/layout/pfd.xml | 8 + androidgcs/res/values/colors.xml | 6 + androidgcs/res/values/strings.xml | 6 + .../openpilot/androidgcs/AttitudeView.java | 89 +++++++++++ .../org/openpilot/androidgcs/CompassView.java | 139 ++++++++++++++++++ .../org/openpilot/androidgcs/HomePage.java | 9 ++ .../src/org/openpilot/androidgcs/PFD.java | 51 +++++++ 12 files changed, 318 insertions(+), 8 deletions(-) create mode 100644 androidgcs/res/drawable-hdpi/browser_icon.png create mode 100644 androidgcs/res/drawable-ldpi/browser_icon.png create mode 100644 androidgcs/res/drawable-mdpi/browser_icon.png create mode 100644 androidgcs/res/layout/pfd.xml create mode 100644 androidgcs/res/values/colors.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/AttitudeView.java create mode 100644 androidgcs/src/org/openpilot/androidgcs/CompassView.java create mode 100644 androidgcs/src/org/openpilot/androidgcs/PFD.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index fe8c6ae9a..1942146c4 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -18,13 +18,8 @@ - - - - - - - + + diff --git a/androidgcs/res/drawable-hdpi/browser_icon.png b/androidgcs/res/drawable-hdpi/browser_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3fcee485245922172e66bad2eb2203db14cdac39 GIT binary patch literal 456 zcmV;(0XP1MP)2!duSV%belNQ;||iLJSe+;1>Z9S#NM0kJ-$^wmm*RY+To8 zv9OU+Vp%S#Dwxlg2qCa-7b$%#%SVV+t!?|?eYIMiWKtswJ$f(3w;l5V%m%S&OW63?^9=i}S!{|oRH^?GKj631~Um0~;V0=*5_l}PE6%PFYp yZavDW{)W@(8>Xp~%_jEdoebdExV#6+x#JU=$8dKofqu*Y00002!duSV%belNQ;||iLJSe+;1>Z9S#NM0kJ-$^wmm*RY+To8 zv9OU+Vp%S#Dwxlg2qCa-7b$%#%SVV+t!?|?eYIMiWKtswJ$f(3w;l5V%m%S&OW63?^9=i}S!{|oRH^?GKj631~Um0~;V0=*5_l}PE6%PFYp yZavDW{)W@(8>Xp~%_jEdoebdExV#6+x#JU=$8dKofqu*Y00002!duSV%belNQ;||iLJSe+;1>Z9S#NM0kJ-$^wmm*RY+To8 zv9OU+Vp%S#Dwxlg2qCa-7b$%#%SVV+t!?|?eYIMiWKtswJ$f(3w;l5V%m%S&OW63?^9=i}S!{|oRH^?GKj631~Um0~;V0=*5_l}PE6%PFYp yZavDW{)W@(8>Xp~%_jEdoebdExV#6+x#JU=$8dKofqu*Y0000 - + diff --git a/androidgcs/res/layout/pfd.xml b/androidgcs/res/layout/pfd.xml new file mode 100644 index 000000000..191a80eb9 --- /dev/null +++ b/androidgcs/res/layout/pfd.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/androidgcs/res/values/colors.xml b/androidgcs/res/values/colors.xml new file mode 100644 index 000000000..dc8eaf315 --- /dev/null +++ b/androidgcs/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #F555 + #AFFF + #AFFF + diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index e9b66a312..3b3a38d02 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -2,6 +2,7 @@ OpenPilot GCS Home OpenPilot Object Browser + OpenPilot PFD Settings Connect Disconnect @@ -10,4 +11,9 @@ Connection Type Bluetooth Select the connection method + Compass + N + E + S + W diff --git a/androidgcs/src/org/openpilot/androidgcs/AttitudeView.java b/androidgcs/src/org/openpilot/androidgcs/AttitudeView.java new file mode 100644 index 000000000..24a8bf5f0 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/AttitudeView.java @@ -0,0 +1,89 @@ +package org.openpilot.androidgcs; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.view.View; + +public class AttitudeView extends View { + + public AttitudeView(Context context) { + super(context); + initAttitudeView(); + } + + public AttitudeView(Context context, AttributeSet ats, int defaultStyle) { + super(context, ats, defaultStyle); + initAttitudeView(); + } + + public AttitudeView(Context context, AttributeSet ats) { + super(context, ats); + initAttitudeView(); + } + + protected void initAttitudeView() { + setFocusable(true); + + circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + circlePaint.setColor(R.color.background_color); + circlePaint.setStrokeWidth(1); + circlePaint.setStyle(Paint.Style.FILL_AND_STROKE); + Resources r = this.getResources(); + textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + textPaint.setColor(r.getColor(R.color.text_color)); + markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + markerPaint.setColor(r.getColor(R.color.marker_color)); + } + + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int measuredWidth = measure(widthMeasureSpec); + int measuredHeight = measure(heightMeasureSpec); + int d = Math.min(measuredWidth, measuredHeight); + setMeasuredDimension(d/2, d/2); + } + + private int measure(int measureSpec) { + int result = 0; + // Decode the measurement specifications. + + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.UNSPECIFIED) { // Return a default size of 200 if no bounds are specified. + result = 200; + } else { + // As you want to fill the available space + // always return the full available bounds. + result = specSize; + } + return result; + } + + private double roll; + public void setRoll(double roll) { + this.roll = roll; + } + private double pitch; + public void setPitch(double d) { + this.pitch = d; + } + + // Drawing related code + private Paint markerPaint; + private Paint textPaint; + private Paint circlePaint; + + @Override + protected void onDraw(Canvas canvas) { + int px = getMeasuredWidth() / 2; + int py = getMeasuredHeight() /2 ; + int radius = Math.min(px, py); + + canvas.drawLine(px,py, (int) (px+radius * Math.cos(roll)), (int) (py + radius * Math.sin(roll)), markerPaint); + canvas.drawLine(px,py, (int) (px+radius * Math.cos(pitch)), (int) (py + radius * Math.sin(pitch)), markerPaint); + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/CompassView.java b/androidgcs/src/org/openpilot/androidgcs/CompassView.java new file mode 100644 index 000000000..50e4abc0a --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/CompassView.java @@ -0,0 +1,139 @@ +package org.openpilot.androidgcs; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.view.View; + +public class CompassView extends View { + + public CompassView(Context context) { + super(context); + initCompassView(); + } + + public CompassView(Context context, AttributeSet ats, int defaultStyle) { + super(context, ats, defaultStyle); + initCompassView(); + } + + public CompassView(Context context, AttributeSet ats) { + super(context, ats); + initCompassView(); + } + + protected void initCompassView() { + setFocusable(true); + + circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + circlePaint.setColor(R.color.background_color); + circlePaint.setStrokeWidth(1); + circlePaint.setStyle(Paint.Style.FILL_AND_STROKE); + Resources r = this.getResources(); + northString = r.getString(R.string.cardinal_north); + eastString = r.getString(R.string.cardinal_east); + southString = r.getString(R.string.cardinal_south); + westString = r.getString(R.string.cardinal_west); + textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + textPaint.setColor(r.getColor(R.color.text_color)); + textHeight = (int)textPaint.measureText("yY"); + markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + markerPaint.setColor(r.getColor(R.color.marker_color)); + } + + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int measuredWidth = measure(widthMeasureSpec); + int measuredHeight = measure(heightMeasureSpec); + int d = Math.min(measuredWidth, measuredHeight); + setMeasuredDimension(d/2, d/2); + } + + private int measure(int measureSpec) { + int result = 0; + // Decode the measurement specifications. + + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.UNSPECIFIED) { // Return a default size of 200 if no bounds are specified. + result = 200; + } else { + // As you want to fill the available space + // always return the full available bounds. + result = specSize; + } + return result; + } + + private double bearing; + public void setBearing(double bearing) { + this.bearing = bearing; + } + + // Drawing related code + private Paint markerPaint; + private Paint textPaint; + private Paint circlePaint; + private String northString; + private String eastString; + private String southString; + private String westString; + private int textHeight; + + @Override + protected void onDraw(Canvas canvas) { + int px = getMeasuredWidth() / 2; + int py = getMeasuredHeight() /2 ; + int radius = Math.min(px, py); + // Draw the background + canvas.drawCircle(px, py, radius, circlePaint); + + // Rotate our perspective so that the ÔtopÕ is + // facing the current bearing. + canvas.save(); + canvas.rotate((float) -bearing, px, py); + + int textWidth = (int)textPaint.measureText("W"); + int cardinalX = px-textWidth/2; + int cardinalY = py-radius+textHeight; + + // Draw the marker every 15 degrees and text every 45. + for (int i = 0; i < 24; i++) { + // Draw a marker. + canvas.drawLine(px, py-radius, px, py-radius+10, markerPaint); + canvas.save(); + canvas.translate(0, textHeight); + // Draw the cardinal points + if (i % 6 == 0) { + String dirString = null; + switch (i) { + case 0 : { + dirString = northString; + int arrowY = 2*textHeight; + canvas.drawLine(px, arrowY, px-5, 3*textHeight, markerPaint); + canvas.drawLine(px, arrowY, px+5, 3*textHeight, markerPaint); + break; + } + case 6: dirString = eastString; break; + case 12: dirString = southString; break; + case 18: dirString = westString; break; + } + canvas.drawText(dirString, cardinalX, cardinalY, textPaint); + } + else if (i % 3 == 0) { + // Draw the text every alternate 45deg + String angle = String.valueOf(i*15); + float angleTextWidth = textPaint.measureText(angle); + + int angleTextX = (int)(px-angleTextWidth/2); + int angleTextY = py-radius+textHeight; + canvas.drawText(angle, angleTextX, angleTextY, textPaint); + } + canvas.restore(); + canvas.rotate(15, px, py); + } + canvas.restore(); + } +} diff --git a/androidgcs/src/org/openpilot/androidgcs/HomePage.java b/androidgcs/src/org/openpilot/androidgcs/HomePage.java index 478c7cdca..7d03e1b04 100644 --- a/androidgcs/src/org/openpilot/androidgcs/HomePage.java +++ b/androidgcs/src/org/openpilot/androidgcs/HomePage.java @@ -12,12 +12,21 @@ public class HomePage extends ObjectManagerActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gcs_home); + Button objectBrowser = (Button) findViewById(R.id.launch_object_browser); objectBrowser.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { startActivity(new Intent(HomePage.this, ObjectBrowser.class)); } }); + + Button pfd = (Button) findViewById(R.id.launch_pfd); + pfd.setOnClickListener(new OnClickListener() { + public void onClick(View arg0) { + startActivity(new Intent(HomePage.this, PFD.class)); + } + }); + } } diff --git a/androidgcs/src/org/openpilot/androidgcs/PFD.java b/androidgcs/src/org/openpilot/androidgcs/PFD.java new file mode 100644 index 000000000..e0d1b9f24 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/PFD.java @@ -0,0 +1,51 @@ +package org.openpilot.androidgcs; + +import java.util.Observable; +import java.util.Observer; + +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObject; + +import android.os.Bundle; + +public class PFD extends ObjectManagerActivity { + + double heading; + double roll; + double pitch; + + Runnable update = new Runnable() { + public void run() { + CompassView compass = (CompassView) findViewById(R.id.compass_view); + compass.setBearing((int) heading); + compass.invalidate(); + + AttitudeView attitude = (AttitudeView) findViewById(R.id.attitude_view); + attitude.setRoll(roll / 180 * Math.PI); + attitude.setPitch(pitch / 180 * Math.PI); + attitude.invalidate(); + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.pfd); + } + + @Override + void onOPConnected() { + + UAVObject obj = objMngr.getObject("AttitudeActual"); + if(obj != null) + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + UAVDataObject obj = (UAVDataObject) data; + heading = obj.getField("Yaw").getDouble(); + pitch = obj.getField("Pitch").getDouble(); + roll = obj.getField("Roll").getDouble(); + runOnUiThread(update); + } + }); + } +} From 0950d0386b4dcde192eaef54e8a69f2e43488ff4 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 12:59:17 -0500 Subject: [PATCH 156/284] Make fake telemetry show rotating attitude. --- .../org/openpilot/androidgcs/OPTelemetryService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 5af7c7d60..43cc13b04 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -200,8 +200,19 @@ public class OPTelemetryService extends Service { //toastMessage("Started fake telemetry thread"); UAVDataObject systemStats = (UAVDataObject) objMngr.getObject("SystemStats"); + UAVDataObject attitudeActual = (UAVDataObject) objMngr.getObject("AttitudeActual"); + double roll = 0; + double pitch = 0; + double yaw = 0; while( !terminate ) { + attitudeActual.getField("Roll").setDouble(roll); + attitudeActual.getField("Pitch").setDouble(pitch); + attitudeActual.getField("Yaw").setDouble(yaw); + roll = (roll + 10) % 180; + pitch = (pitch + 10) % 180; + yaw = (yaw + 10) % 360; systemStats.updated(); + attitudeActual.updated(); try { Thread.sleep(1000); } catch (InterruptedException e) { From c8c7323ab7902377f576a14635cb06b73ad17829 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 13:14:11 -0500 Subject: [PATCH 157/284] Make auto starting work. For now removed support for standalone service but easy to add back. --- .../androidgcs/OPTelemetryService.java | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 43cc13b04..67ee56d4e 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -68,10 +68,10 @@ public class OPTelemetryService extends Service { public void handleMessage(Message msg) { switch(msg.arg1) { case MSG_START: - Toast.makeText(OPTelemetryService.this, "HERE", Toast.LENGTH_SHORT); - System.out.println("HERE"); stopSelf(msg.arg2); - case MSG_CONNECT: + break; + case MSG_CONNECT: + Toast.makeText(getApplicationContext(), "Attempting connection", Toast.LENGTH_SHORT).show(); terminate = false; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); int connection_type = Integer.decode(prefs.getString("connection_type", "")); @@ -90,6 +90,7 @@ public class OPTelemetryService extends Service { activeTelem.start(); break; case MSG_DISCONNECT: + Toast.makeText(getApplicationContext(), "Disconnct", Toast.LENGTH_SHORT).show(); terminate = true; try { activeTelem.join(); @@ -101,6 +102,8 @@ public class OPTelemetryService extends Service { Intent intent = new Intent(); intent.setAction(INTENT_ACTION_DISCONNECTED); sendBroadcast(intent,null); + + stopSelf(); break; case MSG_TOAST: @@ -113,9 +116,9 @@ public class OPTelemetryService extends Service { } }; - @Override - public void onCreate() { - // Low priority thread for message handling with service + public void startup() { + Toast.makeText(getApplicationContext(), "Telemetry service starting", Toast.LENGTH_SHORT).show(); + HandlerThread thread = new HandlerThread("TelemetryServiceHandler", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); @@ -123,20 +126,27 @@ public class OPTelemetryService extends Service { // Get the HandlerThread's Looper and use it for our Handler mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); + if(prefs.getBoolean("autoconnect", false)) { + Toast.makeText(getApplicationContext(), "Should auto connect", Toast.LENGTH_SHORT); + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = MSG_CONNECT; + msg.arg2 = 0; + mServiceHandler.sendMessage(msg); + } + + } + + @Override + public void onCreate() { + startup(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { - Toast.makeText(this, "Telemetry service starting", Toast.LENGTH_SHORT).show(); - - System.out.println("Start"); - // For each start request, send a message to start a job and deliver the - // start ID so we know which request we're stopping when we finish the job - Message msg = mServiceHandler.obtainMessage(); - msg.arg1 = MSG_START; - msg.arg2 = startId; - mServiceHandler.sendMessage(msg); - + // Currently only using as bound service + // If we get killed, after returning from here, restart return START_STICKY; } @@ -156,6 +166,7 @@ public class OPTelemetryService extends Service { return (TelemTask) activeTelem; } public void openConnection() { + Toast.makeText(getApplicationContext(), "Requested open connection", Toast.LENGTH_SHORT); Message msg = mServiceHandler.obtainMessage(); msg.arg1 = MSG_CONNECT; mServiceHandler.sendMessage(msg); From 2139954e49d83beadc4d49be95875c6bda5aae95 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 21:39:44 -0500 Subject: [PATCH 158/284] Added location feature and made fake stream create movement --- androidgcs/AndroidManifest.xml | 18 +- androidgcs/default.properties | 2 +- androidgcs/res/layout/gcs_home.xml | 1 + androidgcs/res/layout/map_layout.xml | 10 + androidgcs/res/values/strings.xml | 37 ++- .../org/openpilot/androidgcs/HomePage.java | 6 + .../androidgcs/OPTelemetryService.java | 27 ++ .../org/openpilot/androidgcs/UAVLocation.java | 273 ++++++++++++++++++ 8 files changed, 351 insertions(+), 23 deletions(-) create mode 100644 androidgcs/res/layout/map_layout.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/UAVLocation.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index 1942146c4..c18dc0cb1 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -4,10 +4,14 @@ android:versionName="1.0"> + + + + @@ -16,13 +20,15 @@ - - + + - - - - + + + + + diff --git a/androidgcs/default.properties b/androidgcs/default.properties index 66db0d159..420db56e3 100644 --- a/androidgcs/default.properties +++ b/androidgcs/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-10 +target=Google Inc.:Google APIs:8 diff --git a/androidgcs/res/layout/gcs_home.xml b/androidgcs/res/layout/gcs_home.xml index 1a5a81cd7..e07f5b003 100644 --- a/androidgcs/res/layout/gcs_home.xml +++ b/androidgcs/res/layout/gcs_home.xml @@ -11,4 +11,5 @@ android:id="@+id/launch_object_browser" android:drawableLeft="@drawable/browser_icon" android:layout_centerHorizontal="true"/> + diff --git a/androidgcs/res/layout/map_layout.xml b/androidgcs/res/layout/map_layout.xml new file mode 100644 index 000000000..64c64b16e --- /dev/null +++ b/androidgcs/res/layout/map_layout.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index 3b3a38d02..7cef563e7 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -1,19 +1,24 @@ - OpenPilot GCS Home - OpenPilot Object Browser - OpenPilot PFD - Settings - Connect - Disconnect - Settings - Automatically Connect - Connection Type - Bluetooth - Select the connection method - Compass - N - E - S - W + OpenPilot GCS Home + OpenPilot Object Browser + OpenPilot PFD + OpenPilot Location + + Settings + Connect + Disconnect + + Settings + Automatically Connect + Connection Type + Bluetooth + Select the connection method + + Compass + N + E + S + W + Connected diff --git a/androidgcs/src/org/openpilot/androidgcs/HomePage.java b/androidgcs/src/org/openpilot/androidgcs/HomePage.java index 7d03e1b04..cf9664d14 100644 --- a/androidgcs/src/org/openpilot/androidgcs/HomePage.java +++ b/androidgcs/src/org/openpilot/androidgcs/HomePage.java @@ -27,6 +27,12 @@ public class HomePage extends ObjectManagerActivity { } }); + Button location = (Button) findViewById(R.id.launch_location); + location.setOnClickListener(new OnClickListener() { + public void onClick(View arg0) { + startActivity(new Intent(HomePage.this, UAVLocation.class)); + } + }); } } diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 67ee56d4e..c2914f34a 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -212,18 +212,45 @@ public class OPTelemetryService extends Service { //toastMessage("Started fake telemetry thread"); UAVDataObject systemStats = (UAVDataObject) objMngr.getObject("SystemStats"); UAVDataObject attitudeActual = (UAVDataObject) objMngr.getObject("AttitudeActual"); + UAVDataObject homeLocation = (UAVDataObject) objMngr.getObject("HomeLocation"); + UAVDataObject positionActual = (UAVDataObject) objMngr.getObject("PositionActual"); + + homeLocation.getField("Latitude").setDouble(379420315); + homeLocation.getField("Longitude").setDouble(-88330078); + homeLocation.getField("ECEF").setDouble(497665694,0); + homeLocation.getField("ECEF").setDouble(-77336320,1); + homeLocation.getField("ECEF").setDouble(390037169,2); + homeLocation.getField("RNE").setDouble(-0.60757166,0); + homeLocation.getField("RNE").setDouble(0.09441550,1); + homeLocation.getField("RNE").setDouble(0.78863323,2); + homeLocation.getField("RNE").setDouble(0.15355512,3); + homeLocation.getField("RNE").setDouble(0.98814011,4); + homeLocation.getField("RNE").setDouble(0,5); + homeLocation.getField("RNE").setDouble(-0.77928013,6); + homeLocation.getField("RNE").setDouble(0.12109867,7); + homeLocation.getField("RNE").setDouble(-0.61486387,8); + homeLocation.getField("Be").setDouble(26702.78710938,0); + homeLocation.getField("Be").setDouble(-1468.33605957,1); + homeLocation.getField("Be").setDouble(34181.78515625,2); + + double roll = 0; double pitch = 0; double yaw = 0; + double north = 0; + double east = 0; while( !terminate ) { attitudeActual.getField("Roll").setDouble(roll); attitudeActual.getField("Pitch").setDouble(pitch); attitudeActual.getField("Yaw").setDouble(yaw); + positionActual.getField("North").setDouble(north += 100); + positionActual.getField("East").setDouble(east += 100); roll = (roll + 10) % 180; pitch = (pitch + 10) % 180; yaw = (yaw + 10) % 360; systemStats.updated(); attitudeActual.updated(); + positionActual.updated(); try { Thread.sleep(1000); } catch (InterruptedException e) { diff --git a/androidgcs/src/org/openpilot/androidgcs/UAVLocation.java b/androidgcs/src/org/openpilot/androidgcs/UAVLocation.java new file mode 100644 index 000000000..72085c1d6 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/UAVLocation.java @@ -0,0 +1,273 @@ +package org.openpilot.androidgcs; + +import java.util.List; +import java.util.Observable; +import java.util.Observer; + +import org.openpilot.androidgcs.OPTelemetryService.LocalBinder; +import org.openpilot.androidgcs.OPTelemetryService.TelemTask; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVObjectManager; + +import com.google.android.maps.GeoPoint; +import com.google.android.maps.MapActivity; +import com.google.android.maps.MapController; +import com.google.android.maps.MapView; +import com.google.android.maps.Overlay; +import com.google.android.maps.Projection; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Point; +import android.graphics.RectF; +import android.os.Bundle; +import android.os.IBinder; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; + +public class UAVLocation extends MapActivity +{ + private final String TAG = "UAVLocation"; + private static int LOGLEVEL = 0; +// private static boolean WARN = LOGLEVEL > 1; + private static boolean DEBUG = LOGLEVEL > 0; + + private MapView mapView; + private MapController mapController; + + UAVObjectManager objMngr; + boolean mBound = false; + boolean mConnected = false; + LocalBinder binder; + + GeoPoint homeLocation; + GeoPoint uavLocation; + + @Override public void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.map_layout); + mapView = (MapView)findViewById(R.id.map_view); + mapController = mapView.getController(); + + mapView.displayZoomControls(true); + Double lat = 37.422006*1E6; + Double lng = -122.084095*1E6; + homeLocation = new GeoPoint(lat.intValue(), lng.intValue()); + uavLocation = homeLocation; + mapController.setCenter(homeLocation); + mapController.setZoom(18); + + List overlays = mapView.getOverlays(); + UAVOverlay myOverlay = new UAVOverlay(); + overlays.add(myOverlay); + mapView.postInvalidate(); + + // ObjectManager related stuff (can't inherit standard class) + BroadcastReceiver connectedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Log.d(TAG, "Received intent"); + TelemTask task; + if(intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_CONNECTED) == 0) { + + if(binder == null) + return; + if((task = binder.getTelemTask(0)) == null) + return; + objMngr = task.getObjectManager(); + mConnected = true; + onOPConnected(); + Log.d(TAG, "Connected()"); + } else if (intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_DISCONNECTED) == 0) { + objMngr = null; + mConnected = false; + onOPDisconnected(); + Log.d(TAG, "Disonnected()"); + } + } + }; + + IntentFilter filter = new IntentFilter(); + filter.addCategory(OPTelemetryService.INTENT_CATEGORY_GCS); + filter.addAction(OPTelemetryService.INTENT_ACTION_CONNECTED); + filter.addAction(OPTelemetryService.INTENT_ACTION_DISCONNECTED); + registerReceiver(connectedReceiver, filter); + } + + //@Override + protected boolean isRouteDisplayed() { + // IMPORTANT: This method must return true if your Activity // is displaying driving directions. Otherwise return false. + return false; + } + + public class UAVOverlay extends Overlay { + @Override + public void draw(Canvas canvas, MapView mapView, boolean shadow) { + + Projection projection = mapView.getProjection(); + + if (shadow == false) { + Point myPoint = new Point(); + projection.toPixels(uavLocation, myPoint); + + //// Draw UAV + // Create and setup your paint brush + Paint paint = new Paint(); + paint.setARGB(250, 255, 0, 0); + paint.setAntiAlias(true); + paint.setFakeBoldText(true); + + // Create the circle + int rad = 5; + RectF oval = new RectF(myPoint.x-rad, myPoint.y-rad, myPoint.x+rad, myPoint.y+rad); + + // Draw on the canvas + canvas.drawOval(oval, paint); + canvas.drawText("UAV", myPoint.x+rad, myPoint.y, paint); + + //// Draw Home + myPoint = new Point(); + projection.toPixels(homeLocation, myPoint); + + // Create and setup your paint brush + paint.setARGB(250, 0, 0, 0); + paint.setAntiAlias(true); + paint.setFakeBoldText(true); + + // Create the circle + rad = 5; + oval = new RectF(myPoint.x-rad, myPoint.y-rad, myPoint.x+rad, myPoint.y+rad); + + // Draw on the canvas + canvas.drawOval(oval, paint); + canvas.drawText("Home", myPoint.x+rad, myPoint.y, paint); + + } + } + + @Override + public boolean onTap(GeoPoint point, MapView mapView1) { + // Return true if screen tap is handled by this overlay + return false; + } + } + + void onOPConnected() { + UAVObject obj = objMngr.getObject("HomeLocation"); + if(obj != null) + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + UAVDataObject obj = (UAVDataObject) data; + Double lat = obj.getField("Latitude").getDouble() / 10; + Double lon = obj.getField("Longitude").getDouble() / 10; + homeLocation = new GeoPoint(lat.intValue(), lon.intValue()); + runOnUiThread(new Runnable() { + public void run() { + mapController.setCenter(homeLocation); + } + }); + System.out.println("HomeLocation: " + homeLocation.toString()); + } + }); + // Hacky - trigger an update + obj.updated(); + + obj = objMngr.getObject("PositionActual"); + if(obj != null) + obj.addUpdatedObserver(new Observer() { + public void update(Observable observable, Object data) { + UAVDataObject obj = (UAVDataObject) data; + Double north = obj.getField("North").getDouble(); + Double east = obj.getField("East").getDouble(); + // TODO: Correct convertion from NED to LLA. This is erroneous conversion from cm to deg + uavLocation = new GeoPoint((int) (homeLocation.getLatitudeE6() + north / 100 * 1e6 / 78847), + (int) (homeLocation.getLongitudeE6() + east / 100 * 1e6 / 78847)); + runOnUiThread(new Runnable() { + public void run() { + mapView.invalidate(); + } + }); + } + }); + + } + + void onOPDisconnected() { + + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.menu_connect: + binder.openConnection(); + return true; + case R.id.menu_disconnect: + binder.stopConnection(); + return true; + case R.id.menu_settings: + startActivity(new Intent(this, Preferences.class)); + return true; + default: + return super.onOptionsItemSelected(item); + } + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.options_menu, menu); + return true; + } + + @Override + public void onStart() { + super.onStart(); + Intent intent = new Intent(this, OPTelemetryService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + public void onBind() { + + } + + /** Defines callbacks for service binding, passed to bindService() */ + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName arg0, IBinder service) { + // We've bound to LocalService, cast the IBinder and attempt to open a connection + if (DEBUG) Log.d(TAG,"Service bound"); + mBound = true; + binder = (LocalBinder) service; + + if(binder.isConnected()) { + TelemTask task; + if((task = binder.getTelemTask(0)) != null) { + objMngr = task.getObjectManager(); + mConnected = true; + onOPConnected(); + } + + } + } + + public void onServiceDisconnected(ComponentName name) { + mBound = false; + binder = null; + mConnected = false; + objMngr = null; + objMngr = null; + mConnected = false; + onOPDisconnected(); + } + }; +} From dadcb3939621c19ce14c681486bb0541346a7155 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 21:59:36 -0500 Subject: [PATCH 159/284] Few tweaks and suppress some warnings --- androidgcs/default.properties | 2 +- androidgcs/res/xml/preferences.xml | 23 ++++++++++-------- .../openpilot/androidgcs/TelemetryWidget.java | 24 ++++++++++++++++++- .../uavobjects/UAVObjectsInitialize.java | 2 +- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/androidgcs/default.properties b/androidgcs/default.properties index 420db56e3..728f51f97 100644 --- a/androidgcs/default.properties +++ b/androidgcs/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=Google Inc.:Google APIs:8 +target=Google Inc.:Google APIs:11 diff --git a/androidgcs/res/xml/preferences.xml b/androidgcs/res/xml/preferences.xml index d731f59dd..24fd43b5e 100644 --- a/androidgcs/res/xml/preferences.xml +++ b/androidgcs/res/xml/preferences.xml @@ -1,12 +1,15 @@ - - - + + + + + + diff --git a/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java b/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java index d316526ef..51afdf568 100644 --- a/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java +++ b/androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java @@ -2,11 +2,34 @@ package org.openpilot.androidgcs; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.widget.RemoteViews; public class TelemetryWidget extends AppWidgetProvider { + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getAction().equals(OPTelemetryService.INTENT_ACTION_CONNECTED)) { + changeStatus(context, true); + } + if(intent.getAction().equals(OPTelemetryService.INTENT_ACTION_DISCONNECTED)) { + changeStatus(context, false); + } + + super.onReceive(context, intent); + } + + public void changeStatus(Context context, boolean status) { + RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.telemetry_widget); + updateViews.setTextViewText(R.id.telemetryWidgetStatus, "Connection status: " + status); + ComponentName thisWidget = new ComponentName(context, TelemetryWidget.class); + AppWidgetManager manager = AppWidgetManager.getInstance(context); + manager.updateAppWidget(thisWidget, updateViews); + + } + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N = appWidgetIds.length; @@ -16,7 +39,6 @@ public class TelemetryWidget extends AppWidgetProvider { // Get the layout for the App Widget and attach an on-click listener to the button RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.telemetry_widget); - //views.setOnClickPendingIntent(R.id.button, pendingIntent); // Tell the AppWidgetManager to perform an update on the current App Widget appWidgetManager.updateAppWidget(appWidgetId, views); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java index 4eca6ea82..d1d47aebb 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java @@ -28,7 +28,7 @@ package org.openpilot.uavtalk.uavobjects; -import org.openpilot.uavtalk.uavobjects.*; +//import org.openpilot.uavtalk.uavobjects.*; import org.openpilot.uavtalk.UAVObjectManager; public class UAVObjectsInitialize { From b654d68ee64d6a353340f46c989821b4bcf23ec5 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Wed, 23 Mar 2011 11:37:20 -0500 Subject: [PATCH 160/284] Cleaner editor interface --- androidgcs/default.properties | 2 +- androidgcs/res/layout/object_browser.xml | 3 +- androidgcs/res/layout/object_edit.xml | 6 +- androidgcs/res/layout/object_editor.xml | 6 + androidgcs/res/values/strings.xml | 3 + .../androidgcs/OPTelemetryService.java | 5 +- .../openpilot/androidgcs/ObjectBrowser.java | 3 + .../openpilot/androidgcs/ObjectEditView.java | 114 ++++++++++++++++++ .../openpilot/androidgcs/ObjectEditor.java | 12 +- 9 files changed, 138 insertions(+), 16 deletions(-) create mode 100644 androidgcs/res/layout/object_editor.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/ObjectEditView.java diff --git a/androidgcs/default.properties b/androidgcs/default.properties index 728f51f97..fd1cedd24 100644 --- a/androidgcs/default.properties +++ b/androidgcs/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=Google Inc.:Google APIs:11 +target=Google Inc.:Google APIs:10 diff --git a/androidgcs/res/layout/object_browser.xml b/androidgcs/res/layout/object_browser.xml index 880e276ff..9c7456915 100644 --- a/androidgcs/res/layout/object_browser.xml +++ b/androidgcs/res/layout/object_browser.xml @@ -2,5 +2,6 @@ - + + diff --git a/androidgcs/res/layout/object_edit.xml b/androidgcs/res/layout/object_edit.xml index 62a482be9..c161caa4c 100644 --- a/androidgcs/res/layout/object_edit.xml +++ b/androidgcs/res/layout/object_edit.xml @@ -3,7 +3,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> - - - + + + diff --git a/androidgcs/res/layout/object_editor.xml b/androidgcs/res/layout/object_editor.xml new file mode 100644 index 000000000..d93b1a097 --- /dev/null +++ b/androidgcs/res/layout/object_editor.xml @@ -0,0 +1,6 @@ + + + diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index 7cef563e7..6d69e4126 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -21,4 +21,7 @@ S W Connected + Update + Save + Send diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index c2914f34a..ce90f5a48 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -74,7 +74,8 @@ public class OPTelemetryService extends Service { Toast.makeText(getApplicationContext(), "Attempting connection", Toast.LENGTH_SHORT).show(); terminate = false; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); - int connection_type = Integer.decode(prefs.getString("connection_type", "")); + //int connection_type = Integer.decode(prefs.getString("connection_type", "")); + int connection_type = 1; switch(connection_type) { case 0: // No connection return; @@ -128,7 +129,7 @@ public class OPTelemetryService extends Service { mServiceHandler = new ServiceHandler(mServiceLooper); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); - if(prefs.getBoolean("autoconnect", false)) { + if(prefs.getBoolean("autoconnect", false) || true) { Toast.makeText(getApplicationContext(), "Should auto connect", Toast.LENGTH_SHORT); Message msg = mServiceHandler.obtainMessage(); msg.arg1 = MSG_CONNECT; diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index df2d114a4..a6ed177a2 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -17,6 +17,7 @@ import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; +import android.widget.Spinner; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; @@ -46,6 +47,8 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref setContentView(R.layout.object_browser); prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); + + Spinner objectFilter = (Spinner) findViewById(R.id.object_list_filter); } @Override diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectEditView.java b/androidgcs/src/org/openpilot/androidgcs/ObjectEditView.java new file mode 100644 index 000000000..7b81ff18c --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectEditView.java @@ -0,0 +1,114 @@ +package org.openpilot.androidgcs; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectField; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class ObjectEditView extends LinearLayout { + + TextView objectName; + List fields; + + public ObjectEditView(Context context) { + super(context); + initObjectEditView(); + } + + public ObjectEditView(Context context, AttributeSet ats, int defaultStyle) { + super(context, ats); + initObjectEditView(); + } + + public ObjectEditView(Context context, AttributeSet ats) { + super(context, ats); + initObjectEditView(); + } + + public void initObjectEditView() { + // Set orientation of layout to vertical + setOrientation(LinearLayout.VERTICAL); + + objectName = new TextView(getContext()); + objectName.setText(""); + objectName.setTextSize(14); + + // Lay them out in the compound control. + int lHeight = LayoutParams.WRAP_CONTENT; + int lWidth = LayoutParams.FILL_PARENT; + addView(objectName, new LinearLayout.LayoutParams(lWidth, lHeight)); + + fields = new ArrayList(); + } + + public void setName(String name) { + objectName.setText(name); + } + + public void addField(UAVObjectField field) { + if(field.getNumElements() == 1) { + FieldValue fieldView = new FieldValue(getContext()); + fieldView.setName(field.getName()); + if(field.isNumeric()) { + fieldView.setValue(new Double(field.getDouble()).toString()); + } else { + fieldView.setValue(field.getValue().toString()); + } + fields.add(fieldView); + addView(fieldView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT)); + } + else { + ListIterator names = field.getElementNames().listIterator(); + int i = 0; + while(names.hasNext()) { + FieldValue fieldView = new FieldValue(getContext()); + fieldView.setName(field.getName() + "-" + names.next()); + if(field.isNumeric()) { + fieldView.setValue(new Double(field.getDouble(i)).toString()); + } else { + fieldView.setValue(field.getValue(i).toString()); + } + i++; + fields.add(fieldView); + addView(fieldView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT)); + + } + } + } + + public class FieldValue extends LinearLayout { + + TextView fieldName; + EditText fieldValue; + + public FieldValue(Context context) { + super(context); + setOrientation(LinearLayout.HORIZONTAL); + + fieldName = new TextView(getContext()); + fieldValue = new EditText(getContext()); + + // Lay them out in the compound control. + addView(fieldName, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT)); + fieldValue.setWidth(300); + addView(fieldValue, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + } + + public void setName(String name) { + fieldName.setText(name); + } + + public void setValue(String value) { + fieldValue.setText(value); + } + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java b/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java index 33d0e2f8e..afbddb5e5 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java @@ -7,8 +7,6 @@ import org.openpilot.uavtalk.UAVObject; import org.openpilot.uavtalk.UAVObjectField; import android.os.Bundle; -import android.widget.LinearLayout; -import android.widget.TextView; import android.widget.Toast; public class ObjectEditor extends ObjectManagerActivity { @@ -35,17 +33,13 @@ public class ObjectEditor extends ObjectManagerActivity { UAVObject obj = objMngr.getObject(objectID, instID); Toast.makeText(getApplicationContext(), obj.toString(), Toast.LENGTH_SHORT); - TextView objectName = (TextView) findViewById(R.id.object_edit_name); - objectName.setText(obj.getName()); + ObjectEditView editView = (ObjectEditView) findViewById(R.id.object_edit_view); + editView.setName(obj.getName()); - LinearLayout fieldViewList = (LinearLayout) findViewById(R.id.object_edit_fields); List fields = obj.getFields(); ListIterator li = fields.listIterator(); while(li.hasNext()) { - UAVObjectField field = li.next(); - TextView fieldName = new TextView(this); - fieldName.setText(field.getName()); - fieldViewList.addView(fieldName); + editView.addField(li.next()); } } From 723bcddc110c252cc5024ed8fbc59910cccf472b Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Feb 2012 17:07:27 -0600 Subject: [PATCH 161/284] Update the project and checked in the meta data. Hopefully this will make it run more easily in future. --- androidgcs/.classpath | 8 +- androidgcs/.metadata/.lock | 0 androidgcs/.metadata/.log | 83 ++++ .../.metadata/.mylyn/repositories.xml.zip | Bin 0 -> 403 bytes androidgcs/.metadata/.mylyn/tasks.xml.zip | Bin 0 -> 250 bytes .../.plugins/org.eclipse.cdt.core/.log | 1 + .../.root/.indexes/history.version | 1 + .../.root/.indexes/properties.index | Bin 0 -> 57 bytes .../.root/.indexes/properties.version | 1 + .../org.eclipse.core.resources/.root/2.tree | Bin 0 -> 149 bytes .../.safetable/org.eclipse.core.resources | Bin 0 -> 614 bytes .../.settings/org.eclipse.cdt.ui.prefs | 5 + .../org.eclipse.core.resources.prefs | 3 + .../org.eclipse.epp.usagedata.recording.prefs | 3 + .../.settings/org.eclipse.jdt.ui.prefs | 15 + .../org.eclipse.mylyn.context.core.prefs | 3 + .../.settings/org.eclipse.team.cvs.ui.prefs | 3 + .../.settings/org.eclipse.team.ui.prefs | 3 + .../.settings/org.eclipse.ui.editors.prefs | 3 + .../.settings/org.eclipse.ui.ide.prefs | 5 + .../.settings/org.eclipse.ui.prefs | 3 + .../.settings/org.eclipse.ui.workbench.prefs | 3 + .../upload0.csv | 251 +++++++++++++ .../usagedata.csv | 83 ++++ .../org.eclipse.jdt.core/nonChainingJarsCache | Bin 0 -> 4 bytes .../variablesAndContainers.dat | Bin 0 -> 96 bytes .../org.eclipse.jdt.ui/OpenTypeHistory.xml | 2 + .../QualifiedTypeNameHistory.xml | 2 + .../org.eclipse.jdt.ui/dialog_settings.xml | 10 + .../org.eclipse.ui.ide/dialog_settings.xml | 9 + .../org.eclipse.ui.intro/dialog_settings.xml | 4 + .../dialog_settings.xml | 5 + .../org.eclipse.ui.workbench/workbench.xml | 355 ++++++++++++++++++ .../org.eclipse.ui.workbench/workingsets.xml | 4 + androidgcs/.metadata/version.ini | 1 + .../.settings/org.eclipse.jdt.core.prefs | 11 +- androidgcs/lint.xml | 3 + ...{default.properties => project.properties} | 4 +- 38 files changed, 879 insertions(+), 8 deletions(-) create mode 100644 androidgcs/.metadata/.lock create mode 100644 androidgcs/.metadata/.log create mode 100644 androidgcs/.metadata/.mylyn/repositories.xml.zip create mode 100644 androidgcs/.metadata/.mylyn/tasks.xml.zip create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.cdt.core/.log create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/2.tree create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.cdt.ui.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.usagedata.recording.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.cvs.ui.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/upload0.csv create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/usagedata.csv create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml create mode 100644 androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml create mode 100644 androidgcs/.metadata/version.ini create mode 100644 androidgcs/lint.xml rename androidgcs/{default.properties => project.properties} (72%) diff --git a/androidgcs/.classpath b/androidgcs/.classpath index 6f3f456df..eb33e4360 100644 --- a/androidgcs/.classpath +++ b/androidgcs/.classpath @@ -1,9 +1,9 @@ + - - - - + + + diff --git a/androidgcs/.metadata/.lock b/androidgcs/.metadata/.lock new file mode 100644 index 000000000..e69de29bb diff --git a/androidgcs/.metadata/.log b/androidgcs/.metadata/.log new file mode 100644 index 000000000..8955f7bbc --- /dev/null +++ b/androidgcs/.metadata/.log @@ -0,0 +1,83 @@ +!SESSION 2012-02-04 14:21:36.086 ----------------------------------------------- +eclipse.buildId=unknown +java.version=1.6.0_29 +java.vendor=Apple Inc. +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -keyring /Users/jcotton81/.eclipse_keyring -showlocation +Command-line arguments: -os macosx -ws cocoa -arch x86_64 -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -data /Users/jcotton81/Documents/Programming/OpenPilot/androidgcs -product org.eclipse.epp.package.cpp.product -keyring /Users/jcotton81/.eclipse_keyring -showlocation + +!ENTRY org.eclipse.core.net 1 0 2012-02-04 14:21:41.864 +!MESSAGE System property http.nonProxyHosts has been set to local|*.local|169.254/16|*.169.254/16 by an external source. This value will be overwritten using the values from the preferences + +!ENTRY org.eclipse.ui.intro.universal 4 0 2012-02-04 14:21:44.892 +!MESSAGE /Users/jcotton81/Documents/Programming/eclipse/Eclipse.app/Contents/MacOS/introData.xml (No such file or directory) +!STACK 0 +java.io.FileNotFoundException: /Users/jcotton81/Documents/Programming/eclipse/Eclipse.app/Contents/MacOS/introData.xml (No such file or directory) + at java.io.FileInputStream.open(Native Method) + at java.io.FileInputStream.(FileInputStream.java:120) + at java.io.FileInputStream.(FileInputStream.java:79) + at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:70) + at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:161) + at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:653) + at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:186) + at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:772) + at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) + at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119) + at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:235) + at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:284) + at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:180) + at org.eclipse.ui.internal.intro.universal.IntroData.parse(IntroData.java:159) + at org.eclipse.ui.internal.intro.universal.IntroData.initialize(IntroData.java:63) + at org.eclipse.ui.internal.intro.universal.IntroData.(IntroData.java:47) + at org.eclipse.ui.internal.intro.universal.CustomizationContentsArea.loadData(CustomizationContentsArea.java:624) + at org.eclipse.ui.internal.intro.universal.CustomizationContentsArea.addPages(CustomizationContentsArea.java:489) + at org.eclipse.ui.internal.intro.universal.CustomizationContentsArea.createContents(CustomizationContentsArea.java:453) + at org.eclipse.ui.internal.intro.universal.CustomizationDialog.createDialogArea(CustomizationDialog.java:44) + at org.eclipse.jface.dialogs.Dialog.createContents(Dialog.java:760) + at org.eclipse.jface.window.Window.create(Window.java:431) + at org.eclipse.jface.dialogs.Dialog.create(Dialog.java:1089) + at org.eclipse.jface.window.Window.open(Window.java:790) + at org.eclipse.ui.internal.intro.universal.CustomizeAction.run(CustomizeAction.java:35) + at org.eclipse.ui.internal.intro.universal.CustomizeAction.run(CustomizeAction.java:29) + at org.eclipse.jface.action.Action.runWithEvent(Action.java:498) + at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:584) + at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:501) + at org.eclipse.jface.action.ActionContributionItem$6.handleEvent(ActionContributionItem.java:452) + at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) + at org.eclipse.swt.widgets.Display.sendEvent(Display.java:3543) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1250) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1273) + at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258) + at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1079) + at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3441) + at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3100) + at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2405) + at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2369) + at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2221) + at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:500) + at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) + at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:493) + at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) + at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113) + at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:194) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:368) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) + at java.lang.reflect.Method.invoke(Method.java:597) + at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:559) + at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514) + at org.eclipse.equinox.launcher.Main.run(Main.java:1311) +!SESSION 2012-02-04 15:23:30.048 ----------------------------------------------- +eclipse.buildId=unknown +java.version=1.6.0_29 +java.vendor=Apple Inc. +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -keyring /Users/jcotton81/.eclipse_keyring -showlocation +Command-line arguments: -os macosx -ws cocoa -arch x86_64 -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -product org.eclipse.epp.package.cpp.product -data /Users/jcotton81/Documents/Programming/OpenPilot/androidgcs -product org.eclipse.epp.package.cpp.product -keyring /Users/jcotton81/.eclipse_keyring -showlocation + +!ENTRY org.eclipse.core.net 1 0 2012-02-04 15:23:34.575 +!MESSAGE System property http.nonProxyHosts has been set to local|*.local|169.254/16|*.169.254/16 by an external source. This value will be overwritten using the values from the preferences diff --git a/androidgcs/.metadata/.mylyn/repositories.xml.zip b/androidgcs/.metadata/.mylyn/repositories.xml.zip new file mode 100644 index 0000000000000000000000000000000000000000..e4df3bd3582f499f1a60b5def214b8ff52af6617 GIT binary patch literal 403 zcmWIWW@Zs#-~hsBMJ^5uNI(F{E=n!PFU~Bdj(; zVVO}bA}k9RU9H|_{jM!-va0dQyZ@?^bz^fywc_@+7(B7PS7R*c8`dl8&6Bbx*kFpf z!UfTNChLMenCzB(Vj$U{HcO2EMwQWWeBm$C<8L3AOn9FDyjhXMjCb8$XV&SwY{4(ytny2L z>Zr1KZsz5i=REypu2G!!Fu39-+x}N6Dmous-A{8_xY)$`S9N}$_2O##r|q}OnXHQb zs!#4`+gH4ys;~2NX}{PedAH=+g>TFBZddPTZ;$@K|4-sWx%33i%5DEskL3q=vvV9^ w68pi($iR@z%)k)f&B!FefCxZjIZyzi0`%Yv@MdKLsbB;`J0NWjG?jq?0GoN09smFU literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.mylyn/tasks.xml.zip b/androidgcs/.metadata/.mylyn/tasks.xml.zip new file mode 100644 index 0000000000000000000000000000000000000000..2c8620af394508c77be5ef0f6f867a56804938c0 GIT binary patch literal 250 zcmWIWW@Zs#-~dAIY8M9vB)|h?mn0Tv=VTU_=vCzAY~Hy3#MwX%Z(Xf(XU=a9HM(LP z5ae;z`<(yDGv3=nxp)gNZw(02(DOXw?RnEr%s1&+P<07Q|H{blRA2V9L+CH zm|nGXSgTK4vh2Bds8$6-=~ITSEzeY)TZ~o*1y2$ABUEh2^7U=bm&CMNj0^$Z>>R?m rvc?5KcT54|0B=Sn5e9@?k>x;cMFq$%5AbGX1IaQ1p%su`1y%|G7vM-E literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.cdt.core/.log b/androidgcs/.metadata/.plugins/org.eclipse.cdt.core/.log new file mode 100644 index 000000000..bce672614 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.cdt.core/.log @@ -0,0 +1 @@ +*** SESSION Feb 04, 2012 14:21:39.72 ------------------------------------------- diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version b/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version new file mode 100644 index 000000000..25cb955ba --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index b/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index new file mode 100644 index 0000000000000000000000000000000000000000..9c245ea2cfab3511d0f8b7802966a5b2bb67b287 GIT binary patch literal 57 zcmZQ%U|?WmVAN+|WMUA>FG|--P0q4Yy oITE#s5Hp-2#a#t%!FeA{J(nSSiHf?N|MotxHB4MgVOxlqE}m~5?f?J) literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources b/androidgcs/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources new file mode 100644 index 0000000000000000000000000000000000000000..f783b188fb03e942944121a16ffc8983afa430df GIT binary patch literal 614 zcmZ?R*xjhShe1S2b=vdAllRFf=Oz}Hq!uZZBqrsgaw!KVmMFNTCMg)0C>WYr8JPf) zf^%?)f{}rt5m$0fYGRQ~YEDUFe11{7UTShqWs%=_gPH`$%3P^!# zML}j!Vo7Fx9*WW|m{LPyBMW0o12Z!d14Bc+THvNbwU}6#8UwZ9a0}c5h+A-|%B{?) w%+o7LEY2?0E6s$uTVJoFC^gmAi0eSa@6X^M3jEwty}SIF!)TDD>X8;?0Hs9PH2?qr literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.cdt.ui.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.cdt.ui.prefs new file mode 100644 index 000000000..3f144b036 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.cdt.ui.prefs @@ -0,0 +1,5 @@ +#Sat Feb 04 15:21:25 CST 2012 +spelling_locale_initialized=true +useAnnotationsPrefPage=true +eclipse.preferences.version=1 +useQuickDiffPrefPage=true diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..360fc96b9 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 15:21:25 CST 2012 +version=1 +eclipse.preferences.version=1 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.usagedata.recording.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.usagedata.recording.prefs new file mode 100644 index 000000000..87706c344 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.usagedata.recording.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 14:21:44 CST 2012 +org.eclipse.epp.usagedata.recording.last-upload=1328386904231 +eclipse.preferences.version=1 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..bdcfb11b5 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,15 @@ +#Sat Feb 04 15:21:25 CST 2012 +useQuickDiffPrefPage=true +proposalOrderMigrated=true +tabWidthPropagated=true +content_assist_proposals_background=255,255,255 +org.eclipse.jdt.ui.javadoclocations.migrated=true +useAnnotationsPrefPage=true +org.eclipse.jface.textfont=1|Monaco|11.0|0|COCOA|1|; +org.eclipse.jdt.internal.ui.navigator.layout=2 +org.eclipse.jdt.ui.editor.tab.width= +org.eclipse.jdt.ui.formatterprofiles.version=11 +spelling_locale_initialized=true +eclipse.preferences.version=1 +content_assist_proposals_foreground=0,0,0 +fontPropagated=true diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs new file mode 100644 index 000000000..7ea301b2d --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 14:21:42 CST 2012 +eclipse.preferences.version=1 +mylyn.attention.migrated=true diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.cvs.ui.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.cvs.ui.prefs new file mode 100644 index 000000000..62dee9f90 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.cvs.ui.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 15:21:25 CST 2012 +pref_first_startup=false +eclipse.preferences.version=1 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs new file mode 100644 index 000000000..06b301613 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 15:21:25 CST 2012 +eclipse.preferences.version=1 +org.eclipse.team.ui.first_time=false diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs new file mode 100644 index 000000000..90e1e2da9 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 15:21:25 CST 2012 +eclipse.preferences.version=1 +overviewRuler_migration=migrated_3.1 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs new file mode 100644 index 000000000..b945f2889 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs @@ -0,0 +1,5 @@ +#Sat Feb 04 15:21:25 CST 2012 +eclipse.preferences.version=1 +tipsAndTricks=true +platformState=1328386704250 +PROBLEMS_FILTERS_MIGRATE=true diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs new file mode 100644 index 000000000..a97c1c1ab --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 15:21:25 CST 2012 +eclipse.preferences.version=1 +showIntro=false diff --git a/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs new file mode 100644 index 000000000..005c5e9bc --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs @@ -0,0 +1,3 @@ +#Sat Feb 04 14:21:42 CST 2012 +eclipse.preferences.version=1 +ENABLED_DECORATORS=com.android.ide.eclipse.adt.project.FolderDecorator\:true,org.eclipse.cdt.ui.indexedFiles\:false,org.eclipse.jdt.ui.override.decorator\:true,org.eclipse.jdt.ui.interface.decorator\:false,org.eclipse.jdt.ui.buildpath.decorator\:true,org.eclipse.mylyn.context.ui.decorator.interest\:true,org.eclipse.mylyn.tasks.ui.decorators.task\:true,org.eclipse.mylyn.team.ui.changeset.decorator\:true,org.eclipse.team.cvs.ui.decorator\:true,org.eclipse.ui.LinkedResourceDecorator\:true,org.eclipse.ui.ContentTypeDecorator\:true, diff --git a/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/upload0.csv b/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/upload0.csv new file mode 100644 index 000000000..bc6540615 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/upload0.csv @@ -0,0 +1,251 @@ +what,kind,bundleId,bundleVersion,description,time +activated,perspective,org.eclipse.cdt.ui,,"org.eclipse.cdt.ui.CPerspective",1328386903139 +started,bundle,org.eclipse.osgi,3.5.2.R35x_v20100126,"org.eclipse.osgi",1328386903141 +started,bundle,org.eclipse.equinox.simpleconfigurator,1.0.101.R35x_v20090807-1100,"org.eclipse.equinox.simpleconfigurator",1328386903142 +started,bundle,com.ibm.icu,4.0.1.v20090822,"com.ibm.icu",1328386903143 +started,bundle,org.eclipse.cdt.core,5.1.2.201002161416,"org.eclipse.cdt.core",1328386903143 +started,bundle,org.eclipse.cdt.make.ui,6.0.1.201002161416,"org.eclipse.cdt.make.ui",1328386903144 +started,bundle,org.eclipse.cdt.ui,5.1.2.201002161416,"org.eclipse.cdt.ui",1328386903147 +started,bundle,org.eclipse.core.contenttype,3.4.1.R35x_v20090826-0451,"org.eclipse.core.contenttype",1328386903148 +started,bundle,org.eclipse.core.databinding.observable,1.2.0.M20090902-0800,"org.eclipse.core.databinding.observable",1328386903148 +started,bundle,org.eclipse.core.expressions,3.4.101.R35x_v20100209,"org.eclipse.core.expressions",1328386903149 +started,bundle,org.eclipse.core.filebuffers,3.5.0.v20090526-2000,"org.eclipse.core.filebuffers",1328386903149 +started,bundle,org.eclipse.core.filesystem,1.2.1.R35x_v20091203-1235,"org.eclipse.core.filesystem",1328386903150 +started,bundle,org.eclipse.core.jobs,3.4.100.v20090429-1800,"org.eclipse.core.jobs",1328386903151 +started,bundle,org.eclipse.core.net,1.2.1.r35x_20090812-1200,"org.eclipse.core.net",1328386903152 +started,bundle,org.eclipse.core.resources,3.5.2.R35x_v20091203-1235,"org.eclipse.core.resources",1328386903153 +started,bundle,org.eclipse.core.runtime,3.5.0.v20090525,"org.eclipse.core.runtime",1328386903153 +started,bundle,org.eclipse.core.runtime.compatibility,3.2.0.v20090413,"org.eclipse.core.runtime.compatibility",1328386903154 +started,bundle,org.eclipse.core.runtime.compatibility.auth,3.2.100.v20090413,"org.eclipse.core.runtime.compatibility.auth",1328386903154 +started,bundle,org.eclipse.ecf,3.0.0.v20090831-1906,"org.eclipse.ecf",1328386903155 +started,bundle,org.eclipse.ecf.filetransfer,3.0.0.v20090831-1906,"org.eclipse.ecf.filetransfer",1328386903155 +started,bundle,org.eclipse.ecf.identity,3.0.0.v20090831-1906,"org.eclipse.ecf.identity",1328386903156 +started,bundle,org.eclipse.ecf.provider.filetransfer,3.0.1.v20090831-1906,"org.eclipse.ecf.provider.filetransfer",1328386903157 +started,bundle,org.eclipse.ecf.provider.filetransfer.httpclient,3.0.1.v20090831-1906,"org.eclipse.ecf.provider.filetransfer.httpclient",1328386903158 +started,bundle,org.eclipse.epp.usagedata.gathering,1.1.1.R201001291118,"org.eclipse.epp.usagedata.gathering",1328386903159 +started,bundle,org.eclipse.epp.usagedata.recording,1.1.1.R201001291118,"org.eclipse.epp.usagedata.recording",1328386903161 +started,bundle,org.eclipse.equinox.app,1.2.1.R35x_v20091203,"org.eclipse.equinox.app",1328386903164 +started,bundle,org.eclipse.equinox.common,3.5.1.R35x_v20090807-1100,"org.eclipse.equinox.common",1328386903165 +started,bundle,org.eclipse.equinox.ds,1.1.1.R35x_v20090806,"org.eclipse.equinox.ds",1328386903166 +started,bundle,org.eclipse.equinox.frameworkadmin,1.0.100.v20090520-1905,"org.eclipse.equinox.frameworkadmin",1328386903166 +started,bundle,org.eclipse.equinox.frameworkadmin.equinox,1.0.101.R35x_v20091214,"org.eclipse.equinox.frameworkadmin.equinox",1328386903166 +started,bundle,org.eclipse.equinox.p2.core,1.0.101.R35x_v20090819,"org.eclipse.equinox.p2.core",1328386903167 +started,bundle,org.eclipse.equinox.p2.director,1.0.101.R35x_v20100112,"org.eclipse.equinox.p2.director",1328386903168 +started,bundle,org.eclipse.equinox.p2.directorywatcher,1.0.100.v20090525,"org.eclipse.equinox.p2.directorywatcher",1328386903168 +started,bundle,org.eclipse.equinox.p2.engine,1.0.102.R35x_v20091117,"org.eclipse.equinox.p2.engine",1328386903169 +started,bundle,org.eclipse.equinox.p2.exemplarysetup,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.exemplarysetup",1328386903169 +started,bundle,org.eclipse.equinox.p2.garbagecollector,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.garbagecollector",1328386903170 +started,bundle,org.eclipse.equinox.p2.metadata,1.0.101.R35x_v20100112,"org.eclipse.equinox.p2.metadata",1328386903170 +started,bundle,org.eclipse.equinox.p2.metadata.repository,1.0.101.R35x_v20090812,"org.eclipse.equinox.p2.metadata.repository",1328386903171 +started,bundle,org.eclipse.equinox.p2.reconciler.dropins,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.reconciler.dropins",1328386903171 +started,bundle,org.eclipse.equinox.p2.repository,1.0.1.R35x_v20100105,"org.eclipse.equinox.p2.repository",1328386903172 +started,bundle,org.eclipse.equinox.p2.ui.sdk.scheduler,1.0.0.v20090520-1905,"org.eclipse.equinox.p2.ui.sdk.scheduler",1328386903172 +started,bundle,org.eclipse.equinox.p2.updatechecker,1.1.0.v20090520-1905,"org.eclipse.equinox.p2.updatechecker",1328386903172 +started,bundle,org.eclipse.equinox.preferences,3.2.301.R35x_v20091117,"org.eclipse.equinox.preferences",1328386903175 +started,bundle,org.eclipse.equinox.registry,3.4.100.v20090520-1800,"org.eclipse.equinox.registry",1328386903176 +started,bundle,org.eclipse.equinox.security,1.0.100.v20090520-1800,"org.eclipse.equinox.security",1328386903177 +started,bundle,org.eclipse.equinox.simpleconfigurator.manipulator,1.0.101.R35x_v20100209,"org.eclipse.equinox.simpleconfigurator.manipulator",1328386903177 +started,bundle,org.eclipse.equinox.util,1.0.100.v20090520-1800,"org.eclipse.equinox.util",1328386903178 +started,bundle,org.eclipse.help,3.4.1.v20090805_35x,"org.eclipse.help",1328386903179 +started,bundle,org.eclipse.jface,3.5.2.M20100120-0800,"org.eclipse.jface",1328386903179 +started,bundle,org.eclipse.jsch.core,1.1.100.I20090430-0408,"org.eclipse.jsch.core",1328386903180 +started,bundle,org.eclipse.ltk.core.refactoring,3.5.0.v20090513-2000,"org.eclipse.ltk.core.refactoring",1328386903180 +started,bundle,org.eclipse.mylyn.bugzilla.core,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.core",1328386903181 +started,bundle,org.eclipse.mylyn.bugzilla.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.ui",1328386903181 +started,bundle,org.eclipse.mylyn.commons.net,3.2.0.v20090617-0100-e3x,"org.eclipse.mylyn.commons.net",1328386903182 +started,bundle,org.eclipse.mylyn.commons.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.commons.ui",1328386903183 +started,bundle,org.eclipse.mylyn.context.core,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.core",1328386903183 +started,bundle,org.eclipse.mylyn.context.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.ui",1328386903184 +started,bundle,org.eclipse.mylyn.monitor.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.monitor.ui",1328386903185 +started,bundle,org.eclipse.mylyn.tasks.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.tasks.ui",1328386903186 +started,bundle,org.eclipse.mylyn.team.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.team.ui",1328386903186 +started,bundle,org.eclipse.team.core,3.5.1.r35x_20100113-0800,"org.eclipse.team.core",1328386903187 +started,bundle,org.eclipse.team.cvs.core,3.3.200.I20090430-0408,"org.eclipse.team.cvs.core",1328386903188 +started,bundle,org.eclipse.team.cvs.ui,3.3.202.r35x_20090930-0800,"org.eclipse.team.cvs.ui",1328386903189 +started,bundle,org.eclipse.team.ui,3.5.0.I20090430-0408,"org.eclipse.team.ui",1328386903189 +started,bundle,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui",1328386903191 +started,bundle,org.eclipse.ui.console,3.4.0.v20090513,"org.eclipse.ui.console",1328386903191 +started,bundle,org.eclipse.ui.editors,3.5.0.v20090527-2000,"org.eclipse.ui.editors",1328386903195 +started,bundle,org.eclipse.ui.forms,3.4.1.v20090714_35x,"org.eclipse.ui.forms",1328386903196 +started,bundle,org.eclipse.ui.ide,3.5.2.M20100113-0800,"org.eclipse.ui.ide",1328386903198 +started,bundle,org.eclipse.ui.intro,3.3.2.v20100111_35x,"org.eclipse.ui.intro",1328386903198 +started,bundle,org.eclipse.ui.intro.universal,3.2.300.v20090526,"org.eclipse.ui.intro.universal",1328386903198 +started,bundle,org.eclipse.ui.navigator,3.4.2.M20100120-0800,"org.eclipse.ui.navigator",1328386903199 +started,bundle,org.eclipse.ui.navigator.resources,3.4.1.M20090826-0800,"org.eclipse.ui.navigator.resources",1328386903200 +started,bundle,org.eclipse.ui.net,1.2.1.r35x_20090812-1200,"org.eclipse.ui.net",1328386903200 +started,bundle,org.eclipse.ui.views,3.4.1.M20090826-0800,"org.eclipse.ui.views",1328386903201 +started,bundle,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"org.eclipse.ui.workbench",1328386903202 +started,bundle,org.eclipse.ui.workbench.texteditor,3.5.1.r352_v20100105,"org.eclipse.ui.workbench.texteditor",1328386903203 +started,bundle,org.eclipse.update.configurator,3.3.0.v20090312,"org.eclipse.update.configurator",1328386903207 +started,bundle,org.eclipse.update.core,3.2.300.v20090525,"org.eclipse.update.core",1328386903209 +started,bundle,org.eclipse.update.scheduler,3.2.200.v20081127,"org.eclipse.update.scheduler",1328386903210 +started,bundle,org.eclipse.jdt.core,3.5.2.v_981_R35x,"org.eclipse.jdt.core",1328386903211 +started,bundle,org.eclipse.jdt.core.manipulation,1.3.0.v20090603,"org.eclipse.jdt.core.manipulation",1328386903212 +started,bundle,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui",1328386903218 +os,sysinfo,,,"macosx",1328386903226 +arch,sysinfo,,,"x86_64",1328386903226 +ws,sysinfo,,,"cocoa",1328386903226 +locale,sysinfo,,,"en_US",1328386903226 +processors,sysinfo,,,"4",1328386903226 +java.runtime.name,sysinfo,,,"Java(TM) SE Runtime Environment",1328386903226 +java.runtime.version,sysinfo,,,"1.6.0_29-b11-402-11M3527",1328386903227 +java.specification.name,sysinfo,,,"Java Platform API Specification",1328386903227 +java.specification.vendor,sysinfo,,,"Sun Microsystems Inc.",1328386903227 +java.specification.version,sysinfo,,,"1.6",1328386903227 +java.vendor,sysinfo,,,"Apple Inc.",1328386903227 +java.version,sysinfo,,,"1.6.0_29",1328386903227 +java.vm.info,sysinfo,,,"mixed mode",1328386903227 +java.vm.name,sysinfo,,,"Java HotSpot(TM) 64-Bit Server VM",1328386903227 +java.vm.specification.name,sysinfo,,,"Java Virtual Machine Specification",1328386903227 +java.vm.specification.vendor,sysinfo,,,"Sun Microsystems Inc.",1328386903227 +java.vm.specification.version,sysinfo,,,"1.0",1328386903227 +java.vm.vendor,sysinfo,,,"Apple Inc.",1328386903227 +java.vm.version,sysinfo,,,"20.4-b02-402",1328386903227 +started,bundle,org.eclipse.equinox.p2.extensionlocation,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.extensionlocation",1328386903389 +started,bundle,org.eclipse.equinox.p2.artifact.repository,1.0.101.R35x_v20090721,"org.eclipse.equinox.p2.artifact.repository",1328386903414 +started,bundle,org.eclipse.equinox.p2.publisher,1.0.1.R35x_20100105,"org.eclipse.equinox.p2.publisher",1328386903450 +started,bundle,org.eclipse.equinox.p2.touchpoint.eclipse,1.0.101.R35x_20090820-1821,"org.eclipse.equinox.p2.touchpoint.eclipse",1328386903464 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328386903480 +activated,view,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui.internal.introview",1328386903487 +error,log,,,"/Users/jcotton81/Documents/Programming/eclipse/Eclipse.app/Contents/MacOS/introData.xml (No such file or directory)",1328386904897 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328386905209 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328386906797 +started,bundle,org.eclipse.equinox.p2.updatesite,1.0.101.R35x_20100105,"org.eclipse.equinox.p2.updatesite",1328386912464 +activated,view,org.eclipse.ui.navigator.resources,3.4.1.M20090826-0800,"org.eclipse.ui.navigator.ProjectExplorer",1328386912583 +activated,view,org.eclipse.ui.navigator.resources,3.4.1.M20090826-0800,"org.eclipse.ui.navigator.ProjectExplorer",1328386912596 +closed,view,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui.internal.introview",1328386912607 +started,bundle,org.eclipse.equinox.p2.ui,1.0.101.R35x_v20090819,"org.eclipse.equinox.p2.ui",1328386912856 +started,bundle,org.eclipse.equinox.p2.ui.sdk,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.ui.sdk",1328386912895 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328386920116 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328387108087 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328387114332 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328387670491 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328387680147 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328389984496 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328389985341 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390196855 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390210754 +started,bundle,com.android.ide.eclipse.ddms,10.0.1.v201103111512-110841,"com.android.ide.eclipse.ddms",1328390214192 +started,bundle,org.eclipse.wst.sse.core,1.1.402.v201001251516,"org.eclipse.wst.sse.core",1328390214246 +started,bundle,com.android.ide.eclipse.adt,10.0.1.v201103111512-110841,"com.android.ide.eclipse.adt",1328390214248 +started,bundle,org.eclipse.ltk.ui.refactoring,3.4.101.r352_v20100209,"org.eclipse.ltk.ui.refactoring",1328390214467 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390455517 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390462855 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390470613 +opened,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.PackageExplorer",1328390470944 +started,bundle,org.eclipse.search,3.5.1.r351_v20090708-0800,"org.eclipse.search",1328390471037 +opened,view,org.eclipse.mylyn.tasks.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.tasks.ui.views.tasks",1328390471127 +activated,perspective,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.JavaPerspective",1328390471151 +activated,view,org.eclipse.ui.ide,3.5.2.M20100113-0800,"org.eclipse.ui.views.ProblemView",1328390471175 +executed,command,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui.perspectives.showPerspective",1328390471213 +executed,command,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui.perspectives.showPerspective",1328390471213 +opened,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.JavadocView",1328390474490 +activated,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.JavadocView",1328390474500 +opened,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.SourceView",1328390475141 +activated,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.SourceView",1328390475161 +activated,view,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui.JavadocView",1328390475451 +activated,view,org.eclipse.ui.ide,3.5.2.M20100113-0800,"org.eclipse.ui.views.ProblemView",1328390475842 +closed,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390485206 +stopped,bundle,org.eclipse.cdt.debug.mi.ui,6.0.0.201002161416,"org.eclipse.cdt.debug.mi.ui",1328390485703 +stopped,bundle,org.eclipse.cdt.debug.gdbjtag.ui,5.0.100.201002161416,"org.eclipse.cdt.debug.gdbjtag.ui",1328390485704 +stopped,bundle,org.eclipse.cdt.debug.gdbjtag.core,5.0.100.201002161416,"org.eclipse.cdt.debug.gdbjtag.core",1328390485704 +stopped,bundle,org.eclipse.cdt.debug.mi.core,6.0.0.201002161416,"org.eclipse.cdt.debug.mi.core",1328390485705 +stopped,bundle,org.eclipse.cdt.dsf.gdb.ui,2.0.0.201002161416,"org.eclipse.cdt.dsf.gdb.ui",1328390485706 +stopped,bundle,org.eclipse.cdt.dsf.ui,2.0.1.201002161416,"org.eclipse.cdt.dsf.ui",1328390485707 +stopped,bundle,org.eclipse.cdt.launch,6.0.0.201002161416,"org.eclipse.cdt.launch",1328390485707 +stopped,bundle,org.eclipse.cdt.debug.ui,6.0.0.201002161416,"org.eclipse.cdt.debug.ui",1328390485708 +stopped,bundle,org.eclipse.cdt.dsf.gdb,2.0.0.201002161416,"org.eclipse.cdt.dsf.gdb",1328390485709 +stopped,bundle,org.eclipse.cdt.dsf,2.0.0.201002161416,"org.eclipse.cdt.dsf",1328390485709 +stopped,bundle,org.eclipse.cdt.debug.core,6.0.0.201002161416,"org.eclipse.cdt.debug.core",1328390485710 +stopped,bundle,org.eclipse.cdt.managedbuilder.ui,5.1.0.201002161416,"org.eclipse.cdt.managedbuilder.ui",1328390485710 +stopped,bundle,org.eclipse.cdt.make.ui,6.0.1.201002161416,"org.eclipse.cdt.make.ui",1328390485711 +stopped,bundle,org.eclipse.cdt.managedbuilder.gnu.ui,5.0.100.201002161416,"org.eclipse.cdt.managedbuilder.gnu.ui",1328390485711 +stopped,bundle,org.eclipse.cdt.managedbuilder.core,6.0.0.201002161416,"org.eclipse.cdt.managedbuilder.core",1328390485712 +stopped,bundle,org.eclipse.cdt.make.core,6.0.0.201002161416,"org.eclipse.cdt.make.core",1328390485713 +stopped,bundle,org.eclipse.cdt.mylyn.ui,1.0.100.201002161416,"org.eclipse.cdt.mylyn.ui",1328390485713 +stopped,bundle,org.eclipse.cdt.ui,5.1.2.201002161416,"org.eclipse.cdt.ui",1328390485713 +stopped,bundle,org.eclipse.cdt.core,5.1.2.201002161416,"org.eclipse.cdt.core",1328390485714 +stopped,bundle,org.eclipse.mylyn.bugzilla.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.ui",1328390485714 +stopped,bundle,org.eclipse.mylyn.ide.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.ide.ui",1328390485714 +stopped,bundle,org.eclipse.mylyn.team.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.team.ui",1328390485715 +stopped,bundle,org.eclipse.mylyn.resources.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.resources.ui",1328390485715 +stopped,bundle,org.eclipse.mylyn.wikitext.tasks.ui,1.1.3.v20100217-0100-e3x,"org.eclipse.mylyn.wikitext.tasks.ui",1328390485716 +stopped,bundle,org.eclipse.mylyn.context.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.ui",1328390485716 +stopped,bundle,org.eclipse.mylyn.help.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.help.ui",1328390485716 +stopped,bundle,org.eclipse.mylyn.tasks.bugs,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.tasks.bugs",1328390485717 +stopped,bundle,org.eclipse.mylyn.tasks.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.tasks.ui",1328390485719 +stopped,bundle,org.eclipse.ant.ui,3.4.2.v20091204_r352,"org.eclipse.ant.ui",1328390485719 +stopped,bundle,com.android.ide.eclipse.adt,10.0.1.v201103111512-110841,"com.android.ide.eclipse.adt",1328390485719 +stopped,bundle,org.eclipse.jdt.junit,3.5.2.r352_v20100113-0800,"org.eclipse.jdt.junit",1328390485720 +stopped,bundle,org.eclipse.jdt.debug.ui,3.4.1.v20090811_r351,"org.eclipse.jdt.debug.ui",1328390485721 +stopped,bundle,org.eclipse.jdt.apt.ui,3.3.200.v20090930-2100_R35x,"org.eclipse.jdt.apt.ui",1328390485722 +stopped,bundle,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui",1328390485726 +stopped,bundle,org.eclipse.wst.dtd.ui,1.0.400.v200904300717,"org.eclipse.wst.dtd.ui",1328390485730 +stopped,bundle,org.eclipse.wst.xsd.ui,1.2.204.v200909021537,"org.eclipse.wst.xsd.ui",1328390485747 +stopped,bundle,org.eclipse.wst.xml.ui,1.1.2.v201001222130,"org.eclipse.wst.xml.ui",1328390485747 +stopped,bundle,org.eclipse.wst.common.ui,1.1.402.v200901262305,"org.eclipse.wst.common.ui",1328390485748 +stopped,bundle,org.eclipse.wst.sse.ui,1.1.102.v200910200227,"org.eclipse.wst.sse.ui",1328390485749 +stopped,bundle,org.eclipse.search,3.5.1.r351_v20090708-0800,"org.eclipse.search",1328390485750 +stopped,bundle,org.eclipse.ltk.ui.refactoring,3.4.101.r352_v20100209,"org.eclipse.ltk.ui.refactoring",1328390485750 +stopped,bundle,org.eclipse.team.cvs.ui,3.3.202.r35x_20090930-0800,"org.eclipse.team.cvs.ui",1328390485751 +stopped,bundle,org.eclipse.team.ui,3.5.0.I20090430-0408,"org.eclipse.team.ui",1328390485751 +stopped,bundle,org.eclipse.compare,3.5.2.r35x_20100113-0800,"org.eclipse.compare",1328390485752 +stopped,bundle,org.eclipse.ui.externaltools,3.2.0.v20090504,"org.eclipse.ui.externaltools",1328390485753 +stopped,bundle,org.eclipse.debug.ui,3.5.2.v20091028_r352,"org.eclipse.debug.ui",1328390485756 +stopped,bundle,org.eclipse.mylyn.wikitext.ui,1.1.3.v20100217-0100-e3x,"org.eclipse.mylyn.wikitext.ui",1328390485757 +stopped,bundle,com.android.ide.eclipse.hierarchyviewer,10.0.1.v201103111512-110841,"com.android.ide.eclipse.hierarchyviewer",1328390485757 +stopped,bundle,com.android.ide.eclipse.ddms,10.0.1.v201103111512-110841,"com.android.ide.eclipse.ddms",1328390485757 +stopped,bundle,org.eclipse.ui.console,3.4.0.v20090513,"org.eclipse.ui.console",1328390485757 +stopped,bundle,org.eclipse.mylyn.commons.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.commons.ui",1328390485757 +stopped,bundle,org.eclipse.ui.editors,3.5.0.v20090527-2000,"org.eclipse.ui.editors",1328390485758 +stopped,bundle,org.eclipse.ui.navigator.resources,3.4.1.M20090826-0800,"org.eclipse.ui.navigator.resources",1328390485758 +activated,perspective,org.eclipse.jdt.ui,,"org.eclipse.jdt.ui.JavaPerspective",1328390616647 +started,bundle,org.eclipse.osgi,3.5.2.R35x_v20100126,"org.eclipse.osgi",1328390616648 +started,bundle,org.eclipse.equinox.simpleconfigurator,1.0.101.R35x_v20090807-1100,"org.eclipse.equinox.simpleconfigurator",1328390616653 +started,bundle,com.ibm.icu,4.0.1.v20090822,"com.ibm.icu",1328390616654 +started,bundle,org.eclipse.core.contenttype,3.4.1.R35x_v20090826-0451,"org.eclipse.core.contenttype",1328390616654 +started,bundle,org.eclipse.core.databinding.observable,1.2.0.M20090902-0800,"org.eclipse.core.databinding.observable",1328390616655 +started,bundle,org.eclipse.core.expressions,3.4.101.R35x_v20100209,"org.eclipse.core.expressions",1328390616656 +started,bundle,org.eclipse.core.filebuffers,3.5.0.v20090526-2000,"org.eclipse.core.filebuffers",1328390616656 +started,bundle,org.eclipse.core.jobs,3.4.100.v20090429-1800,"org.eclipse.core.jobs",1328390616656 +started,bundle,org.eclipse.core.net,1.2.1.r35x_20090812-1200,"org.eclipse.core.net",1328390616657 +started,bundle,org.eclipse.core.resources,3.5.2.R35x_v20091203-1235,"org.eclipse.core.resources",1328390616658 +started,bundle,org.eclipse.core.runtime,3.5.0.v20090525,"org.eclipse.core.runtime",1328390616659 +started,bundle,org.eclipse.core.runtime.compatibility,3.2.0.v20090413,"org.eclipse.core.runtime.compatibility",1328390616659 +started,bundle,org.eclipse.core.runtime.compatibility.auth,3.2.100.v20090413,"org.eclipse.core.runtime.compatibility.auth",1328390616660 +started,bundle,org.eclipse.ecf,3.0.0.v20090831-1906,"org.eclipse.ecf",1328390616660 +started,bundle,org.eclipse.ecf.filetransfer,3.0.0.v20090831-1906,"org.eclipse.ecf.filetransfer",1328390616661 +started,bundle,org.eclipse.ecf.identity,3.0.0.v20090831-1906,"org.eclipse.ecf.identity",1328390616662 +started,bundle,org.eclipse.ecf.provider.filetransfer,3.0.1.v20090831-1906,"org.eclipse.ecf.provider.filetransfer",1328390616663 +started,bundle,org.eclipse.ecf.provider.filetransfer.httpclient,3.0.1.v20090831-1906,"org.eclipse.ecf.provider.filetransfer.httpclient",1328390616663 +started,bundle,org.eclipse.epp.usagedata.gathering,1.1.1.R201001291118,"org.eclipse.epp.usagedata.gathering",1328390616664 +started,bundle,org.eclipse.epp.usagedata.recording,1.1.1.R201001291118,"org.eclipse.epp.usagedata.recording",1328390616668 +started,bundle,org.eclipse.equinox.app,1.2.1.R35x_v20091203,"org.eclipse.equinox.app",1328390616676 +started,bundle,org.eclipse.equinox.common,3.5.1.R35x_v20090807-1100,"org.eclipse.equinox.common",1328390616676 +started,bundle,org.eclipse.equinox.ds,1.1.1.R35x_v20090806,"org.eclipse.equinox.ds",1328390616677 +started,bundle,org.eclipse.equinox.frameworkadmin,1.0.100.v20090520-1905,"org.eclipse.equinox.frameworkadmin",1328390616679 +started,bundle,org.eclipse.equinox.frameworkadmin.equinox,1.0.101.R35x_v20091214,"org.eclipse.equinox.frameworkadmin.equinox",1328390616680 +started,bundle,org.eclipse.equinox.p2.core,1.0.101.R35x_v20090819,"org.eclipse.equinox.p2.core",1328390616681 +started,bundle,org.eclipse.equinox.p2.director,1.0.101.R35x_v20100112,"org.eclipse.equinox.p2.director",1328390616682 +started,bundle,org.eclipse.equinox.p2.directorywatcher,1.0.100.v20090525,"org.eclipse.equinox.p2.directorywatcher",1328390616688 +started,bundle,org.eclipse.equinox.p2.engine,1.0.102.R35x_v20091117,"org.eclipse.equinox.p2.engine",1328390616689 +started,bundle,org.eclipse.equinox.p2.exemplarysetup,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.exemplarysetup",1328390616690 +started,bundle,org.eclipse.equinox.p2.garbagecollector,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.garbagecollector",1328390616691 +started,bundle,org.eclipse.equinox.p2.metadata,1.0.101.R35x_v20100112,"org.eclipse.equinox.p2.metadata",1328390616692 +started,bundle,org.eclipse.equinox.p2.metadata.repository,1.0.101.R35x_v20090812,"org.eclipse.equinox.p2.metadata.repository",1328390616692 +started,bundle,org.eclipse.equinox.p2.reconciler.dropins,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.reconciler.dropins",1328390616693 +started,bundle,org.eclipse.equinox.p2.repository,1.0.1.R35x_v20100105,"org.eclipse.equinox.p2.repository",1328390616693 +started,bundle,org.eclipse.equinox.p2.ui.sdk.scheduler,1.0.0.v20090520-1905,"org.eclipse.equinox.p2.ui.sdk.scheduler",1328390616694 +started,bundle,org.eclipse.equinox.p2.updatechecker,1.1.0.v20090520-1905,"org.eclipse.equinox.p2.updatechecker",1328390616695 +started,bundle,org.eclipse.equinox.preferences,3.2.301.R35x_v20091117,"org.eclipse.equinox.preferences",1328390616695 +started,bundle,org.eclipse.equinox.registry,3.4.100.v20090520-1800,"org.eclipse.equinox.registry",1328390616696 +started,bundle,org.eclipse.equinox.security,1.0.100.v20090520-1800,"org.eclipse.equinox.security",1328390616697 +started,bundle,org.eclipse.equinox.simpleconfigurator.manipulator,1.0.101.R35x_v20100209,"org.eclipse.equinox.simpleconfigurator.manipulator",1328390616697 +started,bundle,org.eclipse.equinox.util,1.0.100.v20090520-1800,"org.eclipse.equinox.util",1328390616698 +started,bundle,org.eclipse.help,3.4.1.v20090805_35x,"org.eclipse.help",1328390616698 +started,bundle,org.eclipse.jface,3.5.2.M20100120-0800,"org.eclipse.jface",1328390616699 +started,bundle,org.eclipse.jsch.core,1.1.100.I20090430-0408,"org.eclipse.jsch.core",1328390616705 +started,bundle,org.eclipse.mylyn.bugzilla.core,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.core",1328390616705 +started,bundle,org.eclipse.mylyn.bugzilla.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.ui",1328390616706 +started,bundle,org.eclipse.mylyn.commons.net,3.2.0.v20090617-0100-e3x,"org.eclipse.mylyn.commons.net",1328390616706 +started,bundle,org.eclipse.mylyn.commons.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.commons.ui",1328390616707 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/usagedata.csv b/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/usagedata.csv new file mode 100644 index 000000000..510c72478 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.epp.usagedata.recording/usagedata.csv @@ -0,0 +1,83 @@ +what,kind,bundleId,bundleVersion,description,time +started,bundle,org.eclipse.mylyn.context.core,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.core",1328390616707 +started,bundle,org.eclipse.mylyn.context.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.ui",1328390616708 +started,bundle,org.eclipse.mylyn.monitor.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.monitor.ui",1328390616708 +started,bundle,org.eclipse.mylyn.tasks.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.tasks.ui",1328390616709 +started,bundle,org.eclipse.mylyn.team.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.team.ui",1328390616710 +started,bundle,org.eclipse.search,3.5.1.r351_v20090708-0800,"org.eclipse.search",1328390616711 +started,bundle,org.eclipse.team.core,3.5.1.r35x_20100113-0800,"org.eclipse.team.core",1328390616712 +started,bundle,org.eclipse.team.cvs.core,3.3.200.I20090430-0408,"org.eclipse.team.cvs.core",1328390616712 +started,bundle,org.eclipse.team.cvs.ui,3.3.202.r35x_20090930-0800,"org.eclipse.team.cvs.ui",1328390616713 +started,bundle,org.eclipse.team.ui,3.5.0.I20090430-0408,"org.eclipse.team.ui",1328390616714 +started,bundle,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui",1328390616715 +started,bundle,org.eclipse.ui.console,3.4.0.v20090513,"org.eclipse.ui.console",1328390616716 +started,bundle,org.eclipse.ui.editors,3.5.0.v20090527-2000,"org.eclipse.ui.editors",1328390616717 +started,bundle,org.eclipse.ui.forms,3.4.1.v20090714_35x,"org.eclipse.ui.forms",1328390616717 +started,bundle,org.eclipse.ui.ide,3.5.2.M20100113-0800,"org.eclipse.ui.ide",1328390616718 +started,bundle,org.eclipse.ui.net,1.2.1.r35x_20090812-1200,"org.eclipse.ui.net",1328390616719 +started,bundle,org.eclipse.ui.views,3.4.1.M20090826-0800,"org.eclipse.ui.views",1328390616720 +started,bundle,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"org.eclipse.ui.workbench",1328390616720 +started,bundle,org.eclipse.ui.workbench.texteditor,3.5.1.r352_v20100105,"org.eclipse.ui.workbench.texteditor",1328390616721 +started,bundle,org.eclipse.update.configurator,3.3.0.v20090312,"org.eclipse.update.configurator",1328390616722 +started,bundle,org.eclipse.update.core,3.2.300.v20090525,"org.eclipse.update.core",1328390616722 +started,bundle,org.eclipse.update.scheduler,3.2.200.v20081127,"org.eclipse.update.scheduler",1328390616723 +started,bundle,org.eclipse.jdt.core,3.5.2.v_981_R35x,"org.eclipse.jdt.core",1328390616724 +started,bundle,org.eclipse.jdt.core.manipulation,1.3.0.v20090603,"org.eclipse.jdt.core.manipulation",1328390616725 +started,bundle,org.eclipse.jdt.ui,3.5.2.r352_v20100106-0800,"org.eclipse.jdt.ui",1328390616730 +os,sysinfo,,,"macosx",1328390616740 +arch,sysinfo,,,"x86_64",1328390616740 +ws,sysinfo,,,"cocoa",1328390616740 +locale,sysinfo,,,"en_US",1328390616740 +processors,sysinfo,,,"4",1328390616740 +java.runtime.name,sysinfo,,,"Java(TM) SE Runtime Environment",1328390616740 +java.runtime.version,sysinfo,,,"1.6.0_29-b11-402-11M3527",1328390616740 +java.specification.name,sysinfo,,,"Java Platform API Specification",1328390616740 +java.specification.vendor,sysinfo,,,"Sun Microsystems Inc.",1328390616740 +java.specification.version,sysinfo,,,"1.6",1328390616740 +java.vendor,sysinfo,,,"Apple Inc.",1328390616740 +java.version,sysinfo,,,"1.6.0_29",1328390616740 +java.vm.info,sysinfo,,,"mixed mode",1328390616740 +java.vm.name,sysinfo,,,"Java HotSpot(TM) 64-Bit Server VM",1328390616740 +java.vm.specification.name,sysinfo,,,"Java Virtual Machine Specification",1328390616740 +java.vm.specification.vendor,sysinfo,,,"Sun Microsystems Inc.",1328390616740 +java.vm.specification.version,sysinfo,,,"1.0",1328390616740 +java.vm.vendor,sysinfo,,,"Apple Inc.",1328390616740 +java.vm.version,sysinfo,,,"20.4-b02-402",1328390616740 +started,bundle,org.eclipse.equinox.p2.extensionlocation,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.extensionlocation",1328390616768 +started,bundle,org.eclipse.equinox.p2.artifact.repository,1.0.101.R35x_v20090721,"org.eclipse.equinox.p2.artifact.repository",1328390616783 +started,bundle,org.eclipse.equinox.p2.publisher,1.0.1.R35x_20100105,"org.eclipse.equinox.p2.publisher",1328390616808 +started,bundle,org.eclipse.equinox.p2.touchpoint.eclipse,1.0.101.R35x_20090820-1821,"org.eclipse.equinox.p2.touchpoint.eclipse",1328390616820 +deactivated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390619481 +started,bundle,org.eclipse.equinox.p2.updatesite,1.0.101.R35x_20100105,"org.eclipse.equinox.p2.updatesite",1328390623001 +started,bundle,org.eclipse.equinox.p2.ui,1.0.101.R35x_v20090819,"org.eclipse.equinox.p2.ui",1328390623371 +started,bundle,org.eclipse.equinox.p2.ui.sdk,1.0.100.v20090520-1905,"org.eclipse.equinox.p2.ui.sdk",1328390623409 +started,bundle,org.eclipse.core.filesystem,1.2.1.R35x_v20091203-1235,"org.eclipse.core.filesystem",1328390630622 +activated,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390659248 +executed,command,org.eclipse.ui,3.5.2.M20100120-0800,"org.eclipse.ui.file.import",1328390659277 +closed,workbench,org.eclipse.ui.workbench,3.5.2.M20100113-0800,"",1328390663881 +stopped,bundle,org.eclipse.cdt.debug.mi.ui,6.0.0.201002161416,"org.eclipse.cdt.debug.mi.ui",1328390664441 +stopped,bundle,org.eclipse.cdt.debug.gdbjtag.ui,5.0.100.201002161416,"org.eclipse.cdt.debug.gdbjtag.ui",1328390664442 +stopped,bundle,org.eclipse.cdt.debug.gdbjtag.core,5.0.100.201002161416,"org.eclipse.cdt.debug.gdbjtag.core",1328390664442 +stopped,bundle,org.eclipse.cdt.debug.mi.core,6.0.0.201002161416,"org.eclipse.cdt.debug.mi.core",1328390664443 +stopped,bundle,org.eclipse.cdt.dsf.gdb.ui,2.0.0.201002161416,"org.eclipse.cdt.dsf.gdb.ui",1328390664443 +stopped,bundle,org.eclipse.cdt.dsf.ui,2.0.1.201002161416,"org.eclipse.cdt.dsf.ui",1328390664444 +stopped,bundle,org.eclipse.cdt.launch,6.0.0.201002161416,"org.eclipse.cdt.launch",1328390664445 +stopped,bundle,org.eclipse.cdt.debug.ui,6.0.0.201002161416,"org.eclipse.cdt.debug.ui",1328390664446 +stopped,bundle,org.eclipse.cdt.dsf.gdb,2.0.0.201002161416,"org.eclipse.cdt.dsf.gdb",1328390664446 +stopped,bundle,org.eclipse.cdt.dsf,2.0.0.201002161416,"org.eclipse.cdt.dsf",1328390664447 +stopped,bundle,org.eclipse.cdt.debug.core,6.0.0.201002161416,"org.eclipse.cdt.debug.core",1328390664448 +stopped,bundle,org.eclipse.cdt.managedbuilder.ui,5.1.0.201002161416,"org.eclipse.cdt.managedbuilder.ui",1328390664449 +stopped,bundle,org.eclipse.cdt.make.ui,6.0.1.201002161416,"org.eclipse.cdt.make.ui",1328390664452 +stopped,bundle,org.eclipse.cdt.managedbuilder.gnu.ui,5.0.100.201002161416,"org.eclipse.cdt.managedbuilder.gnu.ui",1328390664453 +stopped,bundle,org.eclipse.cdt.managedbuilder.core,6.0.0.201002161416,"org.eclipse.cdt.managedbuilder.core",1328390664454 +stopped,bundle,org.eclipse.cdt.make.core,6.0.0.201002161416,"org.eclipse.cdt.make.core",1328390664455 +stopped,bundle,org.eclipse.cdt.mylyn.ui,1.0.100.201002161416,"org.eclipse.cdt.mylyn.ui",1328390664455 +stopped,bundle,org.eclipse.cdt.ui,5.1.2.201002161416,"org.eclipse.cdt.ui",1328390664458 +stopped,bundle,org.eclipse.cdt.core,5.1.2.201002161416,"org.eclipse.cdt.core",1328390664459 +stopped,bundle,org.eclipse.mylyn.bugzilla.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.bugzilla.ui",1328390664460 +stopped,bundle,org.eclipse.mylyn.ide.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.ide.ui",1328390664460 +stopped,bundle,org.eclipse.mylyn.team.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.team.ui",1328390664460 +stopped,bundle,org.eclipse.mylyn.resources.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.resources.ui",1328390664461 +stopped,bundle,org.eclipse.mylyn.wikitext.tasks.ui,1.1.3.v20100217-0100-e3x,"org.eclipse.mylyn.wikitext.tasks.ui",1328390664461 +stopped,bundle,org.eclipse.mylyn.context.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.context.ui",1328390664462 +stopped,bundle,org.eclipse.mylyn.help.ui,3.2.3.v20100217-0100-e3x,"org.eclipse.mylyn.help.ui",1328390664462 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache b/androidgcs/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache new file mode 100644 index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4 GIT binary patch literal 4 LcmZQzU|;|M00aO5 literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat b/androidgcs/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat new file mode 100644 index 0000000000000000000000000000000000000000..3aea61cb8e5c86745251f85e5305774c8841c019 GIT binary patch literal 96 zcmZQzU|?c^09G)??iJ)39~|V&2;?y`aCwFLd4|M$`1`to1eh4Oq0&MA{vjX{W(KeZ SA5SL`kA;B`q5)_CL=yl}T@PLW literal 0 HcmV?d00001 diff --git a/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml new file mode 100644 index 000000000..a4ee3cbc9 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml @@ -0,0 +1,2 @@ + + diff --git a/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml new file mode 100644 index 000000000..9e390f501 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml @@ -0,0 +1,2 @@ + + diff --git a/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml new file mode 100644 index 000000000..8bc608925 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml @@ -0,0 +1,10 @@ + +
+
+ + + + + +
+
diff --git a/androidgcs/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml b/androidgcs/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml new file mode 100644 index 000000000..ab9bf177c --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml @@ -0,0 +1,9 @@ + +
+
+ + +
+
+
+
diff --git a/androidgcs/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml b/androidgcs/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml new file mode 100644 index 000000000..f118f0213 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml @@ -0,0 +1,4 @@ + +
+ +
diff --git a/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml new file mode 100644 index 000000000..5b583c4be --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml @@ -0,0 +1,5 @@ + +
+
+
+
diff --git a/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml new file mode 100644 index 000000000..931fd0157 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml new file mode 100644 index 000000000..8daaf65a1 --- /dev/null +++ b/androidgcs/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/androidgcs/.metadata/version.ini b/androidgcs/.metadata/version.ini new file mode 100644 index 000000000..c51ff745b --- /dev/null +++ b/androidgcs/.metadata/version.ini @@ -0,0 +1 @@ +org.eclipse.core.runtime=1 \ No newline at end of file diff --git a/androidgcs/.settings/org.eclipse.jdt.core.prefs b/androidgcs/.settings/org.eclipse.jdt.core.prefs index f3fe4d6d6..a149e8e84 100644 --- a/androidgcs/.settings/org.eclipse.jdt.core.prefs +++ b/androidgcs/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,12 @@ -#Tue Mar 01 01:16:25 CST 2011 +#Sat Feb 04 16:05:48 CST 2012 eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.source=1.5 diff --git a/androidgcs/lint.xml b/androidgcs/lint.xml new file mode 100644 index 000000000..ee0eead5b --- /dev/null +++ b/androidgcs/lint.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/androidgcs/default.properties b/androidgcs/project.properties similarity index 72% rename from androidgcs/default.properties rename to androidgcs/project.properties index fd1cedd24..5d85d779c 100644 --- a/androidgcs/default.properties +++ b/androidgcs/project.properties @@ -4,8 +4,8 @@ # This file must be checked in Version Control Systems. # # To customize properties used by the Ant build system use, -# "build.properties", and override values to adapt the script to your +# "ant.properties", and override values to adapt the script to your # project structure. # Project target. -target=Google Inc.:Google APIs:10 +target=Google Inc.:Google APIs:13 From e1ba3d2e6311182491d3667c5cd456421ad9ef6a Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Feb 2012 18:30:04 -0600 Subject: [PATCH 162/284] Update the UAVObjects to the version on next. At some point a make script should generate these and copy from build/uavobjects-synth/java to this directory automatically. Also make sure java objects use CamelCase --- .../uavtalk/uavobjects/AHRSCalibration.java | 51 +- .../uavtalk/uavobjects/AHRSSettings.java | 32 +- .../uavtalk/uavobjects/AccessoryDesired.java | 139 +++++ .../uavtalk/uavobjects/ActuatorCommand.java | 12 +- .../uavtalk/uavobjects/ActuatorDesired.java | 2 +- .../uavtalk/uavobjects/ActuatorSettings.java | 496 ++++++++++-------- .../uavtalk/uavobjects/AhrsStatus.java | 10 +- .../uavtalk/uavobjects/AttitudeActual.java | 4 +- .../uavtalk/uavobjects/AttitudeRaw.java | 24 +- .../uavtalk/uavobjects/AttitudeSettings.java | 68 ++- .../uavtalk/uavobjects/BaroAltitude.java | 2 +- .../uavtalk/uavobjects/CameraDesired.java | 147 ++++++ .../uavobjects/CameraStabSettings.java | 205 ++++++++ ...emetrySettings.java => FaultSettings.java} | 45 +- .../uavtalk/uavobjects/FirmwareIAPObj.java | 97 +--- .../uavobjects/FlightBatterySettings.java | 177 +++++++ .../uavobjects/FlightBatteryState.java | 2 +- .../uavtalk/uavobjects/FlightPlanControl.java | 2 +- .../uavobjects/FlightPlanSettings.java | 2 +- .../uavtalk/uavobjects/FlightPlanStatus.java | 35 +- .../uavtalk/uavobjects/FlightStatus.java | 155 ++++++ .../uavobjects/FlightTelemetryStats.java | 20 +- .../uavtalk/uavobjects/GCSReceiver.java | 144 +++++ .../uavtalk/uavobjects/GCSTelemetryStats.java | 20 +- .../uavtalk/uavobjects/GPSPosition.java | 28 +- .../uavtalk/uavobjects/GPSSatellites.java | 48 +- .../openpilot/uavtalk/uavobjects/GPSTime.java | 10 +- .../uavtalk/uavobjects/GuidanceSettings.java | 76 +-- .../uavtalk/uavobjects/HomeLocation.java | 23 +- .../uavtalk/uavobjects/HwSettings.java | 291 ++++++++++ .../uavtalk/uavobjects/I2CStats.java | 34 +- .../uavobjects/ManualControlCommand.java | 55 +- .../uavobjects/ManualControlSettings.java | 313 +++++------ .../uavtalk/uavobjects/MixerSettings.java | 161 +++++- .../uavtalk/uavobjects/MixerStatus.java | 2 +- .../uavtalk/uavobjects/NedAccel.java | 2 +- .../uavtalk/uavobjects/ObjectPersistence.java | 23 +- .../uavtalk/uavobjects/PositionActual.java | 2 +- .../uavtalk/uavobjects/PositionDesired.java | 2 +- .../uavtalk/uavobjects/RateDesired.java | 2 +- ...erySettings.java => ReceiverActivity.java} | 74 ++- .../uavtalk/uavobjects/SonarAltitude.java | 2 +- .../uavobjects/StabilizationDesired.java | 4 +- .../uavobjects/StabilizationSettings.java | 119 +++-- .../uavtalk/uavobjects/SystemAlarms.java | 8 +- .../uavtalk/uavobjects/SystemSettings.java | 9 +- .../uavtalk/uavobjects/SystemStats.java | 6 +- .../uavtalk/uavobjects/TaskInfo.java | 24 +- .../uavobjects/UAVObjectsInitialize.java | 13 +- .../uavtalk/uavobjects/VelocityActual.java | 2 +- .../uavtalk/uavobjects/VelocityDesired.java | 2 +- .../uavtalk/uavobjects/WatchdogStatus.java | 2 +- .../java/uavobjectgeneratorjava.cpp | 2 +- 53 files changed, 2363 insertions(+), 867 deletions(-) create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java rename androidgcs/src/org/openpilot/uavtalk/uavobjects/{TelemetrySettings.java => FaultSettings.java} (74%) create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java rename androidgcs/src/org/openpilot/uavtalk/uavobjects/{BatterySettings.java => ReceiverActivity.java} (61%) diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java index 922582398..47d42991e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java @@ -51,30 +51,29 @@ public class AHRSCalibration extends UAVDataObject { List fields = new ArrayList(); - List measure_varElemNames = new ArrayList(); - measure_varElemNames.add("0"); - List measure_varEnumOptions = new ArrayList(); - measure_varEnumOptions.add("SET"); - measure_varEnumOptions.add("MEASURE"); - fields.add( new UAVObjectField("measure_var", "", UAVObjectField.FieldType.ENUM, measure_varElemNames, measure_varEnumOptions) ); - List accel_biasElemNames = new ArrayList(); accel_biasElemNames.add("X"); accel_biasElemNames.add("Y"); accel_biasElemNames.add("Z"); - fields.add( new UAVObjectField("accel_bias", "m/s^2", UAVObjectField.FieldType.FLOAT32, accel_biasElemNames, null) ); + fields.add( new UAVObjectField("accel_bias", "m/s", UAVObjectField.FieldType.FLOAT32, accel_biasElemNames, null) ); List accel_scaleElemNames = new ArrayList(); accel_scaleElemNames.add("X"); accel_scaleElemNames.add("Y"); accel_scaleElemNames.add("Z"); - fields.add( new UAVObjectField("accel_scale", "(m/s^2)/lsb", UAVObjectField.FieldType.FLOAT32, accel_scaleElemNames, null) ); + fields.add( new UAVObjectField("accel_scale", "(m/s)/lsb", UAVObjectField.FieldType.FLOAT32, accel_scaleElemNames, null) ); + + List accel_orthoElemNames = new ArrayList(); + accel_orthoElemNames.add("XY"); + accel_orthoElemNames.add("XZ"); + accel_orthoElemNames.add("YZ"); + fields.add( new UAVObjectField("accel_ortho", "scale", UAVObjectField.FieldType.FLOAT32, accel_orthoElemNames, null) ); List accel_varElemNames = new ArrayList(); accel_varElemNames.add("X"); accel_varElemNames.add("Y"); accel_varElemNames.add("Z"); - fields.add( new UAVObjectField("accel_var", "(m/s^2)^2", UAVObjectField.FieldType.FLOAT32, accel_varElemNames, null) ); + fields.add( new UAVObjectField("accel_var", "(m/s)^2", UAVObjectField.FieldType.FLOAT32, accel_varElemNames, null) ); List gyro_biasElemNames = new ArrayList(); gyro_biasElemNames.add("X"); @@ -126,6 +125,13 @@ public class AHRSCalibration extends UAVDataObject { pos_varElemNames.add("0"); fields.add( new UAVObjectField("pos_var", "m^2", UAVObjectField.FieldType.FLOAT32, pos_varElemNames, null) ); + List measure_varElemNames = new ArrayList(); + measure_varElemNames.add("0"); + List measure_varEnumOptions = new ArrayList(); + measure_varEnumOptions.add("SET"); + measure_varEnumOptions.add("MEASURE"); + fields.add( new UAVObjectField("measure_var", "", UAVObjectField.FieldType.ENUM, measure_varElemNames, measure_varEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -171,19 +177,21 @@ public class AHRSCalibration extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("measure_var").setValue("SET"); getField("accel_bias").setValue(-73.5,0); getField("accel_bias").setValue(-73.5,1); getField("accel_bias").setValue(73.5,2); getField("accel_scale").setValue(0.0359,0); getField("accel_scale").setValue(0.0359,1); - getField("accel_scale").setValue(-0.0359,2); + getField("accel_scale").setValue(0.0359,2); + getField("accel_ortho").setValue(0,0); + getField("accel_ortho").setValue(0,1); + getField("accel_ortho").setValue(0,2); getField("accel_var").setValue(0.0005,0); getField("accel_var").setValue(0.0005,1); getField("accel_var").setValue(0.0005,2); - getField("gyro_bias").setValue(23,0); - getField("gyro_bias").setValue(-23,1); - getField("gyro_bias").setValue(23,2); + getField("gyro_bias").setValue(28,0); + getField("gyro_bias").setValue(-28,1); + getField("gyro_bias").setValue(28,2); getField("gyro_scale").setValue(-0.017,0); getField("gyro_scale").setValue(0.017,1); getField("gyro_scale").setValue(-0.017,2); @@ -196,14 +204,15 @@ public class AHRSCalibration extends UAVDataObject { getField("mag_bias").setValue(0,0); getField("mag_bias").setValue(0,1); getField("mag_bias").setValue(0,2); - getField("mag_scale").setValue(-2,0); - getField("mag_scale").setValue(-2,1); - getField("mag_scale").setValue(-2,2); + getField("mag_scale").setValue(1,0); + getField("mag_scale").setValue(1,1); + getField("mag_scale").setValue(1,2); getField("mag_var").setValue(50,0); getField("mag_var").setValue(50,1); getField("mag_var").setValue(50,2); - getField("vel_var").setValue(0.4); - getField("pos_var").setValue(0.4); + getField("vel_var").setValue(10); + getField("pos_var").setValue(0.04); + getField("measure_var").setValue("SET"); } @@ -232,7 +241,7 @@ public class AHRSCalibration extends UAVDataObject { } // Constants - protected static final int OBJID = 0x30101BB2; + protected static final int OBJID = 0xFD0EDFC4; protected static final String NAME = "AHRSCalibration"; protected static String DESCRIPTION = "Contains the calibration settings for the @ref AHRSCommsModule"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java index c49c04778..032dae775 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java @@ -51,6 +51,18 @@ public class AHRSSettings extends UAVDataObject { List fields = new ArrayList(); + List YawBiasElemNames = new ArrayList(); + YawBiasElemNames.add("0"); + fields.add( new UAVObjectField("YawBias", "", UAVObjectField.FieldType.FLOAT32, YawBiasElemNames, null) ); + + List PitchBiasElemNames = new ArrayList(); + PitchBiasElemNames.add("0"); + fields.add( new UAVObjectField("PitchBias", "", UAVObjectField.FieldType.FLOAT32, PitchBiasElemNames, null) ); + + List RollBiasElemNames = new ArrayList(); + RollBiasElemNames.add("0"); + fields.add( new UAVObjectField("RollBias", "", UAVObjectField.FieldType.FLOAT32, RollBiasElemNames, null) ); + List AlgorithmElemNames = new ArrayList(); AlgorithmElemNames.add("0"); List AlgorithmEnumOptions = new ArrayList(); @@ -75,18 +87,6 @@ public class AHRSSettings extends UAVDataObject { BiasCorrectedRawEnumOptions.add("FALSE"); fields.add( new UAVObjectField("BiasCorrectedRaw", "", UAVObjectField.FieldType.ENUM, BiasCorrectedRawElemNames, BiasCorrectedRawEnumOptions) ); - List YawBiasElemNames = new ArrayList(); - YawBiasElemNames.add("0"); - fields.add( new UAVObjectField("YawBias", "", UAVObjectField.FieldType.FLOAT32, YawBiasElemNames, null) ); - - List PitchBiasElemNames = new ArrayList(); - PitchBiasElemNames.add("0"); - fields.add( new UAVObjectField("PitchBias", "", UAVObjectField.FieldType.FLOAT32, PitchBiasElemNames, null) ); - - List RollBiasElemNames = new ArrayList(); - RollBiasElemNames.add("0"); - fields.add( new UAVObjectField("RollBias", "", UAVObjectField.FieldType.FLOAT32, RollBiasElemNames, null) ); - // Compute the number of bytes for this object int numBytes = 0; @@ -132,13 +132,13 @@ public class AHRSSettings extends UAVDataObject { */ public void setDefaultFieldValues() { + getField("YawBias").setValue(0); + getField("PitchBias").setValue(0); + getField("RollBias").setValue(0); getField("Algorithm").setValue("INSGPS_INDOOR_NOMAG"); getField("Downsampling").setValue(20); getField("UpdatePeriod").setValue(1); getField("BiasCorrectedRaw").setValue("TRUE"); - getField("YawBias").setValue(0); - getField("PitchBias").setValue(0); - getField("RollBias").setValue(0); } @@ -167,7 +167,7 @@ public class AHRSSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0xDEFC5548; + protected static final int OBJID = 0xF8591ED8; protected static final String NAME = "AHRSSettings"; protected static String DESCRIPTION = "Settings for the @ref AHRSCommsModule to control the algorithm and what is updated"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java new file mode 100644 index 000000000..13c63dfdd --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java @@ -0,0 +1,139 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Desired Auxillary actuator settings. Comes from @ref ManualControlModule. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Desired Auxillary actuator settings. Comes from @ref ManualControlModule. + +generated from accessorydesired.xml + **/ +public class AccessoryDesired extends UAVDataObject { + + public AccessoryDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AccessoryValElemNames = new ArrayList(); + AccessoryValElemNames.add("0"); + fields.add( new UAVObjectField("AccessoryVal", "", UAVObjectField.FieldType.FLOAT32, AccessoryValElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AccessoryDesired obj = new AccessoryDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AccessoryDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (AccessoryDesired)(objMngr.getObject(AccessoryDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xC409985A; + protected static final String NAME = "AccessoryDesired"; + protected static String DESCRIPTION = "Desired Auxillary actuator settings. Comes from @ref ManualControlModule."; + protected static final boolean ISSINGLEINST = 0 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java index a5d6230ac..08f2ebefe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java @@ -60,16 +60,18 @@ public class ActuatorCommand extends UAVDataObject { ChannelElemNames.add("5"); ChannelElemNames.add("6"); ChannelElemNames.add("7"); + ChannelElemNames.add("8"); + ChannelElemNames.add("9"); fields.add( new UAVObjectField("Channel", "us", UAVObjectField.FieldType.INT16, ChannelElemNames, null) ); - List UpdateTimeElemNames = new ArrayList(); - UpdateTimeElemNames.add("0"); - fields.add( new UAVObjectField("UpdateTime", "ms", UAVObjectField.FieldType.UINT8, UpdateTimeElemNames, null) ); - List MaxUpdateTimeElemNames = new ArrayList(); MaxUpdateTimeElemNames.add("0"); fields.add( new UAVObjectField("MaxUpdateTime", "ms", UAVObjectField.FieldType.UINT16, MaxUpdateTimeElemNames, null) ); + List UpdateTimeElemNames = new ArrayList(); + UpdateTimeElemNames.add("0"); + fields.add( new UAVObjectField("UpdateTime", "ms", UAVObjectField.FieldType.UINT8, UpdateTimeElemNames, null) ); + List NumFailedUpdatesElemNames = new ArrayList(); NumFailedUpdatesElemNames.add("0"); fields.add( new UAVObjectField("NumFailedUpdates", "", UAVObjectField.FieldType.UINT8, NumFailedUpdatesElemNames, null) ); @@ -147,7 +149,7 @@ public class ActuatorCommand extends UAVDataObject { } // Constants - protected static final int OBJID = 0xE8E077D8; + protected static final int OBJID = 0x5324CB8; protected static final String NAME = "ActuatorCommand"; protected static String DESCRIPTION = "Contains the pulse duration sent to each of the channels. Set by @ref ActuatorModule"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java index b81ca29da..03ff1985c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java @@ -148,7 +148,7 @@ public class ActuatorDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0xD4516782; + protected static final int OBJID = 0xCA4BC4A4; protected static final String NAME = "ActuatorDesired"; protected static String DESCRIPTION = "Desired raw, pitch and yaw actuator settings. Comes from either @ref StabilizationModule or @ref ManualControlModule depending on FlightMode."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java index 542b433d1..71b0bb49f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java @@ -51,202 +51,6 @@ public class ActuatorSettings extends UAVDataObject { List fields = new ArrayList(); - List FixedWingRoll1ElemNames = new ArrayList(); - FixedWingRoll1ElemNames.add("0"); - List FixedWingRoll1EnumOptions = new ArrayList(); - FixedWingRoll1EnumOptions.add("Channel1"); - FixedWingRoll1EnumOptions.add("Channel2"); - FixedWingRoll1EnumOptions.add("Channel3"); - FixedWingRoll1EnumOptions.add("Channel4"); - FixedWingRoll1EnumOptions.add("Channel5"); - FixedWingRoll1EnumOptions.add("Channel6"); - FixedWingRoll1EnumOptions.add("Channel7"); - FixedWingRoll1EnumOptions.add("Channel8"); - FixedWingRoll1EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingRoll1", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll1ElemNames, FixedWingRoll1EnumOptions) ); - - List FixedWingRoll2ElemNames = new ArrayList(); - FixedWingRoll2ElemNames.add("0"); - List FixedWingRoll2EnumOptions = new ArrayList(); - FixedWingRoll2EnumOptions.add("Channel1"); - FixedWingRoll2EnumOptions.add("Channel2"); - FixedWingRoll2EnumOptions.add("Channel3"); - FixedWingRoll2EnumOptions.add("Channel4"); - FixedWingRoll2EnumOptions.add("Channel5"); - FixedWingRoll2EnumOptions.add("Channel6"); - FixedWingRoll2EnumOptions.add("Channel7"); - FixedWingRoll2EnumOptions.add("Channel8"); - FixedWingRoll2EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingRoll2", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll2ElemNames, FixedWingRoll2EnumOptions) ); - - List FixedWingPitch1ElemNames = new ArrayList(); - FixedWingPitch1ElemNames.add("0"); - List FixedWingPitch1EnumOptions = new ArrayList(); - FixedWingPitch1EnumOptions.add("Channel1"); - FixedWingPitch1EnumOptions.add("Channel2"); - FixedWingPitch1EnumOptions.add("Channel3"); - FixedWingPitch1EnumOptions.add("Channel4"); - FixedWingPitch1EnumOptions.add("Channel5"); - FixedWingPitch1EnumOptions.add("Channel6"); - FixedWingPitch1EnumOptions.add("Channel7"); - FixedWingPitch1EnumOptions.add("Channel8"); - FixedWingPitch1EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingPitch1", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch1ElemNames, FixedWingPitch1EnumOptions) ); - - List FixedWingPitch2ElemNames = new ArrayList(); - FixedWingPitch2ElemNames.add("0"); - List FixedWingPitch2EnumOptions = new ArrayList(); - FixedWingPitch2EnumOptions.add("Channel1"); - FixedWingPitch2EnumOptions.add("Channel2"); - FixedWingPitch2EnumOptions.add("Channel3"); - FixedWingPitch2EnumOptions.add("Channel4"); - FixedWingPitch2EnumOptions.add("Channel5"); - FixedWingPitch2EnumOptions.add("Channel6"); - FixedWingPitch2EnumOptions.add("Channel7"); - FixedWingPitch2EnumOptions.add("Channel8"); - FixedWingPitch2EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingPitch2", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch2ElemNames, FixedWingPitch2EnumOptions) ); - - List FixedWingYawElemNames = new ArrayList(); - FixedWingYawElemNames.add("0"); - List FixedWingYawEnumOptions = new ArrayList(); - FixedWingYawEnumOptions.add("Channel1"); - FixedWingYawEnumOptions.add("Channel2"); - FixedWingYawEnumOptions.add("Channel3"); - FixedWingYawEnumOptions.add("Channel4"); - FixedWingYawEnumOptions.add("Channel5"); - FixedWingYawEnumOptions.add("Channel6"); - FixedWingYawEnumOptions.add("Channel7"); - FixedWingYawEnumOptions.add("Channel8"); - FixedWingYawEnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingYaw", "channel", UAVObjectField.FieldType.ENUM, FixedWingYawElemNames, FixedWingYawEnumOptions) ); - - List FixedWingThrottleElemNames = new ArrayList(); - FixedWingThrottleElemNames.add("0"); - List FixedWingThrottleEnumOptions = new ArrayList(); - FixedWingThrottleEnumOptions.add("Channel1"); - FixedWingThrottleEnumOptions.add("Channel2"); - FixedWingThrottleEnumOptions.add("Channel3"); - FixedWingThrottleEnumOptions.add("Channel4"); - FixedWingThrottleEnumOptions.add("Channel5"); - FixedWingThrottleEnumOptions.add("Channel6"); - FixedWingThrottleEnumOptions.add("Channel7"); - FixedWingThrottleEnumOptions.add("Channel8"); - FixedWingThrottleEnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingThrottle", "channel", UAVObjectField.FieldType.ENUM, FixedWingThrottleElemNames, FixedWingThrottleEnumOptions) ); - - List VTOLMotorNElemNames = new ArrayList(); - VTOLMotorNElemNames.add("0"); - List VTOLMotorNEnumOptions = new ArrayList(); - VTOLMotorNEnumOptions.add("Channel1"); - VTOLMotorNEnumOptions.add("Channel2"); - VTOLMotorNEnumOptions.add("Channel3"); - VTOLMotorNEnumOptions.add("Channel4"); - VTOLMotorNEnumOptions.add("Channel5"); - VTOLMotorNEnumOptions.add("Channel6"); - VTOLMotorNEnumOptions.add("Channel7"); - VTOLMotorNEnumOptions.add("Channel8"); - VTOLMotorNEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorN", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNElemNames, VTOLMotorNEnumOptions) ); - - List VTOLMotorNEElemNames = new ArrayList(); - VTOLMotorNEElemNames.add("0"); - List VTOLMotorNEEnumOptions = new ArrayList(); - VTOLMotorNEEnumOptions.add("Channel1"); - VTOLMotorNEEnumOptions.add("Channel2"); - VTOLMotorNEEnumOptions.add("Channel3"); - VTOLMotorNEEnumOptions.add("Channel4"); - VTOLMotorNEEnumOptions.add("Channel5"); - VTOLMotorNEEnumOptions.add("Channel6"); - VTOLMotorNEEnumOptions.add("Channel7"); - VTOLMotorNEEnumOptions.add("Channel8"); - VTOLMotorNEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorNE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNEElemNames, VTOLMotorNEEnumOptions) ); - - List VTOLMotorEElemNames = new ArrayList(); - VTOLMotorEElemNames.add("0"); - List VTOLMotorEEnumOptions = new ArrayList(); - VTOLMotorEEnumOptions.add("Channel1"); - VTOLMotorEEnumOptions.add("Channel2"); - VTOLMotorEEnumOptions.add("Channel3"); - VTOLMotorEEnumOptions.add("Channel4"); - VTOLMotorEEnumOptions.add("Channel5"); - VTOLMotorEEnumOptions.add("Channel6"); - VTOLMotorEEnumOptions.add("Channel7"); - VTOLMotorEEnumOptions.add("Channel8"); - VTOLMotorEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorEElemNames, VTOLMotorEEnumOptions) ); - - List VTOLMotorSEElemNames = new ArrayList(); - VTOLMotorSEElemNames.add("0"); - List VTOLMotorSEEnumOptions = new ArrayList(); - VTOLMotorSEEnumOptions.add("Channel1"); - VTOLMotorSEEnumOptions.add("Channel2"); - VTOLMotorSEEnumOptions.add("Channel3"); - VTOLMotorSEEnumOptions.add("Channel4"); - VTOLMotorSEEnumOptions.add("Channel5"); - VTOLMotorSEEnumOptions.add("Channel6"); - VTOLMotorSEEnumOptions.add("Channel7"); - VTOLMotorSEEnumOptions.add("Channel8"); - VTOLMotorSEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorSE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSEElemNames, VTOLMotorSEEnumOptions) ); - - List VTOLMotorSElemNames = new ArrayList(); - VTOLMotorSElemNames.add("0"); - List VTOLMotorSEnumOptions = new ArrayList(); - VTOLMotorSEnumOptions.add("Channel1"); - VTOLMotorSEnumOptions.add("Channel2"); - VTOLMotorSEnumOptions.add("Channel3"); - VTOLMotorSEnumOptions.add("Channel4"); - VTOLMotorSEnumOptions.add("Channel5"); - VTOLMotorSEnumOptions.add("Channel6"); - VTOLMotorSEnumOptions.add("Channel7"); - VTOLMotorSEnumOptions.add("Channel8"); - VTOLMotorSEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorS", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSElemNames, VTOLMotorSEnumOptions) ); - - List VTOLMotorSWElemNames = new ArrayList(); - VTOLMotorSWElemNames.add("0"); - List VTOLMotorSWEnumOptions = new ArrayList(); - VTOLMotorSWEnumOptions.add("Channel1"); - VTOLMotorSWEnumOptions.add("Channel2"); - VTOLMotorSWEnumOptions.add("Channel3"); - VTOLMotorSWEnumOptions.add("Channel4"); - VTOLMotorSWEnumOptions.add("Channel5"); - VTOLMotorSWEnumOptions.add("Channel6"); - VTOLMotorSWEnumOptions.add("Channel7"); - VTOLMotorSWEnumOptions.add("Channel8"); - VTOLMotorSWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorSW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSWElemNames, VTOLMotorSWEnumOptions) ); - - List VTOLMotorWElemNames = new ArrayList(); - VTOLMotorWElemNames.add("0"); - List VTOLMotorWEnumOptions = new ArrayList(); - VTOLMotorWEnumOptions.add("Channel1"); - VTOLMotorWEnumOptions.add("Channel2"); - VTOLMotorWEnumOptions.add("Channel3"); - VTOLMotorWEnumOptions.add("Channel4"); - VTOLMotorWEnumOptions.add("Channel5"); - VTOLMotorWEnumOptions.add("Channel6"); - VTOLMotorWEnumOptions.add("Channel7"); - VTOLMotorWEnumOptions.add("Channel8"); - VTOLMotorWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorWElemNames, VTOLMotorWEnumOptions) ); - - List VTOLMotorNWElemNames = new ArrayList(); - VTOLMotorNWElemNames.add("0"); - List VTOLMotorNWEnumOptions = new ArrayList(); - VTOLMotorNWEnumOptions.add("Channel1"); - VTOLMotorNWEnumOptions.add("Channel2"); - VTOLMotorNWEnumOptions.add("Channel3"); - VTOLMotorNWEnumOptions.add("Channel4"); - VTOLMotorNWEnumOptions.add("Channel5"); - VTOLMotorNWEnumOptions.add("Channel6"); - VTOLMotorNWEnumOptions.add("Channel7"); - VTOLMotorNWEnumOptions.add("Channel8"); - VTOLMotorNWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorNW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNWElemNames, VTOLMotorNWEnumOptions) ); - List ChannelUpdateFreqElemNames = new ArrayList(); ChannelUpdateFreqElemNames.add("0"); ChannelUpdateFreqElemNames.add("1"); @@ -263,6 +67,8 @@ public class ActuatorSettings extends UAVDataObject { ChannelMaxElemNames.add("5"); ChannelMaxElemNames.add("6"); ChannelMaxElemNames.add("7"); + ChannelMaxElemNames.add("8"); + ChannelMaxElemNames.add("9"); fields.add( new UAVObjectField("ChannelMax", "us", UAVObjectField.FieldType.INT16, ChannelMaxElemNames, null) ); List ChannelNeutralElemNames = new ArrayList(); @@ -274,6 +80,8 @@ public class ActuatorSettings extends UAVDataObject { ChannelNeutralElemNames.add("5"); ChannelNeutralElemNames.add("6"); ChannelNeutralElemNames.add("7"); + ChannelNeutralElemNames.add("8"); + ChannelNeutralElemNames.add("9"); fields.add( new UAVObjectField("ChannelNeutral", "us", UAVObjectField.FieldType.INT16, ChannelNeutralElemNames, null) ); List ChannelMinElemNames = new ArrayList(); @@ -285,8 +93,250 @@ public class ActuatorSettings extends UAVDataObject { ChannelMinElemNames.add("5"); ChannelMinElemNames.add("6"); ChannelMinElemNames.add("7"); + ChannelMinElemNames.add("8"); + ChannelMinElemNames.add("9"); fields.add( new UAVObjectField("ChannelMin", "us", UAVObjectField.FieldType.INT16, ChannelMinElemNames, null) ); + List FixedWingRoll1ElemNames = new ArrayList(); + FixedWingRoll1ElemNames.add("0"); + List FixedWingRoll1EnumOptions = new ArrayList(); + FixedWingRoll1EnumOptions.add("Channel1"); + FixedWingRoll1EnumOptions.add("Channel2"); + FixedWingRoll1EnumOptions.add("Channel3"); + FixedWingRoll1EnumOptions.add("Channel4"); + FixedWingRoll1EnumOptions.add("Channel5"); + FixedWingRoll1EnumOptions.add("Channel6"); + FixedWingRoll1EnumOptions.add("Channel7"); + FixedWingRoll1EnumOptions.add("Channel8"); + FixedWingRoll1EnumOptions.add("Channel9"); + FixedWingRoll1EnumOptions.add("Channel10"); + FixedWingRoll1EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingRoll1", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll1ElemNames, FixedWingRoll1EnumOptions) ); + + List FixedWingRoll2ElemNames = new ArrayList(); + FixedWingRoll2ElemNames.add("0"); + List FixedWingRoll2EnumOptions = new ArrayList(); + FixedWingRoll2EnumOptions.add("Channel1"); + FixedWingRoll2EnumOptions.add("Channel2"); + FixedWingRoll2EnumOptions.add("Channel3"); + FixedWingRoll2EnumOptions.add("Channel4"); + FixedWingRoll2EnumOptions.add("Channel5"); + FixedWingRoll2EnumOptions.add("Channel6"); + FixedWingRoll2EnumOptions.add("Channel7"); + FixedWingRoll2EnumOptions.add("Channel8"); + FixedWingRoll2EnumOptions.add("Channel9"); + FixedWingRoll2EnumOptions.add("Channel10"); + FixedWingRoll2EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingRoll2", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll2ElemNames, FixedWingRoll2EnumOptions) ); + + List FixedWingPitch1ElemNames = new ArrayList(); + FixedWingPitch1ElemNames.add("0"); + List FixedWingPitch1EnumOptions = new ArrayList(); + FixedWingPitch1EnumOptions.add("Channel1"); + FixedWingPitch1EnumOptions.add("Channel2"); + FixedWingPitch1EnumOptions.add("Channel3"); + FixedWingPitch1EnumOptions.add("Channel4"); + FixedWingPitch1EnumOptions.add("Channel5"); + FixedWingPitch1EnumOptions.add("Channel6"); + FixedWingPitch1EnumOptions.add("Channel7"); + FixedWingPitch1EnumOptions.add("Channel8"); + FixedWingPitch1EnumOptions.add("Channel9"); + FixedWingPitch1EnumOptions.add("Channel10"); + FixedWingPitch1EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingPitch1", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch1ElemNames, FixedWingPitch1EnumOptions) ); + + List FixedWingPitch2ElemNames = new ArrayList(); + FixedWingPitch2ElemNames.add("0"); + List FixedWingPitch2EnumOptions = new ArrayList(); + FixedWingPitch2EnumOptions.add("Channel1"); + FixedWingPitch2EnumOptions.add("Channel2"); + FixedWingPitch2EnumOptions.add("Channel3"); + FixedWingPitch2EnumOptions.add("Channel4"); + FixedWingPitch2EnumOptions.add("Channel5"); + FixedWingPitch2EnumOptions.add("Channel6"); + FixedWingPitch2EnumOptions.add("Channel7"); + FixedWingPitch2EnumOptions.add("Channel8"); + FixedWingPitch2EnumOptions.add("Channel9"); + FixedWingPitch2EnumOptions.add("Channel10"); + FixedWingPitch2EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingPitch2", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch2ElemNames, FixedWingPitch2EnumOptions) ); + + List FixedWingYaw1ElemNames = new ArrayList(); + FixedWingYaw1ElemNames.add("0"); + List FixedWingYaw1EnumOptions = new ArrayList(); + FixedWingYaw1EnumOptions.add("Channel1"); + FixedWingYaw1EnumOptions.add("Channel2"); + FixedWingYaw1EnumOptions.add("Channel3"); + FixedWingYaw1EnumOptions.add("Channel4"); + FixedWingYaw1EnumOptions.add("Channel5"); + FixedWingYaw1EnumOptions.add("Channel6"); + FixedWingYaw1EnumOptions.add("Channel7"); + FixedWingYaw1EnumOptions.add("Channel8"); + FixedWingYaw1EnumOptions.add("Channel9"); + FixedWingYaw1EnumOptions.add("Channel10"); + FixedWingYaw1EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingYaw1", "channel", UAVObjectField.FieldType.ENUM, FixedWingYaw1ElemNames, FixedWingYaw1EnumOptions) ); + + List FixedWingYaw2ElemNames = new ArrayList(); + FixedWingYaw2ElemNames.add("0"); + List FixedWingYaw2EnumOptions = new ArrayList(); + FixedWingYaw2EnumOptions.add("Channel1"); + FixedWingYaw2EnumOptions.add("Channel2"); + FixedWingYaw2EnumOptions.add("Channel3"); + FixedWingYaw2EnumOptions.add("Channel4"); + FixedWingYaw2EnumOptions.add("Channel5"); + FixedWingYaw2EnumOptions.add("Channel6"); + FixedWingYaw2EnumOptions.add("Channel7"); + FixedWingYaw2EnumOptions.add("Channel8"); + FixedWingYaw2EnumOptions.add("Channel9"); + FixedWingYaw2EnumOptions.add("Channel10"); + FixedWingYaw2EnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingYaw2", "channel", UAVObjectField.FieldType.ENUM, FixedWingYaw2ElemNames, FixedWingYaw2EnumOptions) ); + + List FixedWingThrottleElemNames = new ArrayList(); + FixedWingThrottleElemNames.add("0"); + List FixedWingThrottleEnumOptions = new ArrayList(); + FixedWingThrottleEnumOptions.add("Channel1"); + FixedWingThrottleEnumOptions.add("Channel2"); + FixedWingThrottleEnumOptions.add("Channel3"); + FixedWingThrottleEnumOptions.add("Channel4"); + FixedWingThrottleEnumOptions.add("Channel5"); + FixedWingThrottleEnumOptions.add("Channel6"); + FixedWingThrottleEnumOptions.add("Channel7"); + FixedWingThrottleEnumOptions.add("Channel8"); + FixedWingThrottleEnumOptions.add("Channel9"); + FixedWingThrottleEnumOptions.add("Channel10"); + FixedWingThrottleEnumOptions.add("None"); + fields.add( new UAVObjectField("FixedWingThrottle", "channel", UAVObjectField.FieldType.ENUM, FixedWingThrottleElemNames, FixedWingThrottleEnumOptions) ); + + List VTOLMotorNElemNames = new ArrayList(); + VTOLMotorNElemNames.add("0"); + List VTOLMotorNEnumOptions = new ArrayList(); + VTOLMotorNEnumOptions.add("Channel1"); + VTOLMotorNEnumOptions.add("Channel2"); + VTOLMotorNEnumOptions.add("Channel3"); + VTOLMotorNEnumOptions.add("Channel4"); + VTOLMotorNEnumOptions.add("Channel5"); + VTOLMotorNEnumOptions.add("Channel6"); + VTOLMotorNEnumOptions.add("Channel7"); + VTOLMotorNEnumOptions.add("Channel8"); + VTOLMotorNEnumOptions.add("Channel9"); + VTOLMotorNEnumOptions.add("Channel10"); + VTOLMotorNEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorN", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNElemNames, VTOLMotorNEnumOptions) ); + + List VTOLMotorNEElemNames = new ArrayList(); + VTOLMotorNEElemNames.add("0"); + List VTOLMotorNEEnumOptions = new ArrayList(); + VTOLMotorNEEnumOptions.add("Channel1"); + VTOLMotorNEEnumOptions.add("Channel2"); + VTOLMotorNEEnumOptions.add("Channel3"); + VTOLMotorNEEnumOptions.add("Channel4"); + VTOLMotorNEEnumOptions.add("Channel5"); + VTOLMotorNEEnumOptions.add("Channel6"); + VTOLMotorNEEnumOptions.add("Channel7"); + VTOLMotorNEEnumOptions.add("Channel8"); + VTOLMotorNEEnumOptions.add("Channel9"); + VTOLMotorNEEnumOptions.add("Channel10"); + VTOLMotorNEEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorNE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNEElemNames, VTOLMotorNEEnumOptions) ); + + List VTOLMotorEElemNames = new ArrayList(); + VTOLMotorEElemNames.add("0"); + List VTOLMotorEEnumOptions = new ArrayList(); + VTOLMotorEEnumOptions.add("Channel1"); + VTOLMotorEEnumOptions.add("Channel2"); + VTOLMotorEEnumOptions.add("Channel3"); + VTOLMotorEEnumOptions.add("Channel4"); + VTOLMotorEEnumOptions.add("Channel5"); + VTOLMotorEEnumOptions.add("Channel6"); + VTOLMotorEEnumOptions.add("Channel7"); + VTOLMotorEEnumOptions.add("Channel8"); + VTOLMotorEEnumOptions.add("Channel9"); + VTOLMotorEEnumOptions.add("Channel10"); + VTOLMotorEEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorEElemNames, VTOLMotorEEnumOptions) ); + + List VTOLMotorSEElemNames = new ArrayList(); + VTOLMotorSEElemNames.add("0"); + List VTOLMotorSEEnumOptions = new ArrayList(); + VTOLMotorSEEnumOptions.add("Channel1"); + VTOLMotorSEEnumOptions.add("Channel2"); + VTOLMotorSEEnumOptions.add("Channel3"); + VTOLMotorSEEnumOptions.add("Channel4"); + VTOLMotorSEEnumOptions.add("Channel5"); + VTOLMotorSEEnumOptions.add("Channel6"); + VTOLMotorSEEnumOptions.add("Channel7"); + VTOLMotorSEEnumOptions.add("Channel8"); + VTOLMotorSEEnumOptions.add("Channel9"); + VTOLMotorSEEnumOptions.add("Channel10"); + VTOLMotorSEEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorSE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSEElemNames, VTOLMotorSEEnumOptions) ); + + List VTOLMotorSElemNames = new ArrayList(); + VTOLMotorSElemNames.add("0"); + List VTOLMotorSEnumOptions = new ArrayList(); + VTOLMotorSEnumOptions.add("Channel1"); + VTOLMotorSEnumOptions.add("Channel2"); + VTOLMotorSEnumOptions.add("Channel3"); + VTOLMotorSEnumOptions.add("Channel4"); + VTOLMotorSEnumOptions.add("Channel5"); + VTOLMotorSEnumOptions.add("Channel6"); + VTOLMotorSEnumOptions.add("Channel7"); + VTOLMotorSEnumOptions.add("Channel8"); + VTOLMotorSEnumOptions.add("Channel9"); + VTOLMotorSEnumOptions.add("Channel10"); + VTOLMotorSEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorS", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSElemNames, VTOLMotorSEnumOptions) ); + + List VTOLMotorSWElemNames = new ArrayList(); + VTOLMotorSWElemNames.add("0"); + List VTOLMotorSWEnumOptions = new ArrayList(); + VTOLMotorSWEnumOptions.add("Channel1"); + VTOLMotorSWEnumOptions.add("Channel2"); + VTOLMotorSWEnumOptions.add("Channel3"); + VTOLMotorSWEnumOptions.add("Channel4"); + VTOLMotorSWEnumOptions.add("Channel5"); + VTOLMotorSWEnumOptions.add("Channel6"); + VTOLMotorSWEnumOptions.add("Channel7"); + VTOLMotorSWEnumOptions.add("Channel8"); + VTOLMotorSWEnumOptions.add("Channel9"); + VTOLMotorSWEnumOptions.add("Channel10"); + VTOLMotorSWEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorSW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSWElemNames, VTOLMotorSWEnumOptions) ); + + List VTOLMotorWElemNames = new ArrayList(); + VTOLMotorWElemNames.add("0"); + List VTOLMotorWEnumOptions = new ArrayList(); + VTOLMotorWEnumOptions.add("Channel1"); + VTOLMotorWEnumOptions.add("Channel2"); + VTOLMotorWEnumOptions.add("Channel3"); + VTOLMotorWEnumOptions.add("Channel4"); + VTOLMotorWEnumOptions.add("Channel5"); + VTOLMotorWEnumOptions.add("Channel6"); + VTOLMotorWEnumOptions.add("Channel7"); + VTOLMotorWEnumOptions.add("Channel8"); + VTOLMotorWEnumOptions.add("Channel9"); + VTOLMotorWEnumOptions.add("Channel10"); + VTOLMotorWEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorWElemNames, VTOLMotorWEnumOptions) ); + + List VTOLMotorNWElemNames = new ArrayList(); + VTOLMotorNWElemNames.add("0"); + List VTOLMotorNWEnumOptions = new ArrayList(); + VTOLMotorNWEnumOptions.add("Channel1"); + VTOLMotorNWEnumOptions.add("Channel2"); + VTOLMotorNWEnumOptions.add("Channel3"); + VTOLMotorNWEnumOptions.add("Channel4"); + VTOLMotorNWEnumOptions.add("Channel5"); + VTOLMotorNWEnumOptions.add("Channel6"); + VTOLMotorNWEnumOptions.add("Channel7"); + VTOLMotorNWEnumOptions.add("Channel8"); + VTOLMotorNWEnumOptions.add("Channel9"); + VTOLMotorNWEnumOptions.add("Channel10"); + VTOLMotorNWEnumOptions.add("None"); + fields.add( new UAVObjectField("VTOLMotorNW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNWElemNames, VTOLMotorNWEnumOptions) ); + List ChannelTypeElemNames = new ArrayList(); ChannelTypeElemNames.add("0"); ChannelTypeElemNames.add("1"); @@ -296,10 +346,13 @@ public class ActuatorSettings extends UAVDataObject { ChannelTypeElemNames.add("5"); ChannelTypeElemNames.add("6"); ChannelTypeElemNames.add("7"); + ChannelTypeElemNames.add("8"); + ChannelTypeElemNames.add("9"); List ChannelTypeEnumOptions = new ArrayList(); ChannelTypeEnumOptions.add("PWM"); ChannelTypeEnumOptions.add("MK"); ChannelTypeEnumOptions.add("ASTEC4"); + ChannelTypeEnumOptions.add("PWM Alarm Buzzer"); fields.add( new UAVObjectField("ChannelType", "", UAVObjectField.FieldType.ENUM, ChannelTypeElemNames, ChannelTypeEnumOptions) ); List ChannelAddrElemNames = new ArrayList(); @@ -311,8 +364,17 @@ public class ActuatorSettings extends UAVDataObject { ChannelAddrElemNames.add("5"); ChannelAddrElemNames.add("6"); ChannelAddrElemNames.add("7"); + ChannelAddrElemNames.add("8"); + ChannelAddrElemNames.add("9"); fields.add( new UAVObjectField("ChannelAddr", "", UAVObjectField.FieldType.UINT8, ChannelAddrElemNames, null) ); + List MotorsSpinWhileArmedElemNames = new ArrayList(); + MotorsSpinWhileArmedElemNames.add("0"); + List MotorsSpinWhileArmedEnumOptions = new ArrayList(); + MotorsSpinWhileArmedEnumOptions.add("FALSE"); + MotorsSpinWhileArmedEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("MotorsSpinWhileArmed", "", UAVObjectField.FieldType.ENUM, MotorsSpinWhileArmedElemNames, MotorsSpinWhileArmedEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -358,20 +420,6 @@ public class ActuatorSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("FixedWingRoll1").setValue("None"); - getField("FixedWingRoll2").setValue("None"); - getField("FixedWingPitch1").setValue("None"); - getField("FixedWingPitch2").setValue("None"); - getField("FixedWingYaw").setValue("None"); - getField("FixedWingThrottle").setValue("None"); - getField("VTOLMotorN").setValue("None"); - getField("VTOLMotorNE").setValue("None"); - getField("VTOLMotorE").setValue("None"); - getField("VTOLMotorSE").setValue("None"); - getField("VTOLMotorS").setValue("None"); - getField("VTOLMotorSW").setValue("None"); - getField("VTOLMotorW").setValue("None"); - getField("VTOLMotorNW").setValue("None"); getField("ChannelUpdateFreq").setValue(50,0); getField("ChannelUpdateFreq").setValue(50,1); getField("ChannelUpdateFreq").setValue(50,2); @@ -384,6 +432,8 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelMax").setValue(1000,5); getField("ChannelMax").setValue(1000,6); getField("ChannelMax").setValue(1000,7); + getField("ChannelMax").setValue(1000,8); + getField("ChannelMax").setValue(1000,9); getField("ChannelNeutral").setValue(1000,0); getField("ChannelNeutral").setValue(1000,1); getField("ChannelNeutral").setValue(1000,2); @@ -392,6 +442,8 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelNeutral").setValue(1000,5); getField("ChannelNeutral").setValue(1000,6); getField("ChannelNeutral").setValue(1000,7); + getField("ChannelNeutral").setValue(1000,8); + getField("ChannelNeutral").setValue(1000,9); getField("ChannelMin").setValue(1000,0); getField("ChannelMin").setValue(1000,1); getField("ChannelMin").setValue(1000,2); @@ -400,6 +452,23 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelMin").setValue(1000,5); getField("ChannelMin").setValue(1000,6); getField("ChannelMin").setValue(1000,7); + getField("ChannelMin").setValue(1000,8); + getField("ChannelMin").setValue(1000,9); + getField("FixedWingRoll1").setValue("None"); + getField("FixedWingRoll2").setValue("None"); + getField("FixedWingPitch1").setValue("None"); + getField("FixedWingPitch2").setValue("None"); + getField("FixedWingYaw1").setValue("None"); + getField("FixedWingYaw2").setValue("None"); + getField("FixedWingThrottle").setValue("None"); + getField("VTOLMotorN").setValue("None"); + getField("VTOLMotorNE").setValue("None"); + getField("VTOLMotorE").setValue("None"); + getField("VTOLMotorSE").setValue("None"); + getField("VTOLMotorS").setValue("None"); + getField("VTOLMotorSW").setValue("None"); + getField("VTOLMotorW").setValue("None"); + getField("VTOLMotorNW").setValue("None"); getField("ChannelType").setValue("PWM",0); getField("ChannelType").setValue("PWM",1); getField("ChannelType").setValue("PWM",2); @@ -408,6 +477,8 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelType").setValue("PWM",5); getField("ChannelType").setValue("PWM",6); getField("ChannelType").setValue("PWM",7); + getField("ChannelType").setValue("PWM",8); + getField("ChannelType").setValue("PWM",9); getField("ChannelAddr").setValue(0,0); getField("ChannelAddr").setValue(1,1); getField("ChannelAddr").setValue(2,2); @@ -416,6 +487,9 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelAddr").setValue(5,5); getField("ChannelAddr").setValue(6,6); getField("ChannelAddr").setValue(7,7); + getField("ChannelAddr").setValue(8,8); + getField("ChannelAddr").setValue(9,9); + getField("MotorsSpinWhileArmed").setValue("FALSE"); } @@ -444,7 +518,7 @@ public class ActuatorSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x1BF864C2; + protected static final int OBJID = 0xF2875746; protected static final String NAME = "ActuatorSettings"; protected static String DESCRIPTION = "Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java index 3ee8304ae..82e447a70 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java @@ -51,6 +51,10 @@ public class AhrsStatus extends UAVDataObject { List fields = new ArrayList(); + List RunningTimeElemNames = new ArrayList(); + RunningTimeElemNames.add("0"); + fields.add( new UAVObjectField("RunningTime", "ms", UAVObjectField.FieldType.UINT32, RunningTimeElemNames, null) ); + List SerialNumberElemNames = new ArrayList(); SerialNumberElemNames.add("0"); SerialNumberElemNames.add("1"); @@ -66,10 +70,6 @@ public class AhrsStatus extends UAVDataObject { CPULoadElemNames.add("0"); fields.add( new UAVObjectField("CPULoad", "count", UAVObjectField.FieldType.UINT8, CPULoadElemNames, null) ); - List RunningTimeElemNames = new ArrayList(); - RunningTimeElemNames.add("0"); - fields.add( new UAVObjectField("RunningTime", "ms", UAVObjectField.FieldType.UINT32, RunningTimeElemNames, null) ); - List IdleTimePerCyleElemNames = new ArrayList(); IdleTimePerCyleElemNames.add("0"); fields.add( new UAVObjectField("IdleTimePerCyle", "10x ms", UAVObjectField.FieldType.UINT8, IdleTimePerCyleElemNames, null) ); @@ -190,7 +190,7 @@ public class AhrsStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0x37A5F7A2; + protected static final int OBJID = 0x706D1AB8; protected static final String NAME = "AhrsStatus"; protected static String DESCRIPTION = "Status for the @ref AHRSCommsModule, including communication errors"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java index 714c18571..7c9272cad 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java @@ -110,7 +110,7 @@ public class AttitudeActual extends UAVDataObject { metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 500; + metadata.flightTelemetryUpdatePeriod = 100; metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; metadata.loggingUpdatePeriod = 0; @@ -152,7 +152,7 @@ public class AttitudeActual extends UAVDataObject { } // Constants - protected static final int OBJID = 0xFC5B8CF4; + protected static final int OBJID = 0x33DAD5E6; protected static final String NAME = "AttitudeActual"; protected static String DESCRIPTION = "The updated Attitude estimation from @ref AHRSCommsModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java index d28302b6a..b8c3aacb4 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java @@ -51,29 +51,29 @@ public class AttitudeRaw extends UAVDataObject { List fields = new ArrayList(); - List magnetometersElemNames = new ArrayList(); - magnetometersElemNames.add("X"); - magnetometersElemNames.add("Y"); - magnetometersElemNames.add("Z"); - fields.add( new UAVObjectField("magnetometers", "mGa", UAVObjectField.FieldType.INT16, magnetometersElemNames, null) ); - List gyrosElemNames = new ArrayList(); gyrosElemNames.add("X"); gyrosElemNames.add("Y"); gyrosElemNames.add("Z"); fields.add( new UAVObjectField("gyros", "deg/s", UAVObjectField.FieldType.FLOAT32, gyrosElemNames, null) ); - List gyrotempElemNames = new ArrayList(); - gyrotempElemNames.add("XY"); - gyrotempElemNames.add("Z"); - fields.add( new UAVObjectField("gyrotemp", "raw", UAVObjectField.FieldType.UINT16, gyrotempElemNames, null) ); - List accelsElemNames = new ArrayList(); accelsElemNames.add("X"); accelsElemNames.add("Y"); accelsElemNames.add("Z"); fields.add( new UAVObjectField("accels", "m/s^2", UAVObjectField.FieldType.FLOAT32, accelsElemNames, null) ); + List magnetometersElemNames = new ArrayList(); + magnetometersElemNames.add("X"); + magnetometersElemNames.add("Y"); + magnetometersElemNames.add("Z"); + fields.add( new UAVObjectField("magnetometers", "mGa", UAVObjectField.FieldType.INT16, magnetometersElemNames, null) ); + + List gyrotempElemNames = new ArrayList(); + gyrotempElemNames.add("XY"); + gyrotempElemNames.add("Z"); + fields.add( new UAVObjectField("gyrotemp", "raw", UAVObjectField.FieldType.UINT16, gyrotempElemNames, null) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -147,7 +147,7 @@ public class AttitudeRaw extends UAVDataObject { } // Constants - protected static final int OBJID = 0x37747DE6; + protected static final int OBJID = 0xDB722974; protected static final String NAME = "AttitudeRaw"; protected static String DESCRIPTION = "The raw attitude sensor data from @ref AHRSCommsModule. Not always updated."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java index 482fc12ce..3034a99ad 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java @@ -51,12 +51,6 @@ public class AttitudeSettings extends UAVDataObject { List fields = new ArrayList(); - List AccelBiasElemNames = new ArrayList(); - AccelBiasElemNames.add("X"); - AccelBiasElemNames.add("Y"); - AccelBiasElemNames.add("Z"); - fields.add( new UAVObjectField("AccelBias", "lsb", UAVObjectField.FieldType.INT16, AccelBiasElemNames, null) ); - List GyroGainElemNames = new ArrayList(); GyroGainElemNames.add("0"); fields.add( new UAVObjectField("GyroGain", "(rad/s)/lsb", UAVObjectField.FieldType.FLOAT32, GyroGainElemNames, null) ); @@ -69,6 +63,50 @@ public class AttitudeSettings extends UAVDataObject { AccelKiElemNames.add("0"); fields.add( new UAVObjectField("AccelKi", "channel", UAVObjectField.FieldType.FLOAT32, AccelKiElemNames, null) ); + List YawBiasRateElemNames = new ArrayList(); + YawBiasRateElemNames.add("0"); + fields.add( new UAVObjectField("YawBiasRate", "channel", UAVObjectField.FieldType.FLOAT32, YawBiasRateElemNames, null) ); + + List AccelBiasElemNames = new ArrayList(); + AccelBiasElemNames.add("X"); + AccelBiasElemNames.add("Y"); + AccelBiasElemNames.add("Z"); + fields.add( new UAVObjectField("AccelBias", "lsb", UAVObjectField.FieldType.INT16, AccelBiasElemNames, null) ); + + List GyroBiasElemNames = new ArrayList(); + GyroBiasElemNames.add("X"); + GyroBiasElemNames.add("Y"); + GyroBiasElemNames.add("Z"); + fields.add( new UAVObjectField("GyroBias", "deg/s * 100", UAVObjectField.FieldType.INT16, GyroBiasElemNames, null) ); + + List BoardRotationElemNames = new ArrayList(); + BoardRotationElemNames.add("Roll"); + BoardRotationElemNames.add("Pitch"); + BoardRotationElemNames.add("Yaw"); + fields.add( new UAVObjectField("BoardRotation", "deg", UAVObjectField.FieldType.INT16, BoardRotationElemNames, null) ); + + List ZeroDuringArmingElemNames = new ArrayList(); + ZeroDuringArmingElemNames.add("0"); + List ZeroDuringArmingEnumOptions = new ArrayList(); + ZeroDuringArmingEnumOptions.add("FALSE"); + ZeroDuringArmingEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("ZeroDuringArming", "channel", UAVObjectField.FieldType.ENUM, ZeroDuringArmingElemNames, ZeroDuringArmingEnumOptions) ); + + List BiasCorrectGyroElemNames = new ArrayList(); + BiasCorrectGyroElemNames.add("0"); + List BiasCorrectGyroEnumOptions = new ArrayList(); + BiasCorrectGyroEnumOptions.add("FALSE"); + BiasCorrectGyroEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("BiasCorrectGyro", "channel", UAVObjectField.FieldType.ENUM, BiasCorrectGyroElemNames, BiasCorrectGyroEnumOptions) ); + + List TrimFlightElemNames = new ArrayList(); + TrimFlightElemNames.add("0"); + List TrimFlightEnumOptions = new ArrayList(); + TrimFlightEnumOptions.add("NORMAL"); + TrimFlightEnumOptions.add("START"); + TrimFlightEnumOptions.add("LOAD"); + fields.add( new UAVObjectField("TrimFlight", "channel", UAVObjectField.FieldType.ENUM, TrimFlightElemNames, TrimFlightEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -114,12 +152,22 @@ public class AttitudeSettings extends UAVDataObject { */ public void setDefaultFieldValues() { + getField("GyroGain").setValue(0.42); + getField("AccelKp").setValue(0.05); + getField("AccelKi").setValue(0.0001); + getField("YawBiasRate").setValue(1e-06); getField("AccelBias").setValue(0,0); getField("AccelBias").setValue(0,1); getField("AccelBias").setValue(0,2); - getField("GyroGain").setValue(0.42); - getField("AccelKp").setValue(0.01); - getField("AccelKi").setValue(0.0001); + getField("GyroBias").setValue(0,0); + getField("GyroBias").setValue(0,1); + getField("GyroBias").setValue(0,2); + getField("BoardRotation").setValue(0,0); + getField("BoardRotation").setValue(0,1); + getField("BoardRotation").setValue(0,2); + getField("ZeroDuringArming").setValue("TRUE"); + getField("BiasCorrectGyro").setValue("TRUE"); + getField("TrimFlight").setValue("NORMAL"); } @@ -148,7 +196,7 @@ public class AttitudeSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x327BF29A; + protected static final int OBJID = 0xC307BC4A; protected static final String NAME = "AttitudeSettings"; protected static String DESCRIPTION = "Settings for the @ref Attitude module used on CopterControl"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java index a2c2c7e3d..ecde53985 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java @@ -136,7 +136,7 @@ public class BaroAltitude extends UAVDataObject { } // Constants - protected static final int OBJID = 0xED4424F6; + protected static final int OBJID = 0x99622E6A; protected static final String NAME = "BaroAltitude"; protected static String DESCRIPTION = "The raw data from the barometric sensor with pressure, temperature and altitude estimate."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java new file mode 100644 index 000000000..7a36ec1ea --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java @@ -0,0 +1,147 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Desired camera outputs. Comes from @ref CameraStabilization module. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Desired camera outputs. Comes from @ref CameraStabilization module. + +generated from cameradesired.xml + **/ +public class CameraDesired extends UAVDataObject { + + public CameraDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; + metadata.flightTelemetryUpdatePeriod = 1000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + CameraDesired obj = new CameraDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public CameraDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (CameraDesired)(objMngr.getObject(CameraDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x531F544E; + protected static final String NAME = "CameraDesired"; + protected static String DESCRIPTION = "Desired camera outputs. Comes from @ref CameraStabilization module."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java new file mode 100644 index 000000000..a8e03df32 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java @@ -0,0 +1,205 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref CameraStab mmodule + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref CameraStab mmodule + +generated from camerastabsettings.xml + **/ +public class CameraStabSettings extends UAVDataObject { + + public CameraStabSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List MaxAxisLockRateElemNames = new ArrayList(); + MaxAxisLockRateElemNames.add("0"); + fields.add( new UAVObjectField("MaxAxisLockRate", "deg/s", UAVObjectField.FieldType.FLOAT32, MaxAxisLockRateElemNames, null) ); + + List ResponseTimeElemNames = new ArrayList(); + ResponseTimeElemNames.add("Roll"); + ResponseTimeElemNames.add("Pitch"); + ResponseTimeElemNames.add("Yaw"); + fields.add( new UAVObjectField("ResponseTime", "ms", UAVObjectField.FieldType.UINT16, ResponseTimeElemNames, null) ); + + List InputElemNames = new ArrayList(); + InputElemNames.add("Roll"); + InputElemNames.add("Pitch"); + InputElemNames.add("Yaw"); + List InputEnumOptions = new ArrayList(); + InputEnumOptions.add("Accessory0"); + InputEnumOptions.add("Accessory1"); + InputEnumOptions.add("Accessory2"); + InputEnumOptions.add("Accessory3"); + InputEnumOptions.add("Accessory4"); + InputEnumOptions.add("Accessory5"); + InputEnumOptions.add("None"); + fields.add( new UAVObjectField("Input", "channel", UAVObjectField.FieldType.ENUM, InputElemNames, InputEnumOptions) ); + + List InputRangeElemNames = new ArrayList(); + InputRangeElemNames.add("Roll"); + InputRangeElemNames.add("Pitch"); + InputRangeElemNames.add("Yaw"); + fields.add( new UAVObjectField("InputRange", "deg", UAVObjectField.FieldType.UINT8, InputRangeElemNames, null) ); + + List InputRateElemNames = new ArrayList(); + InputRateElemNames.add("Roll"); + InputRateElemNames.add("Pitch"); + InputRateElemNames.add("Yaw"); + fields.add( new UAVObjectField("InputRate", "deg/s", UAVObjectField.FieldType.UINT8, InputRateElemNames, null) ); + + List StabilizationModeElemNames = new ArrayList(); + StabilizationModeElemNames.add("Roll"); + StabilizationModeElemNames.add("Pitch"); + StabilizationModeElemNames.add("Yaw"); + List StabilizationModeEnumOptions = new ArrayList(); + StabilizationModeEnumOptions.add("Attitude"); + StabilizationModeEnumOptions.add("AxisLock"); + fields.add( new UAVObjectField("StabilizationMode", "", UAVObjectField.FieldType.ENUM, StabilizationModeElemNames, StabilizationModeEnumOptions) ); + + List OutputRangeElemNames = new ArrayList(); + OutputRangeElemNames.add("Roll"); + OutputRangeElemNames.add("Pitch"); + OutputRangeElemNames.add("Yaw"); + fields.add( new UAVObjectField("OutputRange", "deg", UAVObjectField.FieldType.UINT8, OutputRangeElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("MaxAxisLockRate").setValue(1); + getField("ResponseTime").setValue(150,0); + getField("ResponseTime").setValue(150,1); + getField("ResponseTime").setValue(150,2); + getField("Input").setValue("None",0); + getField("Input").setValue("None",1); + getField("Input").setValue("None",2); + getField("InputRange").setValue(20,0); + getField("InputRange").setValue(20,1); + getField("InputRange").setValue(20,2); + getField("InputRate").setValue(50,0); + getField("InputRate").setValue(50,1); + getField("InputRate").setValue(50,2); + getField("StabilizationMode").setValue("Attitude",0); + getField("StabilizationMode").setValue("Attitude",1); + getField("StabilizationMode").setValue("Attitude",2); + getField("OutputRange").setValue(20,0); + getField("OutputRange").setValue(20,1); + getField("OutputRange").setValue(20,2); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + CameraStabSettings obj = new CameraStabSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public CameraStabSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (CameraStabSettings)(objMngr.getObject(CameraStabSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x3B95DDBA; + protected static final String NAME = "CameraStabSettings"; + protected static String DESCRIPTION = "Settings for the @ref CameraStab mmodule"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java similarity index 74% rename from androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java rename to androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java index 675f9b592..b22b8185e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TelemetrySettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java @@ -5,7 +5,7 @@ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief Template for an uavobject in java * This is a autogenerated file!! Do not modify and expect a result. - * Select baud rate of telemetry. Warning - this must match your modem. + * Allows testers to simulate various fault scenarios. * * @see The GNU Public License (GPL) Version 3 * @@ -39,29 +39,28 @@ import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObjectField; /** -Select baud rate of telemetry. Warning - this must match your modem. +Allows testers to simulate various fault scenarios. -generated from telemetrysettings.xml +generated from faultsettings.xml **/ -public class TelemetrySettings extends UAVDataObject { +public class FaultSettings extends UAVDataObject { - public TelemetrySettings() { + public FaultSettings() { super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); List fields = new ArrayList(); - List SpeedElemNames = new ArrayList(); - SpeedElemNames.add("0"); - List SpeedEnumOptions = new ArrayList(); - SpeedEnumOptions.add("2400"); - SpeedEnumOptions.add("4800"); - SpeedEnumOptions.add("9600"); - SpeedEnumOptions.add("19200"); - SpeedEnumOptions.add("38400"); - SpeedEnumOptions.add("57600"); - SpeedEnumOptions.add("115200"); - fields.add( new UAVObjectField("Speed", "", UAVObjectField.FieldType.ENUM, SpeedElemNames, SpeedEnumOptions) ); + List ActivateFaultElemNames = new ArrayList(); + ActivateFaultElemNames.add("0"); + List ActivateFaultEnumOptions = new ArrayList(); + ActivateFaultEnumOptions.add("NoFault"); + ActivateFaultEnumOptions.add("ModuleInitAssert"); + ActivateFaultEnumOptions.add("InitOutOfMemory"); + ActivateFaultEnumOptions.add("InitBusError"); + ActivateFaultEnumOptions.add("RunawayTask"); + ActivateFaultEnumOptions.add("TaskOutOfMemory"); + fields.add( new UAVObjectField("ActivateFault", "fault", UAVObjectField.FieldType.ENUM, ActivateFaultElemNames, ActivateFaultEnumOptions) ); // Compute the number of bytes for this object @@ -108,7 +107,7 @@ public class TelemetrySettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("Speed").setValue("57600"); + getField("ActivateFault").setValue("NoFault"); } @@ -120,7 +119,7 @@ public class TelemetrySettings extends UAVDataObject { public UAVDataObject clone(int instID) { // TODO: Need to get specific instance to clone try { - TelemetrySettings obj = new TelemetrySettings(); + FaultSettings obj = new FaultSettings(); obj.initialize(instID, this.getMetaObject()); return obj; } catch (Exception e) { @@ -131,15 +130,15 @@ public class TelemetrySettings extends UAVDataObject { /** * Static function to retrieve an instance of the object. */ - public TelemetrySettings GetInstance(UAVObjectManager objMngr, int instID) + public FaultSettings GetInstance(UAVObjectManager objMngr, int instID) { - return (TelemetrySettings)(objMngr.getObject(TelemetrySettings.OBJID, instID)); + return (FaultSettings)(objMngr.getObject(FaultSettings.OBJID, instID)); } // Constants - protected static final int OBJID = 0xA608C526; - protected static final String NAME = "TelemetrySettings"; - protected static String DESCRIPTION = "Select baud rate of telemetry. Warning - this must match your modem."; + protected static final int OBJID = 0x2778BA3C; + protected static final String NAME = "FaultSettings"; + protected static String DESCRIPTION = "Allows testers to simulate various fault scenarios."; protected static final boolean ISSINGLEINST = 1 == 1; protected static final boolean ISSETTINGS = 1 == 1; protected static int NUMBYTES = 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java index 493d6cd64..71c681bd2 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java @@ -5,7 +5,7 @@ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief Template for an uavobject in java * This is a autogenerated file!! Do not modify and expect a result. - * Firmware IAP + * Queries board for SN, model, revision, and sends reset command * * @see The GNU Public License (GPL) Version 3 * @@ -39,7 +39,7 @@ import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObjectField; /** -Firmware IAP +Queries board for SN, model, revision, and sends reset command generated from firmwareiapobj.xml **/ @@ -51,10 +51,18 @@ public class FirmwareIAPObj extends UAVDataObject { List fields = new ArrayList(); + List crcElemNames = new ArrayList(); + crcElemNames.add("0"); + fields.add( new UAVObjectField("crc", "", UAVObjectField.FieldType.UINT32, crcElemNames, null) ); + List CommandElemNames = new ArrayList(); CommandElemNames.add("0"); fields.add( new UAVObjectField("Command", "", UAVObjectField.FieldType.UINT16, CommandElemNames, null) ); + List BoardRevisionElemNames = new ArrayList(); + BoardRevisionElemNames.add("0"); + fields.add( new UAVObjectField("BoardRevision", "", UAVObjectField.FieldType.UINT16, BoardRevisionElemNames, null) ); + List DescriptionElemNames = new ArrayList(); DescriptionElemNames.add("0"); DescriptionElemNames.add("1"); @@ -96,71 +104,22 @@ public class FirmwareIAPObj extends UAVDataObject { DescriptionElemNames.add("37"); DescriptionElemNames.add("38"); DescriptionElemNames.add("39"); - DescriptionElemNames.add("40"); - DescriptionElemNames.add("41"); - DescriptionElemNames.add("42"); - DescriptionElemNames.add("43"); - DescriptionElemNames.add("44"); - DescriptionElemNames.add("45"); - DescriptionElemNames.add("46"); - DescriptionElemNames.add("47"); - DescriptionElemNames.add("48"); - DescriptionElemNames.add("49"); - DescriptionElemNames.add("50"); - DescriptionElemNames.add("51"); - DescriptionElemNames.add("52"); - DescriptionElemNames.add("53"); - DescriptionElemNames.add("54"); - DescriptionElemNames.add("55"); - DescriptionElemNames.add("56"); - DescriptionElemNames.add("57"); - DescriptionElemNames.add("58"); - DescriptionElemNames.add("59"); - DescriptionElemNames.add("60"); - DescriptionElemNames.add("61"); - DescriptionElemNames.add("62"); - DescriptionElemNames.add("63"); - DescriptionElemNames.add("64"); - DescriptionElemNames.add("65"); - DescriptionElemNames.add("66"); - DescriptionElemNames.add("67"); - DescriptionElemNames.add("68"); - DescriptionElemNames.add("69"); - DescriptionElemNames.add("70"); - DescriptionElemNames.add("71"); - DescriptionElemNames.add("72"); - DescriptionElemNames.add("73"); - DescriptionElemNames.add("74"); - DescriptionElemNames.add("75"); - DescriptionElemNames.add("76"); - DescriptionElemNames.add("77"); - DescriptionElemNames.add("78"); - DescriptionElemNames.add("79"); - DescriptionElemNames.add("80"); - DescriptionElemNames.add("81"); - DescriptionElemNames.add("82"); - DescriptionElemNames.add("83"); - DescriptionElemNames.add("84"); - DescriptionElemNames.add("85"); - DescriptionElemNames.add("86"); - DescriptionElemNames.add("87"); - DescriptionElemNames.add("88"); - DescriptionElemNames.add("89"); - DescriptionElemNames.add("90"); - DescriptionElemNames.add("91"); - DescriptionElemNames.add("92"); - DescriptionElemNames.add("93"); - DescriptionElemNames.add("94"); - DescriptionElemNames.add("95"); - DescriptionElemNames.add("96"); - DescriptionElemNames.add("97"); - DescriptionElemNames.add("98"); - DescriptionElemNames.add("99"); fields.add( new UAVObjectField("Description", "", UAVObjectField.FieldType.UINT8, DescriptionElemNames, null) ); - List BoardRevisionElemNames = new ArrayList(); - BoardRevisionElemNames.add("0"); - fields.add( new UAVObjectField("BoardRevision", "", UAVObjectField.FieldType.UINT16, BoardRevisionElemNames, null) ); + List CPUSerialElemNames = new ArrayList(); + CPUSerialElemNames.add("0"); + CPUSerialElemNames.add("1"); + CPUSerialElemNames.add("2"); + CPUSerialElemNames.add("3"); + CPUSerialElemNames.add("4"); + CPUSerialElemNames.add("5"); + CPUSerialElemNames.add("6"); + CPUSerialElemNames.add("7"); + CPUSerialElemNames.add("8"); + CPUSerialElemNames.add("9"); + CPUSerialElemNames.add("10"); + CPUSerialElemNames.add("11"); + fields.add( new UAVObjectField("CPUSerial", "", UAVObjectField.FieldType.UINT8, CPUSerialElemNames, null) ); List BoardTypeElemNames = new ArrayList(); BoardTypeElemNames.add("0"); @@ -170,10 +129,6 @@ public class FirmwareIAPObj extends UAVDataObject { ArmResetElemNames.add("0"); fields.add( new UAVObjectField("ArmReset", "", UAVObjectField.FieldType.UINT8, ArmResetElemNames, null) ); - List crcElemNames = new ArrayList(); - crcElemNames.add("0"); - fields.add( new UAVObjectField("crc", "", UAVObjectField.FieldType.UINT32, crcElemNames, null) ); - // Compute the number of bytes for this object int numBytes = 0; @@ -247,9 +202,9 @@ public class FirmwareIAPObj extends UAVDataObject { } // Constants - protected static final int OBJID = 0x1A8ECC2; + protected static final int OBJID = 0x3CCDFB68; protected static final String NAME = "FirmwareIAPObj"; - protected static String DESCRIPTION = "Firmware IAP"; + protected static String DESCRIPTION = "Queries board for SN, model, revision, and sends reset command"; protected static final boolean ISSINGLEINST = 1 == 1; protected static final boolean ISSETTINGS = 0 == 1; protected static int NUMBYTES = 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java new file mode 100644 index 000000000..a3bc23eb3 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java @@ -0,0 +1,177 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Flight Battery configuration. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Flight Battery configuration. + +generated from flightbatterysettings.xml + **/ +public class FlightBatterySettings extends UAVDataObject { + + public FlightBatterySettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List CapacityElemNames = new ArrayList(); + CapacityElemNames.add("0"); + fields.add( new UAVObjectField("Capacity", "mAh", UAVObjectField.FieldType.UINT32, CapacityElemNames, null) ); + + List VoltageThresholdsElemNames = new ArrayList(); + VoltageThresholdsElemNames.add("Warning"); + VoltageThresholdsElemNames.add("Alarm"); + fields.add( new UAVObjectField("VoltageThresholds", "V", UAVObjectField.FieldType.FLOAT32, VoltageThresholdsElemNames, null) ); + + List SensorCalibrationsElemNames = new ArrayList(); + SensorCalibrationsElemNames.add("VoltageFactor"); + SensorCalibrationsElemNames.add("CurrentFactor"); + fields.add( new UAVObjectField("SensorCalibrations", "", UAVObjectField.FieldType.FLOAT32, SensorCalibrationsElemNames, null) ); + + List TypeElemNames = new ArrayList(); + TypeElemNames.add("0"); + List TypeEnumOptions = new ArrayList(); + TypeEnumOptions.add("LiPo"); + TypeEnumOptions.add("A123"); + TypeEnumOptions.add("LiCo"); + TypeEnumOptions.add("LiFeSO4"); + TypeEnumOptions.add("None"); + fields.add( new UAVObjectField("Type", "", UAVObjectField.FieldType.ENUM, TypeElemNames, TypeEnumOptions) ); + + List NbCellsElemNames = new ArrayList(); + NbCellsElemNames.add("0"); + fields.add( new UAVObjectField("NbCells", "", UAVObjectField.FieldType.UINT8, NbCellsElemNames, null) ); + + List SensorTypeElemNames = new ArrayList(); + SensorTypeElemNames.add("0"); + List SensorTypeEnumOptions = new ArrayList(); + SensorTypeEnumOptions.add("None"); + fields.add( new UAVObjectField("SensorType", "", UAVObjectField.FieldType.ENUM, SensorTypeElemNames, SensorTypeEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Capacity").setValue(2200); + getField("VoltageThresholds").setValue(9.8,0); + getField("VoltageThresholds").setValue(9.2,1); + getField("SensorCalibrations").setValue(1,0); + getField("SensorCalibrations").setValue(1,1); + getField("Type").setValue("LiPo"); + getField("NbCells").setValue(3); + getField("SensorType").setValue("None"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FlightBatterySettings obj = new FlightBatterySettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FlightBatterySettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (FlightBatterySettings)(objMngr.getObject(FlightBatterySettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xF172BB18; + protected static final String NAME = "FlightBatterySettings"; + protected static String DESCRIPTION = "Flight Battery configuration."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java index d9fba1de5..82fcfae47 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java @@ -154,7 +154,7 @@ public class FlightBatteryState extends UAVDataObject { } // Constants - protected static final int OBJID = 0x791A50E; + protected static final int OBJID = 0x8C0D756; protected static final String NAME = "FlightBatteryState"; protected static String DESCRIPTION = "Battery status information."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java index fdc5bfcb0..dbe959f96 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java @@ -133,7 +133,7 @@ public class FlightPlanControl extends UAVDataObject { } // Constants - protected static final int OBJID = 0x6B4FE6DA; + protected static final int OBJID = 0x53E3F180; protected static final String NAME = "FlightPlanControl"; protected static String DESCRIPTION = "Control the flight plan script"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java index 383e4aff0..6fc39a26e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java @@ -129,7 +129,7 @@ public class FlightPlanSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x85368422; + protected static final int OBJID = 0x92E9FF76; protected static final String NAME = "FlightPlanSettings"; protected static String DESCRIPTION = "Settings for the flight plan module, control the execution of the script"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java index 2303514c0..7b78bce71 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java @@ -51,6 +51,19 @@ public class FlightPlanStatus extends UAVDataObject { List fields = new ArrayList(); + List ErrorFileIDElemNames = new ArrayList(); + ErrorFileIDElemNames.add("0"); + fields.add( new UAVObjectField("ErrorFileID", "", UAVObjectField.FieldType.UINT32, ErrorFileIDElemNames, null) ); + + List ErrorLineNumElemNames = new ArrayList(); + ErrorLineNumElemNames.add("0"); + fields.add( new UAVObjectField("ErrorLineNum", "", UAVObjectField.FieldType.UINT32, ErrorLineNumElemNames, null) ); + + List DebugElemNames = new ArrayList(); + DebugElemNames.add("0"); + DebugElemNames.add("1"); + fields.add( new UAVObjectField("Debug", "", UAVObjectField.FieldType.FLOAT32, DebugElemNames, null) ); + List StatusElemNames = new ArrayList(); StatusElemNames.add("0"); List StatusEnumOptions = new ArrayList(); @@ -83,22 +96,6 @@ public class FlightPlanStatus extends UAVDataObject { ErrorTypeEnumOptions.add("UnknownError"); fields.add( new UAVObjectField("ErrorType", "", UAVObjectField.FieldType.ENUM, ErrorTypeElemNames, ErrorTypeEnumOptions) ); - List ErrorFileIDElemNames = new ArrayList(); - ErrorFileIDElemNames.add("0"); - fields.add( new UAVObjectField("ErrorFileID", "", UAVObjectField.FieldType.UINT32, ErrorFileIDElemNames, null) ); - - List ErrorLineNumElemNames = new ArrayList(); - ErrorLineNumElemNames.add("0"); - fields.add( new UAVObjectField("ErrorLineNum", "", UAVObjectField.FieldType.UINT32, ErrorLineNumElemNames, null) ); - - List Debug1ElemNames = new ArrayList(); - Debug1ElemNames.add("0"); - fields.add( new UAVObjectField("Debug1", "", UAVObjectField.FieldType.FLOAT32, Debug1ElemNames, null) ); - - List Debug2ElemNames = new ArrayList(); - Debug2ElemNames.add("0"); - fields.add( new UAVObjectField("Debug2", "", UAVObjectField.FieldType.FLOAT32, Debug2ElemNames, null) ); - // Compute the number of bytes for this object int numBytes = 0; @@ -144,10 +141,10 @@ public class FlightPlanStatus extends UAVDataObject { */ public void setDefaultFieldValues() { + getField("Debug").setValue(0,0); + getField("Debug").setValue(0,1); getField("Status").setValue("Stopped"); getField("ErrorType").setValue("None"); - getField("Debug1").setValue(0); - getField("Debug2").setValue(0); } @@ -176,7 +173,7 @@ public class FlightPlanStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0x9FC14812; + protected static final int OBJID = 0x2206EE46; protected static final String NAME = "FlightPlanStatus"; protected static String DESCRIPTION = "Status of the flight plan script"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java new file mode 100644 index 000000000..d775b21e7 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java @@ -0,0 +1,155 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Contains major flight status information for other modules. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Contains major flight status information for other modules. + +generated from flightstatus.xml + **/ +public class FlightStatus extends UAVDataObject { + + public FlightStatus() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List ArmedElemNames = new ArrayList(); + ArmedElemNames.add("0"); + List ArmedEnumOptions = new ArrayList(); + ArmedEnumOptions.add("Disarmed"); + ArmedEnumOptions.add("Arming"); + ArmedEnumOptions.add("Armed"); + fields.add( new UAVObjectField("Armed", "", UAVObjectField.FieldType.ENUM, ArmedElemNames, ArmedEnumOptions) ); + + List FlightModeElemNames = new ArrayList(); + FlightModeElemNames.add("0"); + List FlightModeEnumOptions = new ArrayList(); + FlightModeEnumOptions.add("Manual"); + FlightModeEnumOptions.add("Stabilized1"); + FlightModeEnumOptions.add("Stabilized2"); + FlightModeEnumOptions.add("Stabilized3"); + FlightModeEnumOptions.add("VelocityControl"); + FlightModeEnumOptions.add("PositionHold"); + fields.add( new UAVObjectField("FlightMode", "", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 5000; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Armed").setValue("Disarmed"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FlightStatus obj = new FlightStatus(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FlightStatus GetInstance(UAVObjectManager objMngr, int instID) + { + return (FlightStatus)(objMngr.getObject(FlightStatus.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x743DB13C; + protected static final String NAME = "FlightStatus"; + protected static String DESCRIPTION = "Contains major flight status information for other modules."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java index b58fe6d46..403ea1d5e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java @@ -51,15 +51,6 @@ public class FlightTelemetryStats extends UAVDataObject { List fields = new ArrayList(); - List StatusElemNames = new ArrayList(); - StatusElemNames.add("0"); - List StatusEnumOptions = new ArrayList(); - StatusEnumOptions.add("Disconnected"); - StatusEnumOptions.add("HandshakeReq"); - StatusEnumOptions.add("HandshakeAck"); - StatusEnumOptions.add("Connected"); - fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); - List TxDataRateElemNames = new ArrayList(); TxDataRateElemNames.add("0"); fields.add( new UAVObjectField("TxDataRate", "bytes/sec", UAVObjectField.FieldType.FLOAT32, TxDataRateElemNames, null) ); @@ -80,6 +71,15 @@ public class FlightTelemetryStats extends UAVDataObject { TxRetriesElemNames.add("0"); fields.add( new UAVObjectField("TxRetries", "count", UAVObjectField.FieldType.UINT32, TxRetriesElemNames, null) ); + List StatusElemNames = new ArrayList(); + StatusElemNames.add("0"); + List StatusEnumOptions = new ArrayList(); + StatusEnumOptions.add("Disconnected"); + StatusEnumOptions.add("HandshakeReq"); + StatusEnumOptions.add("HandshakeAck"); + StatusEnumOptions.add("Connected"); + fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -153,7 +153,7 @@ public class FlightTelemetryStats extends UAVDataObject { } // Constants - protected static final int OBJID = 0x660C265E; + protected static final int OBJID = 0x2F7E2902; protected static final String NAME = "FlightTelemetryStats"; protected static String DESCRIPTION = "Maintains the telemetry statistics from the OpenPilot flight computer."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java new file mode 100644 index 000000000..3cb3811ae --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java @@ -0,0 +1,144 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * A receiver channel group carried over the telemetry link. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +A receiver channel group carried over the telemetry link. + +generated from gcsreceiver.xml + **/ +public class GCSReceiver extends UAVDataObject { + + public GCSReceiver() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List ChannelElemNames = new ArrayList(); + ChannelElemNames.add("0"); + ChannelElemNames.add("1"); + ChannelElemNames.add("2"); + ChannelElemNames.add("3"); + ChannelElemNames.add("4"); + ChannelElemNames.add("5"); + fields.add( new UAVObjectField("Channel", "us", UAVObjectField.FieldType.UINT16, ChannelElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READONLY; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GCSReceiver obj = new GCSReceiver(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GCSReceiver GetInstance(UAVObjectManager objMngr, int instID) + { + return (GCSReceiver)(objMngr.getObject(GCSReceiver.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xCC7E2BBC; + protected static final String NAME = "GCSReceiver"; + protected static String DESCRIPTION = "A receiver channel group carried over the telemetry link."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java index 0f304d45d..b32f551ce 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java @@ -51,15 +51,6 @@ public class GCSTelemetryStats extends UAVDataObject { List fields = new ArrayList(); - List StatusElemNames = new ArrayList(); - StatusElemNames.add("0"); - List StatusEnumOptions = new ArrayList(); - StatusEnumOptions.add("Disconnected"); - StatusEnumOptions.add("HandshakeReq"); - StatusEnumOptions.add("HandshakeAck"); - StatusEnumOptions.add("Connected"); - fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); - List TxDataRateElemNames = new ArrayList(); TxDataRateElemNames.add("0"); fields.add( new UAVObjectField("TxDataRate", "bytes/sec", UAVObjectField.FieldType.FLOAT32, TxDataRateElemNames, null) ); @@ -80,6 +71,15 @@ public class GCSTelemetryStats extends UAVDataObject { TxRetriesElemNames.add("0"); fields.add( new UAVObjectField("TxRetries", "count", UAVObjectField.FieldType.UINT32, TxRetriesElemNames, null) ); + List StatusElemNames = new ArrayList(); + StatusElemNames.add("0"); + List StatusEnumOptions = new ArrayList(); + StatusEnumOptions.add("Disconnected"); + StatusEnumOptions.add("HandshakeReq"); + StatusEnumOptions.add("HandshakeAck"); + StatusEnumOptions.add("Connected"); + fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -153,7 +153,7 @@ public class GCSTelemetryStats extends UAVDataObject { } // Constants - protected static final int OBJID = 0x771E1046; + protected static final int OBJID = 0xABC72744; protected static final String NAME = "GCSTelemetryStats"; protected static String DESCRIPTION = "The telemetry statistics from the ground computer"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java index 889091e0e..5f4e20b46 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java @@ -51,15 +51,6 @@ public class GPSPosition extends UAVDataObject { List fields = new ArrayList(); - List StatusElemNames = new ArrayList(); - StatusElemNames.add("0"); - List StatusEnumOptions = new ArrayList(); - StatusEnumOptions.add("NoGPS"); - StatusEnumOptions.add("NoFix"); - StatusEnumOptions.add("Fix2D"); - StatusEnumOptions.add("Fix3D"); - fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); - List LatitudeElemNames = new ArrayList(); LatitudeElemNames.add("0"); fields.add( new UAVObjectField("Latitude", "degrees x 10^-7", UAVObjectField.FieldType.INT32, LatitudeElemNames, null) ); @@ -84,10 +75,6 @@ public class GPSPosition extends UAVDataObject { GroundspeedElemNames.add("0"); fields.add( new UAVObjectField("Groundspeed", "m/s", UAVObjectField.FieldType.FLOAT32, GroundspeedElemNames, null) ); - List SatellitesElemNames = new ArrayList(); - SatellitesElemNames.add("0"); - fields.add( new UAVObjectField("Satellites", "", UAVObjectField.FieldType.INT8, SatellitesElemNames, null) ); - List PDOPElemNames = new ArrayList(); PDOPElemNames.add("0"); fields.add( new UAVObjectField("PDOP", "", UAVObjectField.FieldType.FLOAT32, PDOPElemNames, null) ); @@ -100,6 +87,19 @@ public class GPSPosition extends UAVDataObject { VDOPElemNames.add("0"); fields.add( new UAVObjectField("VDOP", "", UAVObjectField.FieldType.FLOAT32, VDOPElemNames, null) ); + List StatusElemNames = new ArrayList(); + StatusElemNames.add("0"); + List StatusEnumOptions = new ArrayList(); + StatusEnumOptions.add("NoGPS"); + StatusEnumOptions.add("NoFix"); + StatusEnumOptions.add("Fix2D"); + StatusEnumOptions.add("Fix3D"); + fields.add( new UAVObjectField("Status", "", UAVObjectField.FieldType.ENUM, StatusElemNames, StatusEnumOptions) ); + + List SatellitesElemNames = new ArrayList(); + SatellitesElemNames.add("0"); + fields.add( new UAVObjectField("Satellites", "", UAVObjectField.FieldType.INT8, SatellitesElemNames, null) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -173,7 +173,7 @@ public class GPSPosition extends UAVDataObject { } // Constants - protected static final int OBJID = 0xB5495042; + protected static final int OBJID = 0xE2A323B6; protected static final String NAME = "GPSPosition"; protected static String DESCRIPTION = "Raw GPS data from @ref GPSModule. Should only be used by @ref AHRSCommsModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java index fa1100207..bb331132d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java @@ -51,29 +51,6 @@ public class GPSSatellites extends UAVDataObject { List fields = new ArrayList(); - List SatsInViewElemNames = new ArrayList(); - SatsInViewElemNames.add("0"); - fields.add( new UAVObjectField("SatsInView", "", UAVObjectField.FieldType.INT8, SatsInViewElemNames, null) ); - - List PRNElemNames = new ArrayList(); - PRNElemNames.add("0"); - PRNElemNames.add("1"); - PRNElemNames.add("2"); - PRNElemNames.add("3"); - PRNElemNames.add("4"); - PRNElemNames.add("5"); - PRNElemNames.add("6"); - PRNElemNames.add("7"); - PRNElemNames.add("8"); - PRNElemNames.add("9"); - PRNElemNames.add("10"); - PRNElemNames.add("11"); - PRNElemNames.add("12"); - PRNElemNames.add("13"); - PRNElemNames.add("14"); - PRNElemNames.add("15"); - fields.add( new UAVObjectField("PRN", "", UAVObjectField.FieldType.INT8, PRNElemNames, null) ); - List ElevationElemNames = new ArrayList(); ElevationElemNames.add("0"); ElevationElemNames.add("1"); @@ -112,6 +89,29 @@ public class GPSSatellites extends UAVDataObject { AzimuthElemNames.add("15"); fields.add( new UAVObjectField("Azimuth", "degrees", UAVObjectField.FieldType.FLOAT32, AzimuthElemNames, null) ); + List SatsInViewElemNames = new ArrayList(); + SatsInViewElemNames.add("0"); + fields.add( new UAVObjectField("SatsInView", "", UAVObjectField.FieldType.INT8, SatsInViewElemNames, null) ); + + List PRNElemNames = new ArrayList(); + PRNElemNames.add("0"); + PRNElemNames.add("1"); + PRNElemNames.add("2"); + PRNElemNames.add("3"); + PRNElemNames.add("4"); + PRNElemNames.add("5"); + PRNElemNames.add("6"); + PRNElemNames.add("7"); + PRNElemNames.add("8"); + PRNElemNames.add("9"); + PRNElemNames.add("10"); + PRNElemNames.add("11"); + PRNElemNames.add("12"); + PRNElemNames.add("13"); + PRNElemNames.add("14"); + PRNElemNames.add("15"); + fields.add( new UAVObjectField("PRN", "", UAVObjectField.FieldType.INT8, PRNElemNames, null) ); + List SNRElemNames = new ArrayList(); SNRElemNames.add("0"); SNRElemNames.add("1"); @@ -204,7 +204,7 @@ public class GPSSatellites extends UAVDataObject { } // Constants - protected static final int OBJID = 0xD62FA3AE; + protected static final int OBJID = 0x920D998; protected static final String NAME = "GPSSatellites"; protected static String DESCRIPTION = "Contains information about the GPS satellites in view from @ref GPSModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java index 5ff55cc2e..5aa4df7bf 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java @@ -51,6 +51,10 @@ public class GPSTime extends UAVDataObject { List fields = new ArrayList(); + List YearElemNames = new ArrayList(); + YearElemNames.add("0"); + fields.add( new UAVObjectField("Year", "", UAVObjectField.FieldType.INT16, YearElemNames, null) ); + List MonthElemNames = new ArrayList(); MonthElemNames.add("0"); fields.add( new UAVObjectField("Month", "", UAVObjectField.FieldType.INT8, MonthElemNames, null) ); @@ -59,10 +63,6 @@ public class GPSTime extends UAVDataObject { DayElemNames.add("0"); fields.add( new UAVObjectField("Day", "", UAVObjectField.FieldType.INT8, DayElemNames, null) ); - List YearElemNames = new ArrayList(); - YearElemNames.add("0"); - fields.add( new UAVObjectField("Year", "", UAVObjectField.FieldType.INT16, YearElemNames, null) ); - List HourElemNames = new ArrayList(); HourElemNames.add("0"); fields.add( new UAVObjectField("Hour", "", UAVObjectField.FieldType.INT8, HourElemNames, null) ); @@ -148,7 +148,7 @@ public class GPSTime extends UAVDataObject { } // Constants - protected static final int OBJID = 0x56FFF0A2; + protected static final int OBJID = 0xD4478084; protected static final String NAME = "GPSTime"; protected static String DESCRIPTION = "Contains the GPS time from @ref GPSModule. Required to compute the world magnetic model correctly when setting the home location."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java index 2fe8bb437..205384efe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java @@ -51,29 +51,24 @@ public class GuidanceSettings extends UAVDataObject { List fields = new ArrayList(); - List GuidanceModeElemNames = new ArrayList(); - GuidanceModeElemNames.add("0"); - List GuidanceModeEnumOptions = new ArrayList(); - GuidanceModeEnumOptions.add("DUAL_LOOP"); - GuidanceModeEnumOptions.add("VELOCITY_CONTROL"); - fields.add( new UAVObjectField("GuidanceMode", "", UAVObjectField.FieldType.ENUM, GuidanceModeElemNames, GuidanceModeEnumOptions) ); - - List HorizontalPElemNames = new ArrayList(); - HorizontalPElemNames.add("Kp"); - HorizontalPElemNames.add("Max"); - fields.add( new UAVObjectField("HorizontalP", "", UAVObjectField.FieldType.FLOAT32, HorizontalPElemNames, null) ); + List HorizontalPosPIElemNames = new ArrayList(); + HorizontalPosPIElemNames.add("Kp"); + HorizontalPosPIElemNames.add("Ki"); + HorizontalPosPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("HorizontalPosPI", "(cm/s)/cm", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) ); List HorizontalVelPIDElemNames = new ArrayList(); HorizontalVelPIDElemNames.add("Kp"); HorizontalVelPIDElemNames.add("Ki"); HorizontalVelPIDElemNames.add("Kd"); HorizontalVelPIDElemNames.add("ILimit"); - fields.add( new UAVObjectField("HorizontalVelPID", "", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); + fields.add( new UAVObjectField("HorizontalVelPID", "deg/(cm/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); - List VerticalPElemNames = new ArrayList(); - VerticalPElemNames.add("Kp"); - VerticalPElemNames.add("Max"); - fields.add( new UAVObjectField("VerticalP", "", UAVObjectField.FieldType.FLOAT32, VerticalPElemNames, null) ); + List VerticalPosPIElemNames = new ArrayList(); + VerticalPosPIElemNames.add("Kp"); + VerticalPosPIElemNames.add("Ki"); + VerticalPosPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("VerticalPosPI", "", UAVObjectField.FieldType.FLOAT32, VerticalPosPIElemNames, null) ); List VerticalVelPIDElemNames = new ArrayList(); VerticalVelPIDElemNames.add("Kp"); @@ -82,13 +77,6 @@ public class GuidanceSettings extends UAVDataObject { VerticalVelPIDElemNames.add("ILimit"); fields.add( new UAVObjectField("VerticalVelPID", "", UAVObjectField.FieldType.FLOAT32, VerticalVelPIDElemNames, null) ); - List ThrottleControlElemNames = new ArrayList(); - ThrottleControlElemNames.add("0"); - List ThrottleControlEnumOptions = new ArrayList(); - ThrottleControlEnumOptions.add("FALSE"); - ThrottleControlEnumOptions.add("TRUE"); - fields.add( new UAVObjectField("ThrottleControl", "", UAVObjectField.FieldType.ENUM, ThrottleControlElemNames, ThrottleControlEnumOptions) ); - List MaxRollPitchElemNames = new ArrayList(); MaxRollPitchElemNames.add("0"); fields.add( new UAVObjectField("MaxRollPitch", "deg", UAVObjectField.FieldType.FLOAT32, MaxRollPitchElemNames, null) ); @@ -97,6 +85,28 @@ public class GuidanceSettings extends UAVDataObject { UpdatePeriodElemNames.add("0"); fields.add( new UAVObjectField("UpdatePeriod", "", UAVObjectField.FieldType.INT32, UpdatePeriodElemNames, null) ); + List HorizontalVelMaxElemNames = new ArrayList(); + HorizontalVelMaxElemNames.add("0"); + fields.add( new UAVObjectField("HorizontalVelMax", "cm/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) ); + + List VerticalVelMaxElemNames = new ArrayList(); + VerticalVelMaxElemNames.add("0"); + fields.add( new UAVObjectField("VerticalVelMax", "cm/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) ); + + List GuidanceModeElemNames = new ArrayList(); + GuidanceModeElemNames.add("0"); + List GuidanceModeEnumOptions = new ArrayList(); + GuidanceModeEnumOptions.add("DUAL_LOOP"); + GuidanceModeEnumOptions.add("VELOCITY_CONTROL"); + fields.add( new UAVObjectField("GuidanceMode", "", UAVObjectField.FieldType.ENUM, GuidanceModeElemNames, GuidanceModeEnumOptions) ); + + List ThrottleControlElemNames = new ArrayList(); + ThrottleControlElemNames.add("0"); + List ThrottleControlEnumOptions = new ArrayList(); + ThrottleControlEnumOptions.add("FALSE"); + ThrottleControlEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("ThrottleControl", "", UAVObjectField.FieldType.ENUM, ThrottleControlElemNames, ThrottleControlEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -142,22 +152,26 @@ public class GuidanceSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("GuidanceMode").setValue("DUAL_LOOP"); - getField("HorizontalP").setValue(0.2,0); - getField("HorizontalP").setValue(150,1); - getField("HorizontalVelPID").setValue(0.1,0); + getField("HorizontalPosPI").setValue(0.1,0); + getField("HorizontalPosPI").setValue(0.001,1); + getField("HorizontalPosPI").setValue(300,2); + getField("HorizontalVelPID").setValue(0.05,0); getField("HorizontalVelPID").setValue(0.002,1); getField("HorizontalVelPID").setValue(0,2); getField("HorizontalVelPID").setValue(1000,3); - getField("VerticalP").setValue(0.1,0); - getField("VerticalP").setValue(200,1); + getField("VerticalPosPI").setValue(0.1,0); + getField("VerticalPosPI").setValue(0.001,1); + getField("VerticalPosPI").setValue(200,2); getField("VerticalVelPID").setValue(0.1,0); getField("VerticalVelPID").setValue(0,1); getField("VerticalVelPID").setValue(0,2); getField("VerticalVelPID").setValue(0,3); - getField("ThrottleControl").setValue("FALSE"); getField("MaxRollPitch").setValue(10); getField("UpdatePeriod").setValue(100); + getField("HorizontalVelMax").setValue(300); + getField("VerticalVelMax").setValue(150); + getField("GuidanceMode").setValue("DUAL_LOOP"); + getField("ThrottleControl").setValue("FALSE"); } @@ -186,7 +200,7 @@ public class GuidanceSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x74740AA2; + protected static final int OBJID = 0x6EA79FB4; protected static final String NAME = "GuidanceSettings"; protected static String DESCRIPTION = "Settings for the @ref GuidanceModule"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java index 5941c069c..68abb3633 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java @@ -51,13 +51,6 @@ public class HomeLocation extends UAVDataObject { List fields = new ArrayList(); - List SetElemNames = new ArrayList(); - SetElemNames.add("0"); - List SetEnumOptions = new ArrayList(); - SetEnumOptions.add("FALSE"); - SetEnumOptions.add("TRUE"); - fields.add( new UAVObjectField("Set", "", UAVObjectField.FieldType.ENUM, SetElemNames, SetEnumOptions) ); - List LatitudeElemNames = new ArrayList(); LatitudeElemNames.add("0"); fields.add( new UAVObjectField("Latitude", "deg * 10e6", UAVObjectField.FieldType.INT32, LatitudeElemNames, null) ); @@ -94,6 +87,17 @@ public class HomeLocation extends UAVDataObject { BeElemNames.add("2"); fields.add( new UAVObjectField("Be", "", UAVObjectField.FieldType.FLOAT32, BeElemNames, null) ); + List g_eElemNames = new ArrayList(); + g_eElemNames.add("0"); + fields.add( new UAVObjectField("g_e", "m/s^2", UAVObjectField.FieldType.FLOAT32, g_eElemNames, null) ); + + List SetElemNames = new ArrayList(); + SetElemNames.add("0"); + List SetEnumOptions = new ArrayList(); + SetEnumOptions.add("FALSE"); + SetEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("Set", "", UAVObjectField.FieldType.ENUM, SetElemNames, SetEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -139,7 +143,6 @@ public class HomeLocation extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("Set").setValue("FALSE"); getField("Latitude").setValue(0); getField("Longitude").setValue(0); getField("Altitude").setValue(0); @@ -158,6 +161,8 @@ public class HomeLocation extends UAVDataObject { getField("Be").setValue(0,0); getField("Be").setValue(0,1); getField("Be").setValue(0,2); + getField("g_e").setValue(9.81); + getField("Set").setValue("FALSE"); } @@ -186,7 +191,7 @@ public class HomeLocation extends UAVDataObject { } // Constants - protected static final int OBJID = 0xD6008ED2; + protected static final int OBJID = 0x5BB3AEFC; protected static final String NAME = "HomeLocation"; protected static String DESCRIPTION = "HomeLocation setting which contains the constants to tranlate from longitutde and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java new file mode 100644 index 000000000..83b7ae7b6 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java @@ -0,0 +1,291 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Selection of optional hardware configurations. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Selection of optional hardware configurations. + +generated from hwsettings.xml + **/ +public class HwSettings extends UAVDataObject { + + public HwSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List CC_RcvrPortElemNames = new ArrayList(); + CC_RcvrPortElemNames.add("0"); + List CC_RcvrPortEnumOptions = new ArrayList(); + CC_RcvrPortEnumOptions.add("Disabled"); + CC_RcvrPortEnumOptions.add("PWM"); + CC_RcvrPortEnumOptions.add("PPM"); + CC_RcvrPortEnumOptions.add("PPM+Outputs"); + CC_RcvrPortEnumOptions.add("Outputs"); + fields.add( new UAVObjectField("CC_RcvrPort", "function", UAVObjectField.FieldType.ENUM, CC_RcvrPortElemNames, CC_RcvrPortEnumOptions) ); + + List CC_MainPortElemNames = new ArrayList(); + CC_MainPortElemNames.add("0"); + List CC_MainPortEnumOptions = new ArrayList(); + CC_MainPortEnumOptions.add("Disabled"); + CC_MainPortEnumOptions.add("Telemetry"); + CC_MainPortEnumOptions.add("GPS"); + CC_MainPortEnumOptions.add("S.Bus"); + CC_MainPortEnumOptions.add("DSM2"); + CC_MainPortEnumOptions.add("DSMX (10bit)"); + CC_MainPortEnumOptions.add("DSMX (11bit)"); + CC_MainPortEnumOptions.add("ComAux"); + CC_MainPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("CC_MainPort", "function", UAVObjectField.FieldType.ENUM, CC_MainPortElemNames, CC_MainPortEnumOptions) ); + + List CC_FlexiPortElemNames = new ArrayList(); + CC_FlexiPortElemNames.add("0"); + List CC_FlexiPortEnumOptions = new ArrayList(); + CC_FlexiPortEnumOptions.add("Disabled"); + CC_FlexiPortEnumOptions.add("Telemetry"); + CC_FlexiPortEnumOptions.add("GPS"); + CC_FlexiPortEnumOptions.add("I2C"); + CC_FlexiPortEnumOptions.add("DSM2"); + CC_FlexiPortEnumOptions.add("DSMX (10bit)"); + CC_FlexiPortEnumOptions.add("DSMX (11bit)"); + CC_FlexiPortEnumOptions.add("ComAux"); + CC_FlexiPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("CC_FlexiPort", "function", UAVObjectField.FieldType.ENUM, CC_FlexiPortElemNames, CC_FlexiPortEnumOptions) ); + + List OP_RcvrPortElemNames = new ArrayList(); + OP_RcvrPortElemNames.add("0"); + List OP_RcvrPortEnumOptions = new ArrayList(); + OP_RcvrPortEnumOptions.add("Disabled"); + OP_RcvrPortEnumOptions.add("PWM"); + OP_RcvrPortEnumOptions.add("PPM"); + OP_RcvrPortEnumOptions.add("DSM2"); + OP_RcvrPortEnumOptions.add("DSMX (10bit)"); + OP_RcvrPortEnumOptions.add("DSMX (11bit)"); + OP_RcvrPortEnumOptions.add("Debug"); + fields.add( new UAVObjectField("OP_RcvrPort", "function", UAVObjectField.FieldType.ENUM, OP_RcvrPortElemNames, OP_RcvrPortEnumOptions) ); + + List OP_MainPortElemNames = new ArrayList(); + OP_MainPortElemNames.add("0"); + List OP_MainPortEnumOptions = new ArrayList(); + OP_MainPortEnumOptions.add("Disabled"); + OP_MainPortEnumOptions.add("Telemetry"); + fields.add( new UAVObjectField("OP_MainPort", "function", UAVObjectField.FieldType.ENUM, OP_MainPortElemNames, OP_MainPortEnumOptions) ); + + List OP_FlexiPortElemNames = new ArrayList(); + OP_FlexiPortElemNames.add("0"); + List OP_FlexiPortEnumOptions = new ArrayList(); + OP_FlexiPortEnumOptions.add("Disabled"); + OP_FlexiPortEnumOptions.add("GPS"); + fields.add( new UAVObjectField("OP_FlexiPort", "function", UAVObjectField.FieldType.ENUM, OP_FlexiPortElemNames, OP_FlexiPortEnumOptions) ); + + List TelemetrySpeedElemNames = new ArrayList(); + TelemetrySpeedElemNames.add("0"); + List TelemetrySpeedEnumOptions = new ArrayList(); + TelemetrySpeedEnumOptions.add("2400"); + TelemetrySpeedEnumOptions.add("4800"); + TelemetrySpeedEnumOptions.add("9600"); + TelemetrySpeedEnumOptions.add("19200"); + TelemetrySpeedEnumOptions.add("38400"); + TelemetrySpeedEnumOptions.add("57600"); + TelemetrySpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("TelemetrySpeed", "bps", UAVObjectField.FieldType.ENUM, TelemetrySpeedElemNames, TelemetrySpeedEnumOptions) ); + + List GPSSpeedElemNames = new ArrayList(); + GPSSpeedElemNames.add("0"); + List GPSSpeedEnumOptions = new ArrayList(); + GPSSpeedEnumOptions.add("2400"); + GPSSpeedEnumOptions.add("4800"); + GPSSpeedEnumOptions.add("9600"); + GPSSpeedEnumOptions.add("19200"); + GPSSpeedEnumOptions.add("38400"); + GPSSpeedEnumOptions.add("57600"); + GPSSpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("GPSSpeed", "bps", UAVObjectField.FieldType.ENUM, GPSSpeedElemNames, GPSSpeedEnumOptions) ); + + List ComUsbBridgeSpeedElemNames = new ArrayList(); + ComUsbBridgeSpeedElemNames.add("0"); + List ComUsbBridgeSpeedEnumOptions = new ArrayList(); + ComUsbBridgeSpeedEnumOptions.add("2400"); + ComUsbBridgeSpeedEnumOptions.add("4800"); + ComUsbBridgeSpeedEnumOptions.add("9600"); + ComUsbBridgeSpeedEnumOptions.add("19200"); + ComUsbBridgeSpeedEnumOptions.add("38400"); + ComUsbBridgeSpeedEnumOptions.add("57600"); + ComUsbBridgeSpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("ComUsbBridgeSpeed", "bps", UAVObjectField.FieldType.ENUM, ComUsbBridgeSpeedElemNames, ComUsbBridgeSpeedEnumOptions) ); + + List USB_DeviceTypeElemNames = new ArrayList(); + USB_DeviceTypeElemNames.add("0"); + List USB_DeviceTypeEnumOptions = new ArrayList(); + USB_DeviceTypeEnumOptions.add("HID-only"); + USB_DeviceTypeEnumOptions.add("HID+VCP"); + USB_DeviceTypeEnumOptions.add("VCP-only"); + fields.add( new UAVObjectField("USB_DeviceType", "descriptor", UAVObjectField.FieldType.ENUM, USB_DeviceTypeElemNames, USB_DeviceTypeEnumOptions) ); + + List USB_HIDPortElemNames = new ArrayList(); + USB_HIDPortElemNames.add("0"); + List USB_HIDPortEnumOptions = new ArrayList(); + USB_HIDPortEnumOptions.add("USBTelemetry"); + USB_HIDPortEnumOptions.add("Disabled"); + fields.add( new UAVObjectField("USB_HIDPort", "function", UAVObjectField.FieldType.ENUM, USB_HIDPortElemNames, USB_HIDPortEnumOptions) ); + + List USB_VCPPortElemNames = new ArrayList(); + USB_VCPPortElemNames.add("0"); + List USB_VCPPortEnumOptions = new ArrayList(); + USB_VCPPortEnumOptions.add("USBTelemetry"); + USB_VCPPortEnumOptions.add("ComBridge"); + USB_VCPPortEnumOptions.add("Disabled"); + fields.add( new UAVObjectField("USB_VCPPort", "function", UAVObjectField.FieldType.ENUM, USB_VCPPortElemNames, USB_VCPPortEnumOptions) ); + + List OptionalModulesElemNames = new ArrayList(); + OptionalModulesElemNames.add("CameraStab"); + OptionalModulesElemNames.add("GPS"); + OptionalModulesElemNames.add("ComUsbBridge"); + OptionalModulesElemNames.add("Fault"); + OptionalModulesElemNames.add("Altitude"); + List OptionalModulesEnumOptions = new ArrayList(); + OptionalModulesEnumOptions.add("Disabled"); + OptionalModulesEnumOptions.add("Enabled"); + fields.add( new UAVObjectField("OptionalModules", "", UAVObjectField.FieldType.ENUM, OptionalModulesElemNames, OptionalModulesEnumOptions) ); + + List DSMxBindElemNames = new ArrayList(); + DSMxBindElemNames.add("0"); + fields.add( new UAVObjectField("DSMxBind", "", UAVObjectField.FieldType.UINT8, DSMxBindElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsTelemetryUpdatePeriod = 0; + + metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; + metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; + + metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("CC_RcvrPort").setValue("PWM"); + getField("CC_MainPort").setValue("Disabled"); + getField("CC_FlexiPort").setValue("Disabled"); + getField("OP_RcvrPort").setValue("PWM"); + getField("OP_MainPort").setValue("Telemetry"); + getField("OP_FlexiPort").setValue("GPS"); + getField("TelemetrySpeed").setValue("57600"); + getField("GPSSpeed").setValue("57600"); + getField("ComUsbBridgeSpeed").setValue("57600"); + getField("USB_DeviceType").setValue("HID-only"); + getField("USB_HIDPort").setValue("USBTelemetry"); + getField("USB_VCPPort").setValue("Disabled"); + getField("OptionalModules").setValue("Disabled",0); + getField("OptionalModules").setValue("Disabled",1); + getField("OptionalModules").setValue("Disabled",2); + getField("OptionalModules").setValue("Disabled",3); + getField("OptionalModules").setValue("Disabled",4); + getField("DSMxBind").setValue(0); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + HwSettings obj = new HwSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public HwSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (HwSettings)(objMngr.getObject(HwSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x2EE6575A; + protected static final String NAME = "HwSettings"; + protected static String DESCRIPTION = "Selection of optional hardware configurations."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java index fc68e2902..abd8f41f6 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java @@ -51,6 +51,22 @@ public class I2CStats extends UAVDataObject { List fields = new ArrayList(); + List evirq_logElemNames = new ArrayList(); + evirq_logElemNames.add("0"); + evirq_logElemNames.add("1"); + evirq_logElemNames.add("2"); + evirq_logElemNames.add("3"); + evirq_logElemNames.add("4"); + fields.add( new UAVObjectField("evirq_log", "", UAVObjectField.FieldType.UINT32, evirq_logElemNames, null) ); + + List erirq_logElemNames = new ArrayList(); + erirq_logElemNames.add("0"); + erirq_logElemNames.add("1"); + erirq_logElemNames.add("2"); + erirq_logElemNames.add("3"); + erirq_logElemNames.add("4"); + fields.add( new UAVObjectField("erirq_log", "", UAVObjectField.FieldType.UINT32, erirq_logElemNames, null) ); + List event_errorsElemNames = new ArrayList(); event_errorsElemNames.add("0"); fields.add( new UAVObjectField("event_errors", "", UAVObjectField.FieldType.UINT8, event_errorsElemNames, null) ); @@ -79,22 +95,6 @@ public class I2CStats extends UAVDataObject { last_error_typeEnumOptions.add("INTERRUPT"); fields.add( new UAVObjectField("last_error_type", "", UAVObjectField.FieldType.ENUM, last_error_typeElemNames, last_error_typeEnumOptions) ); - List evirq_logElemNames = new ArrayList(); - evirq_logElemNames.add("0"); - evirq_logElemNames.add("1"); - evirq_logElemNames.add("2"); - evirq_logElemNames.add("3"); - evirq_logElemNames.add("4"); - fields.add( new UAVObjectField("evirq_log", "", UAVObjectField.FieldType.UINT32, evirq_logElemNames, null) ); - - List erirq_logElemNames = new ArrayList(); - erirq_logElemNames.add("0"); - erirq_logElemNames.add("1"); - erirq_logElemNames.add("2"); - erirq_logElemNames.add("3"); - erirq_logElemNames.add("4"); - fields.add( new UAVObjectField("erirq_log", "", UAVObjectField.FieldType.UINT32, erirq_logElemNames, null) ); - List event_logElemNames = new ArrayList(); event_logElemNames.add("0"); event_logElemNames.add("1"); @@ -227,7 +227,7 @@ public class I2CStats extends UAVDataObject { } // Constants - protected static final int OBJID = 0x23CE9E9C; + protected static final int OBJID = 0xB714823E; protected static final String NAME = "I2CStats"; protected static String DESCRIPTION = "Tracks statistics on the I2C bus."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java index 636f30946..6ac5a1b2c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java @@ -51,19 +51,9 @@ public class ManualControlCommand extends UAVDataObject { List fields = new ArrayList(); - List ConnectedElemNames = new ArrayList(); - ConnectedElemNames.add("0"); - List ConnectedEnumOptions = new ArrayList(); - ConnectedEnumOptions.add("False"); - ConnectedEnumOptions.add("True"); - fields.add( new UAVObjectField("Connected", "", UAVObjectField.FieldType.ENUM, ConnectedElemNames, ConnectedEnumOptions) ); - - List ArmedElemNames = new ArrayList(); - ArmedElemNames.add("0"); - List ArmedEnumOptions = new ArrayList(); - ArmedEnumOptions.add("False"); - ArmedEnumOptions.add("True"); - fields.add( new UAVObjectField("Armed", "", UAVObjectField.FieldType.ENUM, ArmedElemNames, ArmedEnumOptions) ); + List ThrottleElemNames = new ArrayList(); + ThrottleElemNames.add("0"); + fields.add( new UAVObjectField("Throttle", "%", UAVObjectField.FieldType.FLOAT32, ThrottleElemNames, null) ); List RollElemNames = new ArrayList(); RollElemNames.add("0"); @@ -77,32 +67,9 @@ public class ManualControlCommand extends UAVDataObject { YawElemNames.add("0"); fields.add( new UAVObjectField("Yaw", "%", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); - List ThrottleElemNames = new ArrayList(); - ThrottleElemNames.add("0"); - fields.add( new UAVObjectField("Throttle", "%", UAVObjectField.FieldType.FLOAT32, ThrottleElemNames, null) ); - - List FlightModeElemNames = new ArrayList(); - FlightModeElemNames.add("0"); - List FlightModeEnumOptions = new ArrayList(); - FlightModeEnumOptions.add("Manual"); - FlightModeEnumOptions.add("Stabilized1"); - FlightModeEnumOptions.add("Stabilized2"); - FlightModeEnumOptions.add("Stabilized3"); - FlightModeEnumOptions.add("VelocityControl"); - FlightModeEnumOptions.add("PositionHold"); - fields.add( new UAVObjectField("FlightMode", "", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); - - List Accessory1ElemNames = new ArrayList(); - Accessory1ElemNames.add("0"); - fields.add( new UAVObjectField("Accessory1", "%", UAVObjectField.FieldType.FLOAT32, Accessory1ElemNames, null) ); - - List Accessory2ElemNames = new ArrayList(); - Accessory2ElemNames.add("0"); - fields.add( new UAVObjectField("Accessory2", "%", UAVObjectField.FieldType.FLOAT32, Accessory2ElemNames, null) ); - - List Accessory3ElemNames = new ArrayList(); - Accessory3ElemNames.add("0"); - fields.add( new UAVObjectField("Accessory3", "%", UAVObjectField.FieldType.FLOAT32, Accessory3ElemNames, null) ); + List CollectiveElemNames = new ArrayList(); + CollectiveElemNames.add("0"); + fields.add( new UAVObjectField("Collective", "%", UAVObjectField.FieldType.FLOAT32, CollectiveElemNames, null) ); List ChannelElemNames = new ArrayList(); ChannelElemNames.add("0"); @@ -113,8 +80,16 @@ public class ManualControlCommand extends UAVDataObject { ChannelElemNames.add("5"); ChannelElemNames.add("6"); ChannelElemNames.add("7"); + ChannelElemNames.add("8"); fields.add( new UAVObjectField("Channel", "us", UAVObjectField.FieldType.UINT16, ChannelElemNames, null) ); + List ConnectedElemNames = new ArrayList(); + ConnectedElemNames.add("0"); + List ConnectedEnumOptions = new ArrayList(); + ConnectedEnumOptions.add("False"); + ConnectedEnumOptions.add("True"); + fields.add( new UAVObjectField("Connected", "", UAVObjectField.FieldType.ENUM, ConnectedElemNames, ConnectedEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -188,7 +163,7 @@ public class ManualControlCommand extends UAVDataObject { } // Constants - protected static final int OBJID = 0x926794; + protected static final int OBJID = 0x1E82C2D2; protected static final String NAME = "ManualControlCommand"; protected static String DESCRIPTION = "The output from the @ref ManualControlModule which descodes the receiver inputs. Overriden by GCS for fly-by-wire control."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java index 83697999a..bb846695d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java @@ -51,125 +51,77 @@ public class ManualControlSettings extends UAVDataObject { List fields = new ArrayList(); - List InputModeElemNames = new ArrayList(); - InputModeElemNames.add("0"); - List InputModeEnumOptions = new ArrayList(); - InputModeEnumOptions.add("PWM"); - InputModeEnumOptions.add("PPM"); - InputModeEnumOptions.add("Spektrum"); - fields.add( new UAVObjectField("InputMode", "", UAVObjectField.FieldType.ENUM, InputModeElemNames, InputModeEnumOptions) ); + List ChannelMinElemNames = new ArrayList(); + ChannelMinElemNames.add("Throttle"); + ChannelMinElemNames.add("Roll"); + ChannelMinElemNames.add("Pitch"); + ChannelMinElemNames.add("Yaw"); + ChannelMinElemNames.add("FlightMode"); + ChannelMinElemNames.add("Collective"); + ChannelMinElemNames.add("Accessory0"); + ChannelMinElemNames.add("Accessory1"); + ChannelMinElemNames.add("Accessory2"); + fields.add( new UAVObjectField("ChannelMin", "us", UAVObjectField.FieldType.INT16, ChannelMinElemNames, null) ); - List RollElemNames = new ArrayList(); - RollElemNames.add("0"); - List RollEnumOptions = new ArrayList(); - RollEnumOptions.add("Channel1"); - RollEnumOptions.add("Channel2"); - RollEnumOptions.add("Channel3"); - RollEnumOptions.add("Channel4"); - RollEnumOptions.add("Channel5"); - RollEnumOptions.add("Channel6"); - RollEnumOptions.add("Channel7"); - RollEnumOptions.add("Channel8"); - RollEnumOptions.add("None"); - fields.add( new UAVObjectField("Roll", "channel", UAVObjectField.FieldType.ENUM, RollElemNames, RollEnumOptions) ); + List ChannelNeutralElemNames = new ArrayList(); + ChannelNeutralElemNames.add("Throttle"); + ChannelNeutralElemNames.add("Roll"); + ChannelNeutralElemNames.add("Pitch"); + ChannelNeutralElemNames.add("Yaw"); + ChannelNeutralElemNames.add("FlightMode"); + ChannelNeutralElemNames.add("Collective"); + ChannelNeutralElemNames.add("Accessory0"); + ChannelNeutralElemNames.add("Accessory1"); + ChannelNeutralElemNames.add("Accessory2"); + fields.add( new UAVObjectField("ChannelNeutral", "us", UAVObjectField.FieldType.INT16, ChannelNeutralElemNames, null) ); - List PitchElemNames = new ArrayList(); - PitchElemNames.add("0"); - List PitchEnumOptions = new ArrayList(); - PitchEnumOptions.add("Channel1"); - PitchEnumOptions.add("Channel2"); - PitchEnumOptions.add("Channel3"); - PitchEnumOptions.add("Channel4"); - PitchEnumOptions.add("Channel5"); - PitchEnumOptions.add("Channel6"); - PitchEnumOptions.add("Channel7"); - PitchEnumOptions.add("Channel8"); - PitchEnumOptions.add("None"); - fields.add( new UAVObjectField("Pitch", "channel", UAVObjectField.FieldType.ENUM, PitchElemNames, PitchEnumOptions) ); + List ChannelMaxElemNames = new ArrayList(); + ChannelMaxElemNames.add("Throttle"); + ChannelMaxElemNames.add("Roll"); + ChannelMaxElemNames.add("Pitch"); + ChannelMaxElemNames.add("Yaw"); + ChannelMaxElemNames.add("FlightMode"); + ChannelMaxElemNames.add("Collective"); + ChannelMaxElemNames.add("Accessory0"); + ChannelMaxElemNames.add("Accessory1"); + ChannelMaxElemNames.add("Accessory2"); + fields.add( new UAVObjectField("ChannelMax", "us", UAVObjectField.FieldType.INT16, ChannelMaxElemNames, null) ); - List YawElemNames = new ArrayList(); - YawElemNames.add("0"); - List YawEnumOptions = new ArrayList(); - YawEnumOptions.add("Channel1"); - YawEnumOptions.add("Channel2"); - YawEnumOptions.add("Channel3"); - YawEnumOptions.add("Channel4"); - YawEnumOptions.add("Channel5"); - YawEnumOptions.add("Channel6"); - YawEnumOptions.add("Channel7"); - YawEnumOptions.add("Channel8"); - YawEnumOptions.add("None"); - fields.add( new UAVObjectField("Yaw", "channel", UAVObjectField.FieldType.ENUM, YawElemNames, YawEnumOptions) ); + List ArmedTimeoutElemNames = new ArrayList(); + ArmedTimeoutElemNames.add("0"); + fields.add( new UAVObjectField("ArmedTimeout", "ms", UAVObjectField.FieldType.UINT16, ArmedTimeoutElemNames, null) ); - List ThrottleElemNames = new ArrayList(); - ThrottleElemNames.add("0"); - List ThrottleEnumOptions = new ArrayList(); - ThrottleEnumOptions.add("Channel1"); - ThrottleEnumOptions.add("Channel2"); - ThrottleEnumOptions.add("Channel3"); - ThrottleEnumOptions.add("Channel4"); - ThrottleEnumOptions.add("Channel5"); - ThrottleEnumOptions.add("Channel6"); - ThrottleEnumOptions.add("Channel7"); - ThrottleEnumOptions.add("Channel8"); - ThrottleEnumOptions.add("None"); - fields.add( new UAVObjectField("Throttle", "channel", UAVObjectField.FieldType.ENUM, ThrottleElemNames, ThrottleEnumOptions) ); + List ChannelGroupsElemNames = new ArrayList(); + ChannelGroupsElemNames.add("Throttle"); + ChannelGroupsElemNames.add("Roll"); + ChannelGroupsElemNames.add("Pitch"); + ChannelGroupsElemNames.add("Yaw"); + ChannelGroupsElemNames.add("FlightMode"); + ChannelGroupsElemNames.add("Collective"); + ChannelGroupsElemNames.add("Accessory0"); + ChannelGroupsElemNames.add("Accessory1"); + ChannelGroupsElemNames.add("Accessory2"); + List ChannelGroupsEnumOptions = new ArrayList(); + ChannelGroupsEnumOptions.add("PWM"); + ChannelGroupsEnumOptions.add("PPM"); + ChannelGroupsEnumOptions.add("DSM (MainPort)"); + ChannelGroupsEnumOptions.add("DSM (FlexiPort)"); + ChannelGroupsEnumOptions.add("S.Bus"); + ChannelGroupsEnumOptions.add("GCS"); + ChannelGroupsEnumOptions.add("None"); + fields.add( new UAVObjectField("ChannelGroups", "Channel Group", UAVObjectField.FieldType.ENUM, ChannelGroupsElemNames, ChannelGroupsEnumOptions) ); - List FlightModeElemNames = new ArrayList(); - FlightModeElemNames.add("0"); - List FlightModeEnumOptions = new ArrayList(); - FlightModeEnumOptions.add("Channel1"); - FlightModeEnumOptions.add("Channel2"); - FlightModeEnumOptions.add("Channel3"); - FlightModeEnumOptions.add("Channel4"); - FlightModeEnumOptions.add("Channel5"); - FlightModeEnumOptions.add("Channel6"); - FlightModeEnumOptions.add("Channel7"); - FlightModeEnumOptions.add("Channel8"); - FlightModeEnumOptions.add("None"); - fields.add( new UAVObjectField("FlightMode", "channel", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); - - List Accessory1ElemNames = new ArrayList(); - Accessory1ElemNames.add("0"); - List Accessory1EnumOptions = new ArrayList(); - Accessory1EnumOptions.add("Channel1"); - Accessory1EnumOptions.add("Channel2"); - Accessory1EnumOptions.add("Channel3"); - Accessory1EnumOptions.add("Channel4"); - Accessory1EnumOptions.add("Channel5"); - Accessory1EnumOptions.add("Channel6"); - Accessory1EnumOptions.add("Channel7"); - Accessory1EnumOptions.add("Channel8"); - Accessory1EnumOptions.add("None"); - fields.add( new UAVObjectField("Accessory1", "channel", UAVObjectField.FieldType.ENUM, Accessory1ElemNames, Accessory1EnumOptions) ); - - List Accessory2ElemNames = new ArrayList(); - Accessory2ElemNames.add("0"); - List Accessory2EnumOptions = new ArrayList(); - Accessory2EnumOptions.add("Channel1"); - Accessory2EnumOptions.add("Channel2"); - Accessory2EnumOptions.add("Channel3"); - Accessory2EnumOptions.add("Channel4"); - Accessory2EnumOptions.add("Channel5"); - Accessory2EnumOptions.add("Channel6"); - Accessory2EnumOptions.add("Channel7"); - Accessory2EnumOptions.add("Channel8"); - Accessory2EnumOptions.add("None"); - fields.add( new UAVObjectField("Accessory2", "channel", UAVObjectField.FieldType.ENUM, Accessory2ElemNames, Accessory2EnumOptions) ); - - List Accessory3ElemNames = new ArrayList(); - Accessory3ElemNames.add("0"); - List Accessory3EnumOptions = new ArrayList(); - Accessory3EnumOptions.add("Channel1"); - Accessory3EnumOptions.add("Channel2"); - Accessory3EnumOptions.add("Channel3"); - Accessory3EnumOptions.add("Channel4"); - Accessory3EnumOptions.add("Channel5"); - Accessory3EnumOptions.add("Channel6"); - Accessory3EnumOptions.add("Channel7"); - Accessory3EnumOptions.add("Channel8"); - Accessory3EnumOptions.add("None"); - fields.add( new UAVObjectField("Accessory3", "channel", UAVObjectField.FieldType.ENUM, Accessory3ElemNames, Accessory3EnumOptions) ); + List ChannelNumberElemNames = new ArrayList(); + ChannelNumberElemNames.add("Throttle"); + ChannelNumberElemNames.add("Roll"); + ChannelNumberElemNames.add("Pitch"); + ChannelNumberElemNames.add("Yaw"); + ChannelNumberElemNames.add("FlightMode"); + ChannelNumberElemNames.add("Collective"); + ChannelNumberElemNames.add("Accessory0"); + ChannelNumberElemNames.add("Accessory1"); + ChannelNumberElemNames.add("Accessory2"); + fields.add( new UAVObjectField("ChannelNumber", "channel", UAVObjectField.FieldType.UINT8, ChannelNumberElemNames, null) ); List ArmingElemNames = new ArrayList(); ArmingElemNames.add("0"); @@ -192,6 +144,8 @@ public class ManualControlSettings extends UAVDataObject { Stabilization1SettingsEnumOptions.add("None"); Stabilization1SettingsEnumOptions.add("Rate"); Stabilization1SettingsEnumOptions.add("Attitude"); + Stabilization1SettingsEnumOptions.add("AxisLock"); + Stabilization1SettingsEnumOptions.add("WeakLeveling"); fields.add( new UAVObjectField("Stabilization1Settings", "", UAVObjectField.FieldType.ENUM, Stabilization1SettingsElemNames, Stabilization1SettingsEnumOptions) ); List Stabilization2SettingsElemNames = new ArrayList(); @@ -202,6 +156,8 @@ public class ManualControlSettings extends UAVDataObject { Stabilization2SettingsEnumOptions.add("None"); Stabilization2SettingsEnumOptions.add("Rate"); Stabilization2SettingsEnumOptions.add("Attitude"); + Stabilization2SettingsEnumOptions.add("AxisLock"); + Stabilization2SettingsEnumOptions.add("WeakLeveling"); fields.add( new UAVObjectField("Stabilization2Settings", "", UAVObjectField.FieldType.ENUM, Stabilization2SettingsElemNames, Stabilization2SettingsEnumOptions) ); List Stabilization3SettingsElemNames = new ArrayList(); @@ -212,6 +168,8 @@ public class ManualControlSettings extends UAVDataObject { Stabilization3SettingsEnumOptions.add("None"); Stabilization3SettingsEnumOptions.add("Rate"); Stabilization3SettingsEnumOptions.add("Attitude"); + Stabilization3SettingsEnumOptions.add("AxisLock"); + Stabilization3SettingsEnumOptions.add("WeakLeveling"); fields.add( new UAVObjectField("Stabilization3Settings", "", UAVObjectField.FieldType.ENUM, Stabilization3SettingsElemNames, Stabilization3SettingsEnumOptions) ); List FlightModePositionElemNames = new ArrayList(); @@ -227,43 +185,6 @@ public class ManualControlSettings extends UAVDataObject { FlightModePositionEnumOptions.add("PositionHold"); fields.add( new UAVObjectField("FlightModePosition", "", UAVObjectField.FieldType.ENUM, FlightModePositionElemNames, FlightModePositionEnumOptions) ); - List ChannelMaxElemNames = new ArrayList(); - ChannelMaxElemNames.add("0"); - ChannelMaxElemNames.add("1"); - ChannelMaxElemNames.add("2"); - ChannelMaxElemNames.add("3"); - ChannelMaxElemNames.add("4"); - ChannelMaxElemNames.add("5"); - ChannelMaxElemNames.add("6"); - ChannelMaxElemNames.add("7"); - fields.add( new UAVObjectField("ChannelMax", "us", UAVObjectField.FieldType.INT16, ChannelMaxElemNames, null) ); - - List ChannelNeutralElemNames = new ArrayList(); - ChannelNeutralElemNames.add("0"); - ChannelNeutralElemNames.add("1"); - ChannelNeutralElemNames.add("2"); - ChannelNeutralElemNames.add("3"); - ChannelNeutralElemNames.add("4"); - ChannelNeutralElemNames.add("5"); - ChannelNeutralElemNames.add("6"); - ChannelNeutralElemNames.add("7"); - fields.add( new UAVObjectField("ChannelNeutral", "us", UAVObjectField.FieldType.INT16, ChannelNeutralElemNames, null) ); - - List ChannelMinElemNames = new ArrayList(); - ChannelMinElemNames.add("0"); - ChannelMinElemNames.add("1"); - ChannelMinElemNames.add("2"); - ChannelMinElemNames.add("3"); - ChannelMinElemNames.add("4"); - ChannelMinElemNames.add("5"); - ChannelMinElemNames.add("6"); - ChannelMinElemNames.add("7"); - fields.add( new UAVObjectField("ChannelMin", "us", UAVObjectField.FieldType.INT16, ChannelMinElemNames, null) ); - - List ArmedTimeoutElemNames = new ArrayList(); - ArmedTimeoutElemNames.add("0"); - fields.add( new UAVObjectField("ArmedTimeout", "ms", UAVObjectField.FieldType.UINT16, ArmedTimeoutElemNames, null) ); - // Compute the number of bytes for this object int numBytes = 0; @@ -309,44 +230,6 @@ public class ManualControlSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("InputMode").setValue("PWM"); - getField("Roll").setValue("Channel1"); - getField("Pitch").setValue("Channel2"); - getField("Yaw").setValue("Channel3"); - getField("Throttle").setValue("Channel4"); - getField("FlightMode").setValue("Channel5"); - getField("Accessory1").setValue("None"); - getField("Accessory2").setValue("None"); - getField("Accessory3").setValue("None"); - getField("Arming").setValue("Always Disarmed"); - getField("Stabilization1Settings").setValue("Attitude",0); - getField("Stabilization1Settings").setValue("Attitude",1); - getField("Stabilization1Settings").setValue("Attitude",2); - getField("Stabilization2Settings").setValue("Attitude",0); - getField("Stabilization2Settings").setValue("Attitude",1); - getField("Stabilization2Settings").setValue("Attitude",2); - getField("Stabilization3Settings").setValue("Attitude",0); - getField("Stabilization3Settings").setValue("Attitude",1); - getField("Stabilization3Settings").setValue("Attitude",2); - getField("FlightModePosition").setValue("Manual",0); - getField("FlightModePosition").setValue("Manual",1); - getField("FlightModePosition").setValue("Manual",2); - getField("ChannelMax").setValue(2000,0); - getField("ChannelMax").setValue(2000,1); - getField("ChannelMax").setValue(2000,2); - getField("ChannelMax").setValue(2000,3); - getField("ChannelMax").setValue(2000,4); - getField("ChannelMax").setValue(2000,5); - getField("ChannelMax").setValue(2000,6); - getField("ChannelMax").setValue(2000,7); - getField("ChannelNeutral").setValue(1500,0); - getField("ChannelNeutral").setValue(1500,1); - getField("ChannelNeutral").setValue(1500,2); - getField("ChannelNeutral").setValue(1500,3); - getField("ChannelNeutral").setValue(1500,4); - getField("ChannelNeutral").setValue(1500,5); - getField("ChannelNeutral").setValue(1500,6); - getField("ChannelNeutral").setValue(1500,7); getField("ChannelMin").setValue(1000,0); getField("ChannelMin").setValue(1000,1); getField("ChannelMin").setValue(1000,2); @@ -355,7 +238,57 @@ public class ManualControlSettings extends UAVDataObject { getField("ChannelMin").setValue(1000,5); getField("ChannelMin").setValue(1000,6); getField("ChannelMin").setValue(1000,7); + getField("ChannelMin").setValue(1000,8); + getField("ChannelNeutral").setValue(1500,0); + getField("ChannelNeutral").setValue(1500,1); + getField("ChannelNeutral").setValue(1500,2); + getField("ChannelNeutral").setValue(1500,3); + getField("ChannelNeutral").setValue(1500,4); + getField("ChannelNeutral").setValue(1500,5); + getField("ChannelNeutral").setValue(1500,6); + getField("ChannelNeutral").setValue(1500,7); + getField("ChannelNeutral").setValue(1500,8); + getField("ChannelMax").setValue(2000,0); + getField("ChannelMax").setValue(2000,1); + getField("ChannelMax").setValue(2000,2); + getField("ChannelMax").setValue(2000,3); + getField("ChannelMax").setValue(2000,4); + getField("ChannelMax").setValue(2000,5); + getField("ChannelMax").setValue(2000,6); + getField("ChannelMax").setValue(2000,7); + getField("ChannelMax").setValue(2000,8); getField("ArmedTimeout").setValue(30000); + getField("ChannelGroups").setValue("None",0); + getField("ChannelGroups").setValue("None",1); + getField("ChannelGroups").setValue("None",2); + getField("ChannelGroups").setValue("None",3); + getField("ChannelGroups").setValue("None",4); + getField("ChannelGroups").setValue("None",5); + getField("ChannelGroups").setValue("None",6); + getField("ChannelGroups").setValue("None",7); + getField("ChannelGroups").setValue("None",8); + getField("ChannelNumber").setValue(0,0); + getField("ChannelNumber").setValue(0,1); + getField("ChannelNumber").setValue(0,2); + getField("ChannelNumber").setValue(0,3); + getField("ChannelNumber").setValue(0,4); + getField("ChannelNumber").setValue(0,5); + getField("ChannelNumber").setValue(0,6); + getField("ChannelNumber").setValue(0,7); + getField("ChannelNumber").setValue(0,8); + getField("Arming").setValue("Always Disarmed"); + getField("Stabilization1Settings").setValue("Attitude",0); + getField("Stabilization1Settings").setValue("Attitude",1); + getField("Stabilization1Settings").setValue("Rate",2); + getField("Stabilization2Settings").setValue("Attitude",0); + getField("Stabilization2Settings").setValue("Attitude",1); + getField("Stabilization2Settings").setValue("Rate",2); + getField("Stabilization3Settings").setValue("Attitude",0); + getField("Stabilization3Settings").setValue("Attitude",1); + getField("Stabilization3Settings").setValue("Rate",2); + getField("FlightModePosition").setValue("Manual",0); + getField("FlightModePosition").setValue("Stabilized1",1); + getField("FlightModePosition").setValue("Stabilized2",2); } @@ -384,7 +317,7 @@ public class ManualControlSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x2B82102; + protected static final int OBJID = 0x24959BB0; protected static final String NAME = "ManualControlSettings"; protected static String DESCRIPTION = "Settings to indicate how to decode receiver input by @ref ManualControlModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java index 9aa87d49e..76841d8ff 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java @@ -83,12 +83,37 @@ public class MixerSettings extends UAVDataObject { ThrottleCurve2ElemNames.add("100"); fields.add( new UAVObjectField("ThrottleCurve2", "percent", UAVObjectField.FieldType.FLOAT32, ThrottleCurve2ElemNames, null) ); + List Curve2SourceElemNames = new ArrayList(); + Curve2SourceElemNames.add("0"); + List Curve2SourceEnumOptions = new ArrayList(); + Curve2SourceEnumOptions.add("Throttle"); + Curve2SourceEnumOptions.add("Roll"); + Curve2SourceEnumOptions.add("Pitch"); + Curve2SourceEnumOptions.add("Yaw"); + Curve2SourceEnumOptions.add("Collective"); + Curve2SourceEnumOptions.add("Accessory0"); + Curve2SourceEnumOptions.add("Accessory1"); + Curve2SourceEnumOptions.add("Accessory2"); + Curve2SourceEnumOptions.add("Accessory3"); + Curve2SourceEnumOptions.add("Accessory4"); + Curve2SourceEnumOptions.add("Accessory5"); + fields.add( new UAVObjectField("Curve2Source", "", UAVObjectField.FieldType.ENUM, Curve2SourceElemNames, Curve2SourceEnumOptions) ); + List Mixer1TypeElemNames = new ArrayList(); Mixer1TypeElemNames.add("0"); List Mixer1TypeEnumOptions = new ArrayList(); Mixer1TypeEnumOptions.add("Disabled"); Mixer1TypeEnumOptions.add("Motor"); Mixer1TypeEnumOptions.add("Servo"); + Mixer1TypeEnumOptions.add("CameraRoll"); + Mixer1TypeEnumOptions.add("CameraPitch"); + Mixer1TypeEnumOptions.add("CameraYaw"); + Mixer1TypeEnumOptions.add("Accessory0"); + Mixer1TypeEnumOptions.add("Accessory1"); + Mixer1TypeEnumOptions.add("Accessory2"); + Mixer1TypeEnumOptions.add("Accessory3"); + Mixer1TypeEnumOptions.add("Accessory4"); + Mixer1TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer1Type", "", UAVObjectField.FieldType.ENUM, Mixer1TypeElemNames, Mixer1TypeEnumOptions) ); List Mixer1VectorElemNames = new ArrayList(); @@ -105,6 +130,15 @@ public class MixerSettings extends UAVDataObject { Mixer2TypeEnumOptions.add("Disabled"); Mixer2TypeEnumOptions.add("Motor"); Mixer2TypeEnumOptions.add("Servo"); + Mixer2TypeEnumOptions.add("CameraRoll"); + Mixer2TypeEnumOptions.add("CameraPitch"); + Mixer2TypeEnumOptions.add("CameraYaw"); + Mixer2TypeEnumOptions.add("Accessory0"); + Mixer2TypeEnumOptions.add("Accessory1"); + Mixer2TypeEnumOptions.add("Accessory2"); + Mixer2TypeEnumOptions.add("Accessory3"); + Mixer2TypeEnumOptions.add("Accessory4"); + Mixer2TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer2Type", "", UAVObjectField.FieldType.ENUM, Mixer2TypeElemNames, Mixer2TypeEnumOptions) ); List Mixer2VectorElemNames = new ArrayList(); @@ -121,6 +155,15 @@ public class MixerSettings extends UAVDataObject { Mixer3TypeEnumOptions.add("Disabled"); Mixer3TypeEnumOptions.add("Motor"); Mixer3TypeEnumOptions.add("Servo"); + Mixer3TypeEnumOptions.add("CameraRoll"); + Mixer3TypeEnumOptions.add("CameraPitch"); + Mixer3TypeEnumOptions.add("CameraYaw"); + Mixer3TypeEnumOptions.add("Accessory0"); + Mixer3TypeEnumOptions.add("Accessory1"); + Mixer3TypeEnumOptions.add("Accessory2"); + Mixer3TypeEnumOptions.add("Accessory3"); + Mixer3TypeEnumOptions.add("Accessory4"); + Mixer3TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer3Type", "", UAVObjectField.FieldType.ENUM, Mixer3TypeElemNames, Mixer3TypeEnumOptions) ); List Mixer3VectorElemNames = new ArrayList(); @@ -137,6 +180,15 @@ public class MixerSettings extends UAVDataObject { Mixer4TypeEnumOptions.add("Disabled"); Mixer4TypeEnumOptions.add("Motor"); Mixer4TypeEnumOptions.add("Servo"); + Mixer4TypeEnumOptions.add("CameraRoll"); + Mixer4TypeEnumOptions.add("CameraPitch"); + Mixer4TypeEnumOptions.add("CameraYaw"); + Mixer4TypeEnumOptions.add("Accessory0"); + Mixer4TypeEnumOptions.add("Accessory1"); + Mixer4TypeEnumOptions.add("Accessory2"); + Mixer4TypeEnumOptions.add("Accessory3"); + Mixer4TypeEnumOptions.add("Accessory4"); + Mixer4TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer4Type", "", UAVObjectField.FieldType.ENUM, Mixer4TypeElemNames, Mixer4TypeEnumOptions) ); List Mixer4VectorElemNames = new ArrayList(); @@ -153,6 +205,15 @@ public class MixerSettings extends UAVDataObject { Mixer5TypeEnumOptions.add("Disabled"); Mixer5TypeEnumOptions.add("Motor"); Mixer5TypeEnumOptions.add("Servo"); + Mixer5TypeEnumOptions.add("CameraRoll"); + Mixer5TypeEnumOptions.add("CameraPitch"); + Mixer5TypeEnumOptions.add("CameraYaw"); + Mixer5TypeEnumOptions.add("Accessory0"); + Mixer5TypeEnumOptions.add("Accessory1"); + Mixer5TypeEnumOptions.add("Accessory2"); + Mixer5TypeEnumOptions.add("Accessory3"); + Mixer5TypeEnumOptions.add("Accessory4"); + Mixer5TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer5Type", "", UAVObjectField.FieldType.ENUM, Mixer5TypeElemNames, Mixer5TypeEnumOptions) ); List Mixer5VectorElemNames = new ArrayList(); @@ -169,6 +230,15 @@ public class MixerSettings extends UAVDataObject { Mixer6TypeEnumOptions.add("Disabled"); Mixer6TypeEnumOptions.add("Motor"); Mixer6TypeEnumOptions.add("Servo"); + Mixer6TypeEnumOptions.add("CameraRoll"); + Mixer6TypeEnumOptions.add("CameraPitch"); + Mixer6TypeEnumOptions.add("CameraYaw"); + Mixer6TypeEnumOptions.add("Accessory0"); + Mixer6TypeEnumOptions.add("Accessory1"); + Mixer6TypeEnumOptions.add("Accessory2"); + Mixer6TypeEnumOptions.add("Accessory3"); + Mixer6TypeEnumOptions.add("Accessory4"); + Mixer6TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer6Type", "", UAVObjectField.FieldType.ENUM, Mixer6TypeElemNames, Mixer6TypeEnumOptions) ); List Mixer6VectorElemNames = new ArrayList(); @@ -185,6 +255,15 @@ public class MixerSettings extends UAVDataObject { Mixer7TypeEnumOptions.add("Disabled"); Mixer7TypeEnumOptions.add("Motor"); Mixer7TypeEnumOptions.add("Servo"); + Mixer7TypeEnumOptions.add("CameraRoll"); + Mixer7TypeEnumOptions.add("CameraPitch"); + Mixer7TypeEnumOptions.add("CameraYaw"); + Mixer7TypeEnumOptions.add("Accessory0"); + Mixer7TypeEnumOptions.add("Accessory1"); + Mixer7TypeEnumOptions.add("Accessory2"); + Mixer7TypeEnumOptions.add("Accessory3"); + Mixer7TypeEnumOptions.add("Accessory4"); + Mixer7TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer7Type", "", UAVObjectField.FieldType.ENUM, Mixer7TypeElemNames, Mixer7TypeEnumOptions) ); List Mixer7VectorElemNames = new ArrayList(); @@ -201,6 +280,15 @@ public class MixerSettings extends UAVDataObject { Mixer8TypeEnumOptions.add("Disabled"); Mixer8TypeEnumOptions.add("Motor"); Mixer8TypeEnumOptions.add("Servo"); + Mixer8TypeEnumOptions.add("CameraRoll"); + Mixer8TypeEnumOptions.add("CameraPitch"); + Mixer8TypeEnumOptions.add("CameraYaw"); + Mixer8TypeEnumOptions.add("Accessory0"); + Mixer8TypeEnumOptions.add("Accessory1"); + Mixer8TypeEnumOptions.add("Accessory2"); + Mixer8TypeEnumOptions.add("Accessory3"); + Mixer8TypeEnumOptions.add("Accessory4"); + Mixer8TypeEnumOptions.add("Accessory5"); fields.add( new UAVObjectField("Mixer8Type", "", UAVObjectField.FieldType.ENUM, Mixer8TypeElemNames, Mixer8TypeEnumOptions) ); List Mixer8VectorElemNames = new ArrayList(); @@ -211,6 +299,56 @@ public class MixerSettings extends UAVDataObject { Mixer8VectorElemNames.add("Yaw"); fields.add( new UAVObjectField("Mixer8Vector", "", UAVObjectField.FieldType.INT8, Mixer8VectorElemNames, null) ); + List Mixer9TypeElemNames = new ArrayList(); + Mixer9TypeElemNames.add("0"); + List Mixer9TypeEnumOptions = new ArrayList(); + Mixer9TypeEnumOptions.add("Disabled"); + Mixer9TypeEnumOptions.add("Motor"); + Mixer9TypeEnumOptions.add("Servo"); + Mixer9TypeEnumOptions.add("CameraRoll"); + Mixer9TypeEnumOptions.add("CameraPitch"); + Mixer9TypeEnumOptions.add("CameraYaw"); + Mixer9TypeEnumOptions.add("Accessory0"); + Mixer9TypeEnumOptions.add("Accessory1"); + Mixer9TypeEnumOptions.add("Accessory2"); + Mixer9TypeEnumOptions.add("Accessory3"); + Mixer9TypeEnumOptions.add("Accessory4"); + Mixer9TypeEnumOptions.add("Accessory5"); + fields.add( new UAVObjectField("Mixer9Type", "", UAVObjectField.FieldType.ENUM, Mixer9TypeElemNames, Mixer9TypeEnumOptions) ); + + List Mixer9VectorElemNames = new ArrayList(); + Mixer9VectorElemNames.add("ThrottleCurve1"); + Mixer9VectorElemNames.add("ThrottleCurve2"); + Mixer9VectorElemNames.add("Roll"); + Mixer9VectorElemNames.add("Pitch"); + Mixer9VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer9Vector", "", UAVObjectField.FieldType.INT8, Mixer9VectorElemNames, null) ); + + List Mixer10TypeElemNames = new ArrayList(); + Mixer10TypeElemNames.add("0"); + List Mixer10TypeEnumOptions = new ArrayList(); + Mixer10TypeEnumOptions.add("Disabled"); + Mixer10TypeEnumOptions.add("Motor"); + Mixer10TypeEnumOptions.add("Servo"); + Mixer10TypeEnumOptions.add("CameraRoll"); + Mixer10TypeEnumOptions.add("CameraPitch"); + Mixer10TypeEnumOptions.add("CameraYaw"); + Mixer10TypeEnumOptions.add("Accessory0"); + Mixer10TypeEnumOptions.add("Accessory1"); + Mixer10TypeEnumOptions.add("Accessory2"); + Mixer10TypeEnumOptions.add("Accessory3"); + Mixer10TypeEnumOptions.add("Accessory4"); + Mixer10TypeEnumOptions.add("Accessory5"); + fields.add( new UAVObjectField("Mixer10Type", "", UAVObjectField.FieldType.ENUM, Mixer10TypeElemNames, Mixer10TypeEnumOptions) ); + + List Mixer10VectorElemNames = new ArrayList(); + Mixer10VectorElemNames.add("ThrottleCurve1"); + Mixer10VectorElemNames.add("ThrottleCurve2"); + Mixer10VectorElemNames.add("Roll"); + Mixer10VectorElemNames.add("Pitch"); + Mixer10VectorElemNames.add("Yaw"); + fields.add( new UAVObjectField("Mixer10Vector", "", UAVObjectField.FieldType.INT8, Mixer10VectorElemNames, null) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -261,15 +399,16 @@ public class MixerSettings extends UAVDataObject { getField("AccelTime").setValue(0); getField("DecelTime").setValue(0); getField("ThrottleCurve1").setValue(0,0); - getField("ThrottleCurve1").setValue(0.25,1); - getField("ThrottleCurve1").setValue(0.5,2); - getField("ThrottleCurve1").setValue(0.75,3); - getField("ThrottleCurve1").setValue(1,4); + getField("ThrottleCurve1").setValue(0,1); + getField("ThrottleCurve1").setValue(0,2); + getField("ThrottleCurve1").setValue(0,3); + getField("ThrottleCurve1").setValue(0,4); getField("ThrottleCurve2").setValue(0,0); getField("ThrottleCurve2").setValue(0.25,1); getField("ThrottleCurve2").setValue(0.5,2); getField("ThrottleCurve2").setValue(0.75,3); getField("ThrottleCurve2").setValue(1,4); + getField("Curve2Source").setValue("Throttle"); getField("Mixer1Type").setValue("Disabled"); getField("Mixer1Vector").setValue(0,0); getField("Mixer1Vector").setValue(0,1); @@ -318,6 +457,18 @@ public class MixerSettings extends UAVDataObject { getField("Mixer8Vector").setValue(0,2); getField("Mixer8Vector").setValue(0,3); getField("Mixer8Vector").setValue(0,4); + getField("Mixer9Type").setValue("Disabled"); + getField("Mixer9Vector").setValue(0,0); + getField("Mixer9Vector").setValue(0,1); + getField("Mixer9Vector").setValue(0,2); + getField("Mixer9Vector").setValue(0,3); + getField("Mixer9Vector").setValue(0,4); + getField("Mixer10Type").setValue("Disabled"); + getField("Mixer10Vector").setValue(0,0); + getField("Mixer10Vector").setValue(0,1); + getField("Mixer10Vector").setValue(0,2); + getField("Mixer10Vector").setValue(0,3); + getField("Mixer10Vector").setValue(0,4); } @@ -346,7 +497,7 @@ public class MixerSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x4FAE374E; + protected static final int OBJID = 0x5D16D6C4; protected static final String NAME = "MixerSettings"; protected static String DESCRIPTION = "Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java index fbd405b40..106220a8c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java @@ -156,7 +156,7 @@ public class MixerStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0xF6A33F10; + protected static final int OBJID = 0x11CFB4E6; protected static final String NAME = "MixerStatus"; protected static String DESCRIPTION = "Status for the matrix mixer showing the output of each mixer after all scaling"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java index f16ddd199..3b09dd1f8 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java @@ -136,7 +136,7 @@ public class NedAccel extends UAVDataObject { } // Constants - protected static final int OBJID = 0x8E852CE8; + protected static final int OBJID = 0x7C7F5BC0; protected static final String NAME = "NedAccel"; protected static String DESCRIPTION = "The projection of acceleration in the NED reference frame used by @ref Guidance."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java index 2a09c2b40..dccd85d36 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java @@ -51,12 +51,23 @@ public class ObjectPersistence extends UAVDataObject { List fields = new ArrayList(); + List ObjectIDElemNames = new ArrayList(); + ObjectIDElemNames.add("0"); + fields.add( new UAVObjectField("ObjectID", "", UAVObjectField.FieldType.UINT32, ObjectIDElemNames, null) ); + + List InstanceIDElemNames = new ArrayList(); + InstanceIDElemNames.add("0"); + fields.add( new UAVObjectField("InstanceID", "", UAVObjectField.FieldType.UINT32, InstanceIDElemNames, null) ); + List OperationElemNames = new ArrayList(); OperationElemNames.add("0"); List OperationEnumOptions = new ArrayList(); + OperationEnumOptions.add("NOP"); OperationEnumOptions.add("Load"); OperationEnumOptions.add("Save"); OperationEnumOptions.add("Delete"); + OperationEnumOptions.add("FullErase"); + OperationEnumOptions.add("Completed"); fields.add( new UAVObjectField("Operation", "", UAVObjectField.FieldType.ENUM, OperationElemNames, OperationEnumOptions) ); List SelectionElemNames = new ArrayList(); @@ -68,14 +79,6 @@ public class ObjectPersistence extends UAVDataObject { SelectionEnumOptions.add("AllObjects"); fields.add( new UAVObjectField("Selection", "", UAVObjectField.FieldType.ENUM, SelectionElemNames, SelectionEnumOptions) ); - List ObjectIDElemNames = new ArrayList(); - ObjectIDElemNames.add("0"); - fields.add( new UAVObjectField("ObjectID", "", UAVObjectField.FieldType.UINT32, ObjectIDElemNames, null) ); - - List InstanceIDElemNames = new ArrayList(); - InstanceIDElemNames.add("0"); - fields.add( new UAVObjectField("InstanceID", "", UAVObjectField.FieldType.UINT32, InstanceIDElemNames, null) ); - // Compute the number of bytes for this object int numBytes = 0; @@ -106,7 +109,7 @@ public class ObjectPersistence extends UAVDataObject { metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; metadata.flightTelemetryUpdatePeriod = 0; metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; @@ -149,7 +152,7 @@ public class ObjectPersistence extends UAVDataObject { } // Constants - protected static final int OBJID = 0x22216832; + protected static final int OBJID = 0xF69AD8B8; protected static final String NAME = "ObjectPersistence"; protected static String DESCRIPTION = "Someone who knows please enter this"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java index 444009f90..ac30ad4f5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java @@ -136,7 +136,7 @@ public class PositionActual extends UAVDataObject { } // Constants - protected static final int OBJID = 0xE0739636; + protected static final int OBJID = 0xF9691DA4; protected static final String NAME = "PositionActual"; protected static String DESCRIPTION = "Contains the current position relative to @ref HomeLocation"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java index 5cf51df71..2ff5a5586 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java @@ -136,7 +136,7 @@ public class PositionDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0x2FC4E5BA; + protected static final int OBJID = 0x33C9EAB4; protected static final String NAME = "PositionDesired"; protected static String DESCRIPTION = "The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner "; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java index 7164c0957..ddeacd8d4 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java @@ -136,7 +136,7 @@ public class RateDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0xBA41B51C; + protected static final int OBJID = 0xCE8C826; protected static final String NAME = "RateDesired"; protected static String DESCRIPTION = "Status for the matrix mixer showing the output of each mixer after all scaling"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java similarity index 61% rename from androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java rename to androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java index 6af673930..a40b27e38 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BatterySettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java @@ -5,7 +5,7 @@ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief Template for an uavobject in java * This is a autogenerated file!! Do not modify and expect a result. - * Battery configuration information. + * Monitors which receiver channels have been active within the last second. * * @see The GNU Public License (GPL) Version 3 * @@ -39,40 +39,33 @@ import org.openpilot.uavtalk.UAVDataObject; import org.openpilot.uavtalk.UAVObjectField; /** -Battery configuration information. +Monitors which receiver channels have been active within the last second. -generated from batterysettings.xml +generated from receiveractivity.xml **/ -public class BatterySettings extends UAVDataObject { +public class ReceiverActivity extends UAVDataObject { - public BatterySettings() { + public ReceiverActivity() { super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); List fields = new ArrayList(); - List BatteryVoltageElemNames = new ArrayList(); - BatteryVoltageElemNames.add("0"); - fields.add( new UAVObjectField("BatteryVoltage", "V", UAVObjectField.FieldType.FLOAT32, BatteryVoltageElemNames, null) ); + List ActiveGroupElemNames = new ArrayList(); + ActiveGroupElemNames.add("0"); + List ActiveGroupEnumOptions = new ArrayList(); + ActiveGroupEnumOptions.add("PWM"); + ActiveGroupEnumOptions.add("PPM"); + ActiveGroupEnumOptions.add("DSM (MainPort)"); + ActiveGroupEnumOptions.add("DSM (FlexiPort)"); + ActiveGroupEnumOptions.add("S.Bus"); + ActiveGroupEnumOptions.add("GCS"); + ActiveGroupEnumOptions.add("None"); + fields.add( new UAVObjectField("ActiveGroup", "Channel Group", UAVObjectField.FieldType.ENUM, ActiveGroupElemNames, ActiveGroupEnumOptions) ); - List BatteryCapacityElemNames = new ArrayList(); - BatteryCapacityElemNames.add("0"); - fields.add( new UAVObjectField("BatteryCapacity", "mAh", UAVObjectField.FieldType.UINT32, BatteryCapacityElemNames, null) ); - - List BatteryTypeElemNames = new ArrayList(); - BatteryTypeElemNames.add("0"); - List BatteryTypeEnumOptions = new ArrayList(); - BatteryTypeEnumOptions.add("LiPo"); - BatteryTypeEnumOptions.add("A123"); - BatteryTypeEnumOptions.add("LiCo"); - BatteryTypeEnumOptions.add("LiFeSO4"); - BatteryTypeEnumOptions.add("None"); - fields.add( new UAVObjectField("BatteryType", "", UAVObjectField.FieldType.ENUM, BatteryTypeElemNames, BatteryTypeEnumOptions) ); - - List CalibrationsElemNames = new ArrayList(); - CalibrationsElemNames.add("Voltage"); - CalibrationsElemNames.add("Current"); - fields.add( new UAVObjectField("Calibrations", "", UAVObjectField.FieldType.FLOAT32, CalibrationsElemNames, null) ); + List ActiveChannelElemNames = new ArrayList(); + ActiveChannelElemNames.add("0"); + fields.add( new UAVObjectField("ActiveChannel", "channel", UAVObjectField.FieldType.UINT8, ActiveChannelElemNames, null) ); // Compute the number of bytes for this object @@ -97,13 +90,13 @@ public class BatterySettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READONLY; + metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; + metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; metadata.gcsTelemetryUpdatePeriod = 0; metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; + metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; metadata.flightTelemetryUpdatePeriod = 0; @@ -119,11 +112,8 @@ public class BatterySettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("BatteryVoltage").setValue(11.1); - getField("BatteryCapacity").setValue(2200); - getField("BatteryType").setValue("LiPo"); - getField("Calibrations").setValue(1,0); - getField("Calibrations").setValue(1,1); + getField("ActiveGroup").setValue("None"); + getField("ActiveChannel").setValue(255); } @@ -135,7 +125,7 @@ public class BatterySettings extends UAVDataObject { public UAVDataObject clone(int instID) { // TODO: Need to get specific instance to clone try { - BatterySettings obj = new BatterySettings(); + ReceiverActivity obj = new ReceiverActivity(); obj.initialize(instID, this.getMetaObject()); return obj; } catch (Exception e) { @@ -146,17 +136,17 @@ public class BatterySettings extends UAVDataObject { /** * Static function to retrieve an instance of the object. */ - public BatterySettings GetInstance(UAVObjectManager objMngr, int instID) + public ReceiverActivity GetInstance(UAVObjectManager objMngr, int instID) { - return (BatterySettings)(objMngr.getObject(BatterySettings.OBJID, instID)); + return (ReceiverActivity)(objMngr.getObject(ReceiverActivity.OBJID, instID)); } // Constants - protected static final int OBJID = 0xA5FF1D9A; - protected static final String NAME = "BatterySettings"; - protected static String DESCRIPTION = "Battery configuration information."; + protected static final int OBJID = 0x1E7C53DA; + protected static final String NAME = "ReceiverActivity"; + protected static String DESCRIPTION = "Monitors which receiver channels have been active within the last second."; protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; protected static int NUMBYTES = 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java index 4e9f0b8b8..18cf6f4d6 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java @@ -128,7 +128,7 @@ public class SonarAltitude extends UAVDataObject { } // Constants - protected static final int OBJID = 0x1FDD844C; + protected static final int OBJID = 0x6C5A0CBC; protected static final String NAME = "SonarAltitude"; protected static String DESCRIPTION = "The raw data from the ultrasound sonar sensor with altitude estimate."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java index 8cba8a54c..32d2c735c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java @@ -75,6 +75,8 @@ public class StabilizationDesired extends UAVDataObject { StabilizationModeEnumOptions.add("None"); StabilizationModeEnumOptions.add("Rate"); StabilizationModeEnumOptions.add("Attitude"); + StabilizationModeEnumOptions.add("AxisLock"); + StabilizationModeEnumOptions.add("WeakLeveling"); fields.add( new UAVObjectField("StabilizationMode", "", UAVObjectField.FieldType.ENUM, StabilizationModeElemNames, StabilizationModeEnumOptions) ); @@ -150,7 +152,7 @@ public class StabilizationDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0x41AA9DC2; + protected static final int OBJID = 0xDB8FFC3C; protected static final String NAME = "StabilizationDesired"; protected static String DESCRIPTION = "The desired attitude that @ref StabilizationModule will try and achieve if FlightMode is Stabilized. Comes from @ref ManaulControlModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java index 74c480e1c..ab78bdc74 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java @@ -51,18 +51,6 @@ public class StabilizationSettings extends UAVDataObject { List fields = new ArrayList(); - List RollMaxElemNames = new ArrayList(); - RollMaxElemNames.add("0"); - fields.add( new UAVObjectField("RollMax", "degrees", UAVObjectField.FieldType.UINT8, RollMaxElemNames, null) ); - - List PitchMaxElemNames = new ArrayList(); - PitchMaxElemNames.add("0"); - fields.add( new UAVObjectField("PitchMax", "degrees", UAVObjectField.FieldType.UINT8, PitchMaxElemNames, null) ); - - List YawMaxElemNames = new ArrayList(); - YawMaxElemNames.add("0"); - fields.add( new UAVObjectField("YawMax", "degrees", UAVObjectField.FieldType.UINT8, YawMaxElemNames, null) ); - List ManualRateElemNames = new ArrayList(); ManualRateElemNames.add("Roll"); ManualRateElemNames.add("Pitch"); @@ -75,23 +63,26 @@ public class StabilizationSettings extends UAVDataObject { MaximumRateElemNames.add("Yaw"); fields.add( new UAVObjectField("MaximumRate", "degrees/sec", UAVObjectField.FieldType.FLOAT32, MaximumRateElemNames, null) ); - List RollRatePIElemNames = new ArrayList(); - RollRatePIElemNames.add("Kp"); - RollRatePIElemNames.add("Ki"); - RollRatePIElemNames.add("ILimit"); - fields.add( new UAVObjectField("RollRatePI", "", UAVObjectField.FieldType.FLOAT32, RollRatePIElemNames, null) ); + List RollRatePIDElemNames = new ArrayList(); + RollRatePIDElemNames.add("Kp"); + RollRatePIDElemNames.add("Ki"); + RollRatePIDElemNames.add("Kd"); + RollRatePIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("RollRatePID", "", UAVObjectField.FieldType.FLOAT32, RollRatePIDElemNames, null) ); - List PitchRatePIElemNames = new ArrayList(); - PitchRatePIElemNames.add("Kp"); - PitchRatePIElemNames.add("Ki"); - PitchRatePIElemNames.add("ILimit"); - fields.add( new UAVObjectField("PitchRatePI", "", UAVObjectField.FieldType.FLOAT32, PitchRatePIElemNames, null) ); + List PitchRatePIDElemNames = new ArrayList(); + PitchRatePIDElemNames.add("Kp"); + PitchRatePIDElemNames.add("Ki"); + PitchRatePIDElemNames.add("Kd"); + PitchRatePIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("PitchRatePID", "", UAVObjectField.FieldType.FLOAT32, PitchRatePIDElemNames, null) ); - List YawRatePIElemNames = new ArrayList(); - YawRatePIElemNames.add("Kp"); - YawRatePIElemNames.add("Ki"); - YawRatePIElemNames.add("ILimit"); - fields.add( new UAVObjectField("YawRatePI", "", UAVObjectField.FieldType.FLOAT32, YawRatePIElemNames, null) ); + List YawRatePIDElemNames = new ArrayList(); + YawRatePIDElemNames.add("Kp"); + YawRatePIDElemNames.add("Ki"); + YawRatePIDElemNames.add("Kd"); + YawRatePIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("YawRatePID", "", UAVObjectField.FieldType.FLOAT32, YawRatePIDElemNames, null) ); List RollPIElemNames = new ArrayList(); RollPIElemNames.add("Kp"); @@ -111,6 +102,45 @@ public class StabilizationSettings extends UAVDataObject { YawPIElemNames.add("ILimit"); fields.add( new UAVObjectField("YawPI", "", UAVObjectField.FieldType.FLOAT32, YawPIElemNames, null) ); + List GyroTauElemNames = new ArrayList(); + GyroTauElemNames.add("0"); + fields.add( new UAVObjectField("GyroTau", "", UAVObjectField.FieldType.FLOAT32, GyroTauElemNames, null) ); + + List WeakLevelingKpElemNames = new ArrayList(); + WeakLevelingKpElemNames.add("0"); + fields.add( new UAVObjectField("WeakLevelingKp", "(deg/s)/deg", UAVObjectField.FieldType.FLOAT32, WeakLevelingKpElemNames, null) ); + + List RollMaxElemNames = new ArrayList(); + RollMaxElemNames.add("0"); + fields.add( new UAVObjectField("RollMax", "degrees", UAVObjectField.FieldType.UINT8, RollMaxElemNames, null) ); + + List PitchMaxElemNames = new ArrayList(); + PitchMaxElemNames.add("0"); + fields.add( new UAVObjectField("PitchMax", "degrees", UAVObjectField.FieldType.UINT8, PitchMaxElemNames, null) ); + + List YawMaxElemNames = new ArrayList(); + YawMaxElemNames.add("0"); + fields.add( new UAVObjectField("YawMax", "degrees", UAVObjectField.FieldType.UINT8, YawMaxElemNames, null) ); + + List MaxAxisLockElemNames = new ArrayList(); + MaxAxisLockElemNames.add("0"); + fields.add( new UAVObjectField("MaxAxisLock", "deg", UAVObjectField.FieldType.UINT8, MaxAxisLockElemNames, null) ); + + List MaxAxisLockRateElemNames = new ArrayList(); + MaxAxisLockRateElemNames.add("0"); + fields.add( new UAVObjectField("MaxAxisLockRate", "deg/s", UAVObjectField.FieldType.UINT8, MaxAxisLockRateElemNames, null) ); + + List MaxWeakLevelingRateElemNames = new ArrayList(); + MaxWeakLevelingRateElemNames.add("0"); + fields.add( new UAVObjectField("MaxWeakLevelingRate", "deg/s", UAVObjectField.FieldType.UINT8, MaxWeakLevelingRateElemNames, null) ); + + List LowThrottleZeroIntegralElemNames = new ArrayList(); + LowThrottleZeroIntegralElemNames.add("0"); + List LowThrottleZeroIntegralEnumOptions = new ArrayList(); + LowThrottleZeroIntegralEnumOptions.add("FALSE"); + LowThrottleZeroIntegralEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("LowThrottleZeroIntegral", "", UAVObjectField.FieldType.ENUM, LowThrottleZeroIntegralElemNames, LowThrottleZeroIntegralEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -156,24 +186,24 @@ public class StabilizationSettings extends UAVDataObject { */ public void setDefaultFieldValues() { - getField("RollMax").setValue(35); - getField("PitchMax").setValue(35); - getField("YawMax").setValue(35); getField("ManualRate").setValue(150,0); getField("ManualRate").setValue(150,1); getField("ManualRate").setValue(150,2); getField("MaximumRate").setValue(300,0); getField("MaximumRate").setValue(300,1); getField("MaximumRate").setValue(300,2); - getField("RollRatePI").setValue(0.0015,0); - getField("RollRatePI").setValue(0,1); - getField("RollRatePI").setValue(0.3,2); - getField("PitchRatePI").setValue(0.0015,0); - getField("PitchRatePI").setValue(0,1); - getField("PitchRatePI").setValue(0.3,2); - getField("YawRatePI").setValue(0.003,0); - getField("YawRatePI").setValue(0,1); - getField("YawRatePI").setValue(0.3,2); + getField("RollRatePID").setValue(0.002,0); + getField("RollRatePID").setValue(0,1); + getField("RollRatePID").setValue(0,2); + getField("RollRatePID").setValue(0.3,3); + getField("PitchRatePID").setValue(0.002,0); + getField("PitchRatePID").setValue(0,1); + getField("PitchRatePID").setValue(0,2); + getField("PitchRatePID").setValue(0.3,3); + getField("YawRatePID").setValue(0.0035,0); + getField("YawRatePID").setValue(0.0035,1); + getField("YawRatePID").setValue(0,2); + getField("YawRatePID").setValue(0.3,3); getField("RollPI").setValue(2,0); getField("RollPI").setValue(0,1); getField("RollPI").setValue(50,2); @@ -183,6 +213,15 @@ public class StabilizationSettings extends UAVDataObject { getField("YawPI").setValue(2,0); getField("YawPI").setValue(0,1); getField("YawPI").setValue(50,2); + getField("GyroTau").setValue(0.005); + getField("WeakLevelingKp").setValue(0.1); + getField("RollMax").setValue(55); + getField("PitchMax").setValue(55); + getField("YawMax").setValue(35); + getField("MaxAxisLock").setValue(15); + getField("MaxAxisLockRate").setValue(2); + getField("MaxWeakLevelingRate").setValue(5); + getField("LowThrottleZeroIntegral").setValue("TRUE"); } @@ -211,7 +250,7 @@ public class StabilizationSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0xE2147404; + protected static final int OBJID = 0x5F78C51E; protected static final String NAME = "StabilizationSettings"; protected static String DESCRIPTION = "PID settings used by the Stabilization module to combine the @ref AttitudeActual and @ref AttitudeDesired to compute @ref ActuatorDesired"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java index e9313472c..458dd9d10 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java @@ -68,6 +68,7 @@ public class SystemAlarms extends UAVDataObject { AlarmElemNames.add("FlightTime"); AlarmElemNames.add("I2C"); AlarmElemNames.add("GPS"); + AlarmElemNames.add("BootFault"); List AlarmEnumOptions = new ArrayList(); AlarmEnumOptions.add("Uninitialised"); AlarmEnumOptions.add("OK"); @@ -106,8 +107,8 @@ public class SystemAlarms extends UAVDataObject { metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 4000; + metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + metadata.flightTelemetryUpdatePeriod = 0; metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; metadata.loggingUpdatePeriod = 1000; @@ -137,6 +138,7 @@ public class SystemAlarms extends UAVDataObject { getField("Alarm").setValue("Uninitialised",13); getField("Alarm").setValue("Uninitialised",14); getField("Alarm").setValue("Uninitialised",15); + getField("Alarm").setValue("Uninitialised",16); } @@ -165,7 +167,7 @@ public class SystemAlarms extends UAVDataObject { } // Constants - protected static final int OBJID = 0x89C3DCB2; + protected static final int OBJID = 0x737ADCF2; protected static final String NAME = "SystemAlarms"; protected static String DESCRIPTION = "Alarms from OpenPilot to indicate failure conditions or warnings. Set by various modules."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java index 99bceb6ba..e3c2cf0b0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java @@ -51,6 +51,11 @@ public class SystemSettings extends UAVDataObject { List fields = new ArrayList(); + List GUIConfigDataElemNames = new ArrayList(); + GUIConfigDataElemNames.add("0"); + GUIConfigDataElemNames.add("1"); + fields.add( new UAVObjectField("GUIConfigData", "bits", UAVObjectField.FieldType.UINT32, GUIConfigDataElemNames, null) ); + List AirframeTypeElemNames = new ArrayList(); AirframeTypeElemNames.add("0"); List AirframeTypeEnumOptions = new ArrayList(); @@ -117,6 +122,8 @@ public class SystemSettings extends UAVDataObject { */ public void setDefaultFieldValues() { + getField("GUIConfigData").setValue(0,0); + getField("GUIConfigData").setValue(0,1); getField("AirframeType").setValue("FixedWing"); } @@ -146,7 +153,7 @@ public class SystemSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x3875CEE; + protected static final int OBJID = 0x30BD5D7C; protected static final String NAME = "SystemSettings"; protected static String DESCRIPTION = "Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java index 7c34360e9..d1c51d43f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java @@ -59,6 +59,10 @@ public class SystemStats extends UAVDataObject { HeapRemainingElemNames.add("0"); fields.add( new UAVObjectField("HeapRemaining", "bytes", UAVObjectField.FieldType.UINT16, HeapRemainingElemNames, null) ); + List IRQStackRemainingElemNames = new ArrayList(); + IRQStackRemainingElemNames.add("0"); + fields.add( new UAVObjectField("IRQStackRemaining", "bytes", UAVObjectField.FieldType.UINT16, IRQStackRemainingElemNames, null) ); + List CPULoadElemNames = new ArrayList(); CPULoadElemNames.add("0"); fields.add( new UAVObjectField("CPULoad", "%", UAVObjectField.FieldType.UINT8, CPULoadElemNames, null) ); @@ -140,7 +144,7 @@ public class SystemStats extends UAVDataObject { } // Constants - protected static final int OBJID = 0xAA26FFFA; + protected static final int OBJID = 0xD610A0F0; protected static final String NAME = "SystemStats"; protected static String DESCRIPTION = "CPU and memory usage from OpenPilot computer. "; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java index 3ad065b5c..54825fafe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java @@ -65,6 +65,8 @@ public class TaskInfo extends UAVDataObject { StackRemainingElemNames.add("Stabilization"); StackRemainingElemNames.add("Guidance"); StackRemainingElemNames.add("FlightPlan"); + StackRemainingElemNames.add("Com2UsbBridge"); + StackRemainingElemNames.add("Usb2ComBridge"); fields.add( new UAVObjectField("StackRemaining", "bytes", UAVObjectField.FieldType.UINT16, StackRemainingElemNames, null) ); List RunningElemNames = new ArrayList(); @@ -81,11 +83,31 @@ public class TaskInfo extends UAVDataObject { RunningElemNames.add("Stabilization"); RunningElemNames.add("Guidance"); RunningElemNames.add("FlightPlan"); + RunningElemNames.add("Com2UsbBridge"); + RunningElemNames.add("Usb2ComBridge"); List RunningEnumOptions = new ArrayList(); RunningEnumOptions.add("False"); RunningEnumOptions.add("True"); fields.add( new UAVObjectField("Running", "bool", UAVObjectField.FieldType.ENUM, RunningElemNames, RunningEnumOptions) ); + List RunningTimeElemNames = new ArrayList(); + RunningTimeElemNames.add("System"); + RunningTimeElemNames.add("Actuator"); + RunningTimeElemNames.add("Attitude"); + RunningTimeElemNames.add("TelemetryTx"); + RunningTimeElemNames.add("TelemetryTxPri"); + RunningTimeElemNames.add("TelemetryRx"); + RunningTimeElemNames.add("GPS"); + RunningTimeElemNames.add("ManualControl"); + RunningTimeElemNames.add("Altitude"); + RunningTimeElemNames.add("AHRSComms"); + RunningTimeElemNames.add("Stabilization"); + RunningTimeElemNames.add("Guidance"); + RunningTimeElemNames.add("FlightPlan"); + RunningTimeElemNames.add("Com2UsbBridge"); + RunningTimeElemNames.add("Usb2ComBridge"); + fields.add( new UAVObjectField("RunningTime", "%", UAVObjectField.FieldType.UINT8, RunningTimeElemNames, null) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -159,7 +181,7 @@ public class TaskInfo extends UAVDataObject { } // Constants - protected static final int OBJID = 0x50F599F0; + protected static final int OBJID = 0xE34A7C32; protected static final String NAME = "TaskInfo"; protected static String DESCRIPTION = "Task information"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java index d1d47aebb..c2cf64d49 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java @@ -28,13 +28,14 @@ package org.openpilot.uavtalk.uavobjects; -//import org.openpilot.uavtalk.uavobjects.*; +import org.openpilot.uavtalk.uavobjects.*; import org.openpilot.uavtalk.UAVObjectManager; public class UAVObjectsInitialize { public static void register(UAVObjectManager objMngr) { try { + objMngr.registerObject( new AccessoryDesired() ); objMngr.registerObject( new ActuatorCommand() ); objMngr.registerObject( new ActuatorDesired() ); objMngr.registerObject( new ActuatorSettings() ); @@ -45,19 +46,25 @@ public class UAVObjectsInitialize { objMngr.registerObject( new AttitudeRaw() ); objMngr.registerObject( new AttitudeSettings() ); objMngr.registerObject( new BaroAltitude() ); - objMngr.registerObject( new BatterySettings() ); + objMngr.registerObject( new CameraDesired() ); + objMngr.registerObject( new CameraStabSettings() ); + objMngr.registerObject( new FaultSettings() ); objMngr.registerObject( new FirmwareIAPObj() ); + objMngr.registerObject( new FlightBatterySettings() ); objMngr.registerObject( new FlightBatteryState() ); objMngr.registerObject( new FlightPlanControl() ); objMngr.registerObject( new FlightPlanSettings() ); objMngr.registerObject( new FlightPlanStatus() ); + objMngr.registerObject( new FlightStatus() ); objMngr.registerObject( new FlightTelemetryStats() ); + objMngr.registerObject( new GCSReceiver() ); objMngr.registerObject( new GCSTelemetryStats() ); objMngr.registerObject( new GPSPosition() ); objMngr.registerObject( new GPSSatellites() ); objMngr.registerObject( new GPSTime() ); objMngr.registerObject( new GuidanceSettings() ); objMngr.registerObject( new HomeLocation() ); + objMngr.registerObject( new HwSettings() ); objMngr.registerObject( new I2CStats() ); objMngr.registerObject( new ManualControlCommand() ); objMngr.registerObject( new ManualControlSettings() ); @@ -68,6 +75,7 @@ public class UAVObjectsInitialize { objMngr.registerObject( new PositionActual() ); objMngr.registerObject( new PositionDesired() ); objMngr.registerObject( new RateDesired() ); + objMngr.registerObject( new ReceiverActivity() ); objMngr.registerObject( new SonarAltitude() ); objMngr.registerObject( new StabilizationDesired() ); objMngr.registerObject( new StabilizationSettings() ); @@ -75,7 +83,6 @@ public class UAVObjectsInitialize { objMngr.registerObject( new SystemSettings() ); objMngr.registerObject( new SystemStats() ); objMngr.registerObject( new TaskInfo() ); - objMngr.registerObject( new TelemetrySettings() ); objMngr.registerObject( new VelocityActual() ); objMngr.registerObject( new VelocityDesired() ); objMngr.registerObject( new WatchdogStatus() ); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java index 649e6c122..97d038cfe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java @@ -136,7 +136,7 @@ public class VelocityActual extends UAVDataObject { } // Constants - protected static final int OBJID = 0x48009C88; + protected static final int OBJID = 0x43007EB0; protected static final String NAME = "VelocityActual"; protected static String DESCRIPTION = "Updated by @ref AHRSCommsModule and used within @ref GuidanceModule for velocity control"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java index 27f290898..f39fbd6de 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java @@ -136,7 +136,7 @@ public class VelocityDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0x122F5E3A; + protected static final int OBJID = 0x25139D1A; protected static final String NAME = "VelocityDesired"; protected static String DESCRIPTION = "Used within @ref GuidanceModule to communicate between the task computing the desired velocity and the PID loop to achieve it (running at different rates)."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java index 3adcad96b..acbdb43d1 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java @@ -132,7 +132,7 @@ public class WatchdogStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0xD646E910; + protected static final int OBJID = 0xA207FA7C; protected static final String NAME = "WatchdogStatus"; protected static String DESCRIPTION = "For monitoring the flags in the watchdog and especially the bootup flags"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp index e942b238f..dc593fd5f 100644 --- a/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp +++ b/ground/uavobjgenerator/generators/java/uavobjectgeneratorjava.cpp @@ -258,7 +258,7 @@ bool UAVObjectGeneratorJava::process_object(ObjectInfo* info) outCode.replace(QString("$(INITFIELDS)"), initfields); // Write the java code - bool res = writeFileIfDiffrent( javaOutputPath.absolutePath() + "/" + info->namelc + ".java", outCode ); + bool res = writeFileIfDiffrent( javaOutputPath.absolutePath() + "/" + info->name + ".java", outCode ); if (!res) { cout << "Error: Could not write gcs output files" << endl; return false; From 92764ebc67b4240928dfeef5682442bb534c2ca6 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 5 Apr 2012 23:35:04 -0500 Subject: [PATCH 163/284] Small upgrades to teh android install --- androidgcs/.classpath | 1 + androidgcs/proguard.cfg | 2 +- androidgcs/res/layout/gcs_home.xml | 50 ++++++++---- .../androidgcs/OPTelemetryService.java | 79 ++++++++++++++++++- 4 files changed, 114 insertions(+), 18 deletions(-) diff --git a/androidgcs/.classpath b/androidgcs/.classpath index eb33e4360..c88f96260 100644 --- a/androidgcs/.classpath +++ b/androidgcs/.classpath @@ -5,5 +5,6 @@ + diff --git a/androidgcs/proguard.cfg b/androidgcs/proguard.cfg index 12dd0392c..ec78e7622 100644 --- a/androidgcs/proguard.cfg +++ b/androidgcs/proguard.cfg @@ -14,7 +14,7 @@ -keep public class * extends android.preference.Preference -keep public class com.android.vending.licensing.ILicensingService --keepclasseswithmembernames class * { +-keepclasseswithmembers class * { native ; } diff --git a/androidgcs/res/layout/gcs_home.xml b/androidgcs/res/layout/gcs_home.xml index e07f5b003..0ff427bcd 100644 --- a/androidgcs/res/layout/gcs_home.xml +++ b/androidgcs/res/layout/gcs_home.xml @@ -1,15 +1,37 @@ - - - - + + + + + + + \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index ce90f5a48..bc711560d 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -71,21 +71,25 @@ public class OPTelemetryService extends Service { stopSelf(msg.arg2); break; case MSG_CONNECT: - Toast.makeText(getApplicationContext(), "Attempting connection", Toast.LENGTH_SHORT).show(); terminate = false; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); - //int connection_type = Integer.decode(prefs.getString("connection_type", "")); - int connection_type = 1; + int connection_type = Integer.decode(prefs.getString("connection_type", "")); switch(connection_type) { case 0: // No connection return; case 1: + Toast.makeText(getApplicationContext(), "Attempting fake connection", Toast.LENGTH_SHORT).show(); activeTelem = new FakeTelemetryThread(); break; case 2: + Toast.makeText(getApplicationContext(), "Attempting BT connection", Toast.LENGTH_SHORT).show(); activeTelem = new BTTelemetryThread(); break; case 3: + Toast.makeText(getApplicationContext(), "Attempting TCP connection", Toast.LENGTH_SHORT).show(); + activeTelem = new TcpTelemetryThread(); + break; + default: throw new Error("Unsupported"); } activeTelem.start(); @@ -329,6 +333,75 @@ public class OPTelemetryService extends Service { }; + private class TcpTelemetryThread extends Thread implements TelemTask { + + private UAVObjectManager objMngr; + private UAVTalk uavTalk; + private Telemetry tel; + private TelemetryMonitor mon; + + public UAVObjectManager getObjectManager() { return objMngr; }; + + TcpTelemetryThread() { + objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + } + + public void run() { + if (DEBUG) Log.d(TAG, "Telemetry Thread started"); + + Looper.prepare(); + + TcpUAVTalk tcp = new TcpUAVTalk(OPTelemetryService.this); + for( int i = 0; i < 10; i++ ) { + if (DEBUG) Log.d(TAG, "Attempting network Connection"); + + tcp.connect(objMngr); + + if (DEBUG) Log.d(TAG, "Done attempting connection"); + if( tcp.getConnected() ) + break; + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + Log.e(TAG, "Thread interrupted while trying to connect"); + e.printStackTrace(); + return; + } + } + if( ! tcp.getConnected() ) { + return; + } + + + if (DEBUG) Log.d(TAG, "Connected via network"); + + uavTalk = tcp.getUavtalk(); + tel = new Telemetry(uavTalk, objMngr); + mon = new TelemetryMonitor(objMngr,tel); + mon.addObserver(new Observer() { + public void update(Observable arg0, Object arg1) { + System.out.println("Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated()); + if(mon.getConnected() /*&& mon.getObjectsUpdated()*/) { + Intent intent = new Intent(); + intent.setAction(INTENT_ACTION_CONNECTED); + sendBroadcast(intent,null); + } + } + }); + + + if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop"); + while( !terminate ) { + if( !uavTalk.processInputStream() ) + break; + } + if (DEBUG) Log.d(TAG, "UAVTalk stream disconnected"); + } + + }; + void postNotification(int id, String message) { String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNManager = (NotificationManager) getSystemService(ns); From c1c12ed57e1356e5f16a3452389d89fdcfa91746 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 10:22:38 -0500 Subject: [PATCH 164/284] Add TCP UAVTalk interface for android --- .../org/openpilot/androidgcs/TcpUAVTalk.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java diff --git a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java new file mode 100644 index 000000000..ad503757e --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java @@ -0,0 +1,84 @@ +package org.openpilot.androidgcs; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVTalk; + +import android.content.Context; +import android.util.Log; + +public class TcpUAVTalk { + private final String TAG = "TcpUAVTalk"; + public static int LOGLEVEL = 2; + public static boolean WARN = LOGLEVEL > 1; + public static boolean DEBUG = LOGLEVEL > 0; + + // Temporarily define fixed device name + public final static String IP_ADDRESS = "127.0.0.1"; + public final static int PORT = 9001; + + private UAVTalk uavTalk; + private boolean connected; + + public TcpUAVTalk(Context caller) { + if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + IP_ADDRESS); + + connected = false; + } + + public boolean connect(UAVObjectManager objMngr) { + if( getConnected() ) + return true; + if( !openTelemetryTcp(objMngr) ) + return false; + return true; + } + + public boolean getConnected() { + return connected; + } + + public UAVTalk getUavtalk() { + return uavTalk; + } + + + private boolean openTelemetryTcp(UAVObjectManager objMngr) { + Log.d(TAG, "Opening conncetion to " + IP_ADDRESS); + + InetAddress serverAddr = null; + try { + serverAddr = InetAddress.getByName(IP_ADDRESS); + } catch (UnknownHostException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + return false; + } + + Socket socket = null; + try { + socket = new Socket(serverAddr,PORT); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + return false; + } + + connected = true; + + try { + uavTalk = new UAVTalk(socket.getInputStream(), socket.getOutputStream(), objMngr); + } catch (IOException e) { + Log.e(TAG,"Error starting UAVTalk"); + // TODO Auto-generated catch block + //e.printStackTrace(); + return false; + } + + return true; + } + +} From 9d7c15fb7f625dd928e4a7b4fd1ea040436983cd Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 11:59:50 -0500 Subject: [PATCH 165/284] Enable some debugging statements --- .../org/openpilot/androidgcs/TcpUAVTalk.java | 4 ++-- .../src/org/openpilot/uavtalk/Telemetry.java | 2 +- .../openpilot/uavtalk/TelemetryMonitor.java | 3 ++- .../src/org/openpilot/uavtalk/UAVTalk.java | 18 +++++++++++------- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java index ad503757e..47074f968 100644 --- a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java +++ b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java @@ -17,7 +17,7 @@ public class TcpUAVTalk { public static boolean DEBUG = LOGLEVEL > 0; // Temporarily define fixed device name - public final static String IP_ADDRESS = "127.0.0.1"; + public final static String IP_ADDRESS = "10.21.18.120"; public final static int PORT = 9001; private UAVTalk uavTalk; @@ -47,7 +47,7 @@ public class TcpUAVTalk { private boolean openTelemetryTcp(UAVObjectManager objMngr) { - Log.d(TAG, "Opening conncetion to " + IP_ADDRESS); + Log.d(TAG, "Opening conncetion to " + IP_ADDRESS + " at address " + PORT); InetAddress serverAddr = null; try { diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 1395a5c08..11e6cb2ca 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -17,7 +17,7 @@ import android.util.Log; public class Telemetry { private final String TAG = "Telemetry"; - public static int LOGLEVEL = 0; + public static int LOGLEVEL = 2; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index daedcc85b..903b6b29f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -185,7 +185,8 @@ public class TelemetryMonitor extends Observable{ // Force update if not yet connected gcsStatsObj = objMngr.getObject("GCSTelemetryStats"); flightStatsObj = objMngr.getObject("FlightTelemetryStats"); - + if (DEBUG) Log.d(TAG,"GCS Status: " + gcsStatsObj.getField("Status").getValue()); + if (DEBUG) Log.d(TAG,"Flight Status: " + flightStatsObj.getField("Status").getValue()); if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") != 0 || ((String) flightStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 ) { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 39c1f6ee7..5a3a9a1a5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -12,7 +12,7 @@ import android.util.Log; public class UAVTalk extends Observable { static final String TAG = "UAVTalk"; - public static int LOGLEVEL = 0; + public static int LOGLEVEL = 2; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; @@ -433,6 +433,7 @@ public class UAVTalk extends Observable { rxCSPacket = rxbyte; if (rxCS != rxCSPacket) { // packet error - faulty CRC + if (DEBUG) Log.d(TAG,"Bad crc"); stats.rxErrors++; rxState = RxStateType.STATE_SYNC; break; @@ -441,11 +442,14 @@ public class UAVTalk extends Observable { if (rxPacketLength != (packetSize + 1)) { // packet error - // mismatched packet // size + if (DEBUG) Log.d(TAG,"Bad size"); stats.rxErrors++; rxState = RxStateType.STATE_SYNC; break; } + if (DEBUG) Log.d(TAG,"Received"); + rxBuffer.position(0); receiveObject(rxType, rxObjId, rxInstId, rxBuffer); stats.rxObjectBytes += rxLength; @@ -500,8 +504,8 @@ public class UAVTalk extends Observable { case TYPE_OBJ_ACK: // All instances, not allowed for OBJ_ACK messages if (!allInstances) { - // System.out.println("Received object ack: " + objId + " " + - // objMngr.getObject(objId).getName()); + System.out.println("Received object ack: " + objId + " " + + objMngr.getObject(objId).getName()); // Get object and update its data obj = updateObject(objId, instId, data); // Transmit ACK @@ -517,8 +521,8 @@ public class UAVTalk extends Observable { case TYPE_OBJ_REQ: // Get object, if all instances are requested get instance 0 of the // object - // System.out.println("Received object request: " + objId + " " + - // objMngr.getObject(objId).getName()); + System.out.println("Received object request: " + objId + " " + + objMngr.getObject(objId).getName()); if (allInstances) { obj = objMngr.getObject(objId); } else { @@ -534,8 +538,8 @@ public class UAVTalk extends Observable { case TYPE_ACK: // All instances, not allowed for ACK messages if (!allInstances) { - // System.out.println("Received ack: " + objId + " " + - // objMngr.getObject(objId).getName()); + System.out.println("Received ack: " + objId + " " + + objMngr.getObject(objId).getName()); // Get object obj = objMngr.getObject(objId, instId); // Check if an ack is pending From 097ae637bfa8f2dfe0fd64613c8ba9a6d2cf7eff Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 12:06:36 -0500 Subject: [PATCH 166/284] Remove the TCHAIN_PREFIX flag from the OSX Makefile. No clue how that got merged in. --- flight/Revolution/Makefile.osx | 3 --- 1 file changed, 3 deletions(-) diff --git a/flight/Revolution/Makefile.osx b/flight/Revolution/Makefile.osx index e2c8ea694..a38bced0d 100644 --- a/flight/Revolution/Makefile.osx +++ b/flight/Revolution/Makefile.osx @@ -40,9 +40,6 @@ USE_BOOTLOADER ?= NO # Set to YES when using Code Sourcery toolchain CODE_SOURCERY ?= NO -# Toolchain prefix (i.e arm-elf- -> arm-elf-gcc.exe) -TCHAIN_PREFIX ?= /usr/local/android-ndk-r5/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi- - # Remove command is different for Code Sourcery on Windows REMOVE_CMD ?= rm From 2257bc59531981d37b2330da7b0168e153fef62a Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 14:42:19 -0500 Subject: [PATCH 167/284] Fix an insidious bug in the Android UAVObjectField unpack method for enums that was exposed by shuffling field orders. There goes 5 hours, FML. --- androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 78ad70630..286859e63 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -226,9 +226,9 @@ public class UAVObjectField { } case ENUM: { - List l = (List) data; + List l = (List) this.data; for (int index = 0 ; index < numElements; ++index) { - l.set(index, dataIn.get(index)); + l.set(index, dataIn.get()); } break; } From 902dbd9269799022bd59ca54f29a4507f9773a65 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 14:49:57 -0500 Subject: [PATCH 168/284] Update objects and delete old UAVObjects --- .../uavtalk/uavobjects/AHRSCalibration.java | 252 ------------------ .../uavtalk/uavobjects/AHRSSettings.java | 178 ------------- .../uavtalk/uavobjects/AhrsStatus.java | 201 -------------- .../uavtalk/uavobjects/AttitudeRaw.java | 158 ----------- .../uavtalk/uavobjects/FlightStatus.java | 4 +- .../uavtalk/uavobjects/GuidanceSettings.java | 8 +- .../uavtalk/uavobjects/HomeLocation.java | 32 +-- .../uavtalk/uavobjects/HwSettings.java | 98 +++++-- .../uavobjects/ManualControlSettings.java | 4 +- .../uavtalk/uavobjects/MixerStatus.java | 10 +- .../uavtalk/uavobjects/NedAccel.java | 6 +- .../uavtalk/uavobjects/PositionActual.java | 8 +- .../uavtalk/uavobjects/PositionDesired.java | 8 +- .../uavtalk/uavobjects/SystemAlarms.java | 4 +- .../uavtalk/uavobjects/SystemStats.java | 14 +- .../uavtalk/uavobjects/TaskInfo.java | 17 +- .../uavobjects/UAVObjectsInitialize.java | 18 +- .../uavtalk/uavobjects/VelocityActual.java | 8 +- .../uavtalk/uavobjects/VelocityDesired.java | 8 +- 19 files changed, 153 insertions(+), 883 deletions(-) delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java deleted file mode 100644 index 47d42991e..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSCalibration.java +++ /dev/null @@ -1,252 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * Contains the calibration settings for the @ref AHRSCommsModule - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -Contains the calibration settings for the @ref AHRSCommsModule - -generated from ahrscalibration.xml - **/ -public class AHRSCalibration extends UAVDataObject { - - public AHRSCalibration() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List accel_biasElemNames = new ArrayList(); - accel_biasElemNames.add("X"); - accel_biasElemNames.add("Y"); - accel_biasElemNames.add("Z"); - fields.add( new UAVObjectField("accel_bias", "m/s", UAVObjectField.FieldType.FLOAT32, accel_biasElemNames, null) ); - - List accel_scaleElemNames = new ArrayList(); - accel_scaleElemNames.add("X"); - accel_scaleElemNames.add("Y"); - accel_scaleElemNames.add("Z"); - fields.add( new UAVObjectField("accel_scale", "(m/s)/lsb", UAVObjectField.FieldType.FLOAT32, accel_scaleElemNames, null) ); - - List accel_orthoElemNames = new ArrayList(); - accel_orthoElemNames.add("XY"); - accel_orthoElemNames.add("XZ"); - accel_orthoElemNames.add("YZ"); - fields.add( new UAVObjectField("accel_ortho", "scale", UAVObjectField.FieldType.FLOAT32, accel_orthoElemNames, null) ); - - List accel_varElemNames = new ArrayList(); - accel_varElemNames.add("X"); - accel_varElemNames.add("Y"); - accel_varElemNames.add("Z"); - fields.add( new UAVObjectField("accel_var", "(m/s)^2", UAVObjectField.FieldType.FLOAT32, accel_varElemNames, null) ); - - List gyro_biasElemNames = new ArrayList(); - gyro_biasElemNames.add("X"); - gyro_biasElemNames.add("Y"); - gyro_biasElemNames.add("Z"); - fields.add( new UAVObjectField("gyro_bias", "rad/s", UAVObjectField.FieldType.FLOAT32, gyro_biasElemNames, null) ); - - List gyro_scaleElemNames = new ArrayList(); - gyro_scaleElemNames.add("X"); - gyro_scaleElemNames.add("Y"); - gyro_scaleElemNames.add("Z"); - fields.add( new UAVObjectField("gyro_scale", "(rad/s)/lsb", UAVObjectField.FieldType.FLOAT32, gyro_scaleElemNames, null) ); - - List gyro_varElemNames = new ArrayList(); - gyro_varElemNames.add("X"); - gyro_varElemNames.add("Y"); - gyro_varElemNames.add("Z"); - fields.add( new UAVObjectField("gyro_var", "(rad/s)^2", UAVObjectField.FieldType.FLOAT32, gyro_varElemNames, null) ); - - List gyro_tempcompfactorElemNames = new ArrayList(); - gyro_tempcompfactorElemNames.add("X"); - gyro_tempcompfactorElemNames.add("Y"); - gyro_tempcompfactorElemNames.add("Z"); - fields.add( new UAVObjectField("gyro_tempcompfactor", "raw/raw", UAVObjectField.FieldType.FLOAT32, gyro_tempcompfactorElemNames, null) ); - - List mag_biasElemNames = new ArrayList(); - mag_biasElemNames.add("X"); - mag_biasElemNames.add("Y"); - mag_biasElemNames.add("Z"); - fields.add( new UAVObjectField("mag_bias", "mGau", UAVObjectField.FieldType.FLOAT32, mag_biasElemNames, null) ); - - List mag_scaleElemNames = new ArrayList(); - mag_scaleElemNames.add("X"); - mag_scaleElemNames.add("Y"); - mag_scaleElemNames.add("Z"); - fields.add( new UAVObjectField("mag_scale", "(mGau)/lsb", UAVObjectField.FieldType.FLOAT32, mag_scaleElemNames, null) ); - - List mag_varElemNames = new ArrayList(); - mag_varElemNames.add("X"); - mag_varElemNames.add("Y"); - mag_varElemNames.add("Z"); - fields.add( new UAVObjectField("mag_var", "mGau^2", UAVObjectField.FieldType.FLOAT32, mag_varElemNames, null) ); - - List vel_varElemNames = new ArrayList(); - vel_varElemNames.add("0"); - fields.add( new UAVObjectField("vel_var", "(m/s)^2", UAVObjectField.FieldType.FLOAT32, vel_varElemNames, null) ); - - List pos_varElemNames = new ArrayList(); - pos_varElemNames.add("0"); - fields.add( new UAVObjectField("pos_var", "m^2", UAVObjectField.FieldType.FLOAT32, pos_varElemNames, null) ); - - List measure_varElemNames = new ArrayList(); - measure_varElemNames.add("0"); - List measure_varEnumOptions = new ArrayList(); - measure_varEnumOptions.add("SET"); - measure_varEnumOptions.add("MEASURE"); - fields.add( new UAVObjectField("measure_var", "", UAVObjectField.FieldType.ENUM, measure_varElemNames, measure_varEnumOptions) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - getField("accel_bias").setValue(-73.5,0); - getField("accel_bias").setValue(-73.5,1); - getField("accel_bias").setValue(73.5,2); - getField("accel_scale").setValue(0.0359,0); - getField("accel_scale").setValue(0.0359,1); - getField("accel_scale").setValue(0.0359,2); - getField("accel_ortho").setValue(0,0); - getField("accel_ortho").setValue(0,1); - getField("accel_ortho").setValue(0,2); - getField("accel_var").setValue(0.0005,0); - getField("accel_var").setValue(0.0005,1); - getField("accel_var").setValue(0.0005,2); - getField("gyro_bias").setValue(28,0); - getField("gyro_bias").setValue(-28,1); - getField("gyro_bias").setValue(28,2); - getField("gyro_scale").setValue(-0.017,0); - getField("gyro_scale").setValue(0.017,1); - getField("gyro_scale").setValue(-0.017,2); - getField("gyro_var").setValue(0.0001,0); - getField("gyro_var").setValue(0.0001,1); - getField("gyro_var").setValue(0.0001,2); - getField("gyro_tempcompfactor").setValue(0,0); - getField("gyro_tempcompfactor").setValue(0,1); - getField("gyro_tempcompfactor").setValue(0,2); - getField("mag_bias").setValue(0,0); - getField("mag_bias").setValue(0,1); - getField("mag_bias").setValue(0,2); - getField("mag_scale").setValue(1,0); - getField("mag_scale").setValue(1,1); - getField("mag_scale").setValue(1,2); - getField("mag_var").setValue(50,0); - getField("mag_var").setValue(50,1); - getField("mag_var").setValue(50,2); - getField("vel_var").setValue(10); - getField("pos_var").setValue(0.04); - getField("measure_var").setValue("SET"); - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - AHRSCalibration obj = new AHRSCalibration(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public AHRSCalibration GetInstance(UAVObjectManager objMngr, int instID) - { - return (AHRSCalibration)(objMngr.getObject(AHRSCalibration.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0xFD0EDFC4; - protected static final String NAME = "AHRSCalibration"; - protected static String DESCRIPTION = "Contains the calibration settings for the @ref AHRSCommsModule"; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 1 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java deleted file mode 100644 index 032dae775..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AHRSSettings.java +++ /dev/null @@ -1,178 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * Settings for the @ref AHRSCommsModule to control the algorithm and what is updated - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -Settings for the @ref AHRSCommsModule to control the algorithm and what is updated - -generated from ahrssettings.xml - **/ -public class AHRSSettings extends UAVDataObject { - - public AHRSSettings() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List YawBiasElemNames = new ArrayList(); - YawBiasElemNames.add("0"); - fields.add( new UAVObjectField("YawBias", "", UAVObjectField.FieldType.FLOAT32, YawBiasElemNames, null) ); - - List PitchBiasElemNames = new ArrayList(); - PitchBiasElemNames.add("0"); - fields.add( new UAVObjectField("PitchBias", "", UAVObjectField.FieldType.FLOAT32, PitchBiasElemNames, null) ); - - List RollBiasElemNames = new ArrayList(); - RollBiasElemNames.add("0"); - fields.add( new UAVObjectField("RollBias", "", UAVObjectField.FieldType.FLOAT32, RollBiasElemNames, null) ); - - List AlgorithmElemNames = new ArrayList(); - AlgorithmElemNames.add("0"); - List AlgorithmEnumOptions = new ArrayList(); - AlgorithmEnumOptions.add("SIMPLE"); - AlgorithmEnumOptions.add("INSGPS_INDOOR_NOMAG"); - AlgorithmEnumOptions.add("INSGPS_INDOOR"); - AlgorithmEnumOptions.add("INSGPS_OUTDOOR"); - fields.add( new UAVObjectField("Algorithm", "", UAVObjectField.FieldType.ENUM, AlgorithmElemNames, AlgorithmEnumOptions) ); - - List DownsamplingElemNames = new ArrayList(); - DownsamplingElemNames.add("0"); - fields.add( new UAVObjectField("Downsampling", "", UAVObjectField.FieldType.UINT8, DownsamplingElemNames, null) ); - - List UpdatePeriodElemNames = new ArrayList(); - UpdatePeriodElemNames.add("0"); - fields.add( new UAVObjectField("UpdatePeriod", "ms", UAVObjectField.FieldType.UINT8, UpdatePeriodElemNames, null) ); - - List BiasCorrectedRawElemNames = new ArrayList(); - BiasCorrectedRawElemNames.add("0"); - List BiasCorrectedRawEnumOptions = new ArrayList(); - BiasCorrectedRawEnumOptions.add("TRUE"); - BiasCorrectedRawEnumOptions.add("FALSE"); - fields.add( new UAVObjectField("BiasCorrectedRaw", "", UAVObjectField.FieldType.ENUM, BiasCorrectedRawElemNames, BiasCorrectedRawEnumOptions) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - getField("YawBias").setValue(0); - getField("PitchBias").setValue(0); - getField("RollBias").setValue(0); - getField("Algorithm").setValue("INSGPS_INDOOR_NOMAG"); - getField("Downsampling").setValue(20); - getField("UpdatePeriod").setValue(1); - getField("BiasCorrectedRaw").setValue("TRUE"); - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - AHRSSettings obj = new AHRSSettings(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public AHRSSettings GetInstance(UAVObjectManager objMngr, int instID) - { - return (AHRSSettings)(objMngr.getObject(AHRSSettings.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0xF8591ED8; - protected static final String NAME = "AHRSSettings"; - protected static String DESCRIPTION = "Settings for the @ref AHRSCommsModule to control the algorithm and what is updated"; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 1 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java deleted file mode 100644 index 82e447a70..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AhrsStatus.java +++ /dev/null @@ -1,201 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * Status for the @ref AHRSCommsModule, including communication errors - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -Status for the @ref AHRSCommsModule, including communication errors - -generated from ahrsstatus.xml - **/ -public class AhrsStatus extends UAVDataObject { - - public AhrsStatus() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List RunningTimeElemNames = new ArrayList(); - RunningTimeElemNames.add("0"); - fields.add( new UAVObjectField("RunningTime", "ms", UAVObjectField.FieldType.UINT32, RunningTimeElemNames, null) ); - - List SerialNumberElemNames = new ArrayList(); - SerialNumberElemNames.add("0"); - SerialNumberElemNames.add("1"); - SerialNumberElemNames.add("2"); - SerialNumberElemNames.add("3"); - SerialNumberElemNames.add("4"); - SerialNumberElemNames.add("5"); - SerialNumberElemNames.add("6"); - SerialNumberElemNames.add("7"); - fields.add( new UAVObjectField("SerialNumber", "", UAVObjectField.FieldType.UINT8, SerialNumberElemNames, null) ); - - List CPULoadElemNames = new ArrayList(); - CPULoadElemNames.add("0"); - fields.add( new UAVObjectField("CPULoad", "count", UAVObjectField.FieldType.UINT8, CPULoadElemNames, null) ); - - List IdleTimePerCyleElemNames = new ArrayList(); - IdleTimePerCyleElemNames.add("0"); - fields.add( new UAVObjectField("IdleTimePerCyle", "10x ms", UAVObjectField.FieldType.UINT8, IdleTimePerCyleElemNames, null) ); - - List RunningTimePerCyleElemNames = new ArrayList(); - RunningTimePerCyleElemNames.add("0"); - fields.add( new UAVObjectField("RunningTimePerCyle", "10x ms", UAVObjectField.FieldType.UINT8, RunningTimePerCyleElemNames, null) ); - - List DroppedUpdatesElemNames = new ArrayList(); - DroppedUpdatesElemNames.add("0"); - fields.add( new UAVObjectField("DroppedUpdates", "count", UAVObjectField.FieldType.UINT8, DroppedUpdatesElemNames, null) ); - - List LinkRunningElemNames = new ArrayList(); - LinkRunningElemNames.add("0"); - List LinkRunningEnumOptions = new ArrayList(); - LinkRunningEnumOptions.add("FALSE"); - LinkRunningEnumOptions.add("TRUE"); - fields.add( new UAVObjectField("LinkRunning", "", UAVObjectField.FieldType.ENUM, LinkRunningElemNames, LinkRunningEnumOptions) ); - - List AhrsKickstartsElemNames = new ArrayList(); - AhrsKickstartsElemNames.add("0"); - fields.add( new UAVObjectField("AhrsKickstarts", "count", UAVObjectField.FieldType.UINT8, AhrsKickstartsElemNames, null) ); - - List AhrsCrcErrorsElemNames = new ArrayList(); - AhrsCrcErrorsElemNames.add("0"); - fields.add( new UAVObjectField("AhrsCrcErrors", "count", UAVObjectField.FieldType.UINT8, AhrsCrcErrorsElemNames, null) ); - - List AhrsRetriesElemNames = new ArrayList(); - AhrsRetriesElemNames.add("0"); - fields.add( new UAVObjectField("AhrsRetries", "count", UAVObjectField.FieldType.UINT8, AhrsRetriesElemNames, null) ); - - List AhrsInvalidPacketsElemNames = new ArrayList(); - AhrsInvalidPacketsElemNames.add("0"); - fields.add( new UAVObjectField("AhrsInvalidPackets", "count", UAVObjectField.FieldType.UINT8, AhrsInvalidPacketsElemNames, null) ); - - List OpCrcErrorsElemNames = new ArrayList(); - OpCrcErrorsElemNames.add("0"); - fields.add( new UAVObjectField("OpCrcErrors", "count", UAVObjectField.FieldType.UINT8, OpCrcErrorsElemNames, null) ); - - List OpRetriesElemNames = new ArrayList(); - OpRetriesElemNames.add("0"); - fields.add( new UAVObjectField("OpRetries", "count", UAVObjectField.FieldType.UINT8, OpRetriesElemNames, null) ); - - List OpInvalidPacketsElemNames = new ArrayList(); - OpInvalidPacketsElemNames.add("0"); - fields.add( new UAVObjectField("OpInvalidPackets", "count", UAVObjectField.FieldType.UINT8, OpInvalidPacketsElemNames, null) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - AhrsStatus obj = new AhrsStatus(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public AhrsStatus GetInstance(UAVObjectManager objMngr, int instID) - { - return (AhrsStatus)(objMngr.getObject(AhrsStatus.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0x706D1AB8; - protected static final String NAME = "AhrsStatus"; - protected static String DESCRIPTION = "Status for the @ref AHRSCommsModule, including communication errors"; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 0 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java deleted file mode 100644 index b8c3aacb4..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeRaw.java +++ /dev/null @@ -1,158 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * The raw attitude sensor data from @ref AHRSCommsModule. Not always updated. - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -The raw attitude sensor data from @ref AHRSCommsModule. Not always updated. - -generated from attituderaw.xml - **/ -public class AttitudeRaw extends UAVDataObject { - - public AttitudeRaw() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List gyrosElemNames = new ArrayList(); - gyrosElemNames.add("X"); - gyrosElemNames.add("Y"); - gyrosElemNames.add("Z"); - fields.add( new UAVObjectField("gyros", "deg/s", UAVObjectField.FieldType.FLOAT32, gyrosElemNames, null) ); - - List accelsElemNames = new ArrayList(); - accelsElemNames.add("X"); - accelsElemNames.add("Y"); - accelsElemNames.add("Z"); - fields.add( new UAVObjectField("accels", "m/s^2", UAVObjectField.FieldType.FLOAT32, accelsElemNames, null) ); - - List magnetometersElemNames = new ArrayList(); - magnetometersElemNames.add("X"); - magnetometersElemNames.add("Y"); - magnetometersElemNames.add("Z"); - fields.add( new UAVObjectField("magnetometers", "mGa", UAVObjectField.FieldType.INT16, magnetometersElemNames, null) ); - - List gyrotempElemNames = new ArrayList(); - gyrotempElemNames.add("XY"); - gyrotempElemNames.add("Z"); - fields.add( new UAVObjectField("gyrotemp", "raw", UAVObjectField.FieldType.UINT16, gyrotempElemNames, null) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - AttitudeRaw obj = new AttitudeRaw(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public AttitudeRaw GetInstance(UAVObjectManager objMngr, int instID) - { - return (AttitudeRaw)(objMngr.getObject(AttitudeRaw.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0xDB722974; - protected static final String NAME = "AttitudeRaw"; - protected static String DESCRIPTION = "The raw attitude sensor data from @ref AHRSCommsModule. Not always updated."; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 0 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java index d775b21e7..ac3812aa6 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java @@ -66,8 +66,10 @@ public class FlightStatus extends UAVDataObject { FlightModeEnumOptions.add("Stabilized1"); FlightModeEnumOptions.add("Stabilized2"); FlightModeEnumOptions.add("Stabilized3"); + FlightModeEnumOptions.add("AltitudeHold"); FlightModeEnumOptions.add("VelocityControl"); FlightModeEnumOptions.add("PositionHold"); + FlightModeEnumOptions.add("PathPlanner"); fields.add( new UAVObjectField("FlightMode", "", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); @@ -144,7 +146,7 @@ public class FlightStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0x743DB13C; + protected static final int OBJID = 0x19B92D8; protected static final String NAME = "FlightStatus"; protected static String DESCRIPTION = "Contains major flight status information for other modules."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java index 205384efe..5510a901d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java @@ -55,14 +55,14 @@ public class GuidanceSettings extends UAVDataObject { HorizontalPosPIElemNames.add("Kp"); HorizontalPosPIElemNames.add("Ki"); HorizontalPosPIElemNames.add("ILimit"); - fields.add( new UAVObjectField("HorizontalPosPI", "(cm/s)/cm", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) ); + fields.add( new UAVObjectField("HorizontalPosPI", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) ); List HorizontalVelPIDElemNames = new ArrayList(); HorizontalVelPIDElemNames.add("Kp"); HorizontalVelPIDElemNames.add("Ki"); HorizontalVelPIDElemNames.add("Kd"); HorizontalVelPIDElemNames.add("ILimit"); - fields.add( new UAVObjectField("HorizontalVelPID", "deg/(cm/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); + fields.add( new UAVObjectField("HorizontalVelPID", "deg/(m/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); List VerticalPosPIElemNames = new ArrayList(); VerticalPosPIElemNames.add("Kp"); @@ -87,11 +87,11 @@ public class GuidanceSettings extends UAVDataObject { List HorizontalVelMaxElemNames = new ArrayList(); HorizontalVelMaxElemNames.add("0"); - fields.add( new UAVObjectField("HorizontalVelMax", "cm/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) ); + fields.add( new UAVObjectField("HorizontalVelMax", "m/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) ); List VerticalVelMaxElemNames = new ArrayList(); VerticalVelMaxElemNames.add("0"); - fields.add( new UAVObjectField("VerticalVelMax", "cm/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) ); + fields.add( new UAVObjectField("VerticalVelMax", "m/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) ); List GuidanceModeElemNames = new ArrayList(); GuidanceModeElemNames.add("0"); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java index 68abb3633..3f3b3d8dd 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java @@ -63,24 +63,6 @@ public class HomeLocation extends UAVDataObject { AltitudeElemNames.add("0"); fields.add( new UAVObjectField("Altitude", "m over geoid", UAVObjectField.FieldType.FLOAT32, AltitudeElemNames, null) ); - List ECEFElemNames = new ArrayList(); - ECEFElemNames.add("0"); - ECEFElemNames.add("1"); - ECEFElemNames.add("2"); - fields.add( new UAVObjectField("ECEF", "cm", UAVObjectField.FieldType.INT32, ECEFElemNames, null) ); - - List RNEElemNames = new ArrayList(); - RNEElemNames.add("0"); - RNEElemNames.add("1"); - RNEElemNames.add("2"); - RNEElemNames.add("3"); - RNEElemNames.add("4"); - RNEElemNames.add("5"); - RNEElemNames.add("6"); - RNEElemNames.add("7"); - RNEElemNames.add("8"); - fields.add( new UAVObjectField("RNE", "", UAVObjectField.FieldType.FLOAT32, RNEElemNames, null) ); - List BeElemNames = new ArrayList(); BeElemNames.add("0"); BeElemNames.add("1"); @@ -146,18 +128,6 @@ public class HomeLocation extends UAVDataObject { getField("Latitude").setValue(0); getField("Longitude").setValue(0); getField("Altitude").setValue(0); - getField("ECEF").setValue(0,0); - getField("ECEF").setValue(0,1); - getField("ECEF").setValue(0,2); - getField("RNE").setValue(0,0); - getField("RNE").setValue(0,1); - getField("RNE").setValue(0,2); - getField("RNE").setValue(0,3); - getField("RNE").setValue(0,4); - getField("RNE").setValue(0,5); - getField("RNE").setValue(0,6); - getField("RNE").setValue(0,7); - getField("RNE").setValue(0,8); getField("Be").setValue(0,0); getField("Be").setValue(0,1); getField("Be").setValue(0,2); @@ -191,7 +161,7 @@ public class HomeLocation extends UAVDataObject { } // Constants - protected static final int OBJID = 0x5BB3AEFC; + protected static final int OBJID = 0x6185DC6E; protected static final String NAME = "HomeLocation"; protected static String DESCRIPTION = "HomeLocation setting which contains the constants to tranlate from longitutde and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java index 83b7ae7b6..f56982e69 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java @@ -89,31 +89,70 @@ public class HwSettings extends UAVDataObject { CC_FlexiPortEnumOptions.add("ComBridge"); fields.add( new UAVObjectField("CC_FlexiPort", "function", UAVObjectField.FieldType.ENUM, CC_FlexiPortElemNames, CC_FlexiPortEnumOptions) ); - List OP_RcvrPortElemNames = new ArrayList(); - OP_RcvrPortElemNames.add("0"); - List OP_RcvrPortEnumOptions = new ArrayList(); - OP_RcvrPortEnumOptions.add("Disabled"); - OP_RcvrPortEnumOptions.add("PWM"); - OP_RcvrPortEnumOptions.add("PPM"); - OP_RcvrPortEnumOptions.add("DSM2"); - OP_RcvrPortEnumOptions.add("DSMX (10bit)"); - OP_RcvrPortEnumOptions.add("DSMX (11bit)"); - OP_RcvrPortEnumOptions.add("Debug"); - fields.add( new UAVObjectField("OP_RcvrPort", "function", UAVObjectField.FieldType.ENUM, OP_RcvrPortElemNames, OP_RcvrPortEnumOptions) ); + List RV_RcvrPortElemNames = new ArrayList(); + RV_RcvrPortElemNames.add("0"); + List RV_RcvrPortEnumOptions = new ArrayList(); + RV_RcvrPortEnumOptions.add("Disabled"); + RV_RcvrPortEnumOptions.add("PWM"); + RV_RcvrPortEnumOptions.add("PPM"); + RV_RcvrPortEnumOptions.add("PPM+Outputs"); + RV_RcvrPortEnumOptions.add("Outputs"); + fields.add( new UAVObjectField("RV_RcvrPort", "function", UAVObjectField.FieldType.ENUM, RV_RcvrPortElemNames, RV_RcvrPortEnumOptions) ); - List OP_MainPortElemNames = new ArrayList(); - OP_MainPortElemNames.add("0"); - List OP_MainPortEnumOptions = new ArrayList(); - OP_MainPortEnumOptions.add("Disabled"); - OP_MainPortEnumOptions.add("Telemetry"); - fields.add( new UAVObjectField("OP_MainPort", "function", UAVObjectField.FieldType.ENUM, OP_MainPortElemNames, OP_MainPortEnumOptions) ); + List RV_AuxPortElemNames = new ArrayList(); + RV_AuxPortElemNames.add("0"); + List RV_AuxPortEnumOptions = new ArrayList(); + RV_AuxPortEnumOptions.add("Disabled"); + RV_AuxPortEnumOptions.add("Telemetry"); + RV_AuxPortEnumOptions.add("DSM2"); + RV_AuxPortEnumOptions.add("DSMX (10bit)"); + RV_AuxPortEnumOptions.add("DSMX (11bit)"); + RV_AuxPortEnumOptions.add("ComAux"); + RV_AuxPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("RV_AuxPort", "function", UAVObjectField.FieldType.ENUM, RV_AuxPortElemNames, RV_AuxPortEnumOptions) ); - List OP_FlexiPortElemNames = new ArrayList(); - OP_FlexiPortElemNames.add("0"); - List OP_FlexiPortEnumOptions = new ArrayList(); - OP_FlexiPortEnumOptions.add("Disabled"); - OP_FlexiPortEnumOptions.add("GPS"); - fields.add( new UAVObjectField("OP_FlexiPort", "function", UAVObjectField.FieldType.ENUM, OP_FlexiPortElemNames, OP_FlexiPortEnumOptions) ); + List RV_AuxSBusPortElemNames = new ArrayList(); + RV_AuxSBusPortElemNames.add("0"); + List RV_AuxSBusPortEnumOptions = new ArrayList(); + RV_AuxSBusPortEnumOptions.add("Disabled"); + RV_AuxSBusPortEnumOptions.add("S.Bus"); + RV_AuxSBusPortEnumOptions.add("DSM2"); + RV_AuxSBusPortEnumOptions.add("DSMX (10bit)"); + RV_AuxSBusPortEnumOptions.add("DSMX (11bit)"); + RV_AuxSBusPortEnumOptions.add("ComAux"); + RV_AuxSBusPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("RV_AuxSBusPort", "function", UAVObjectField.FieldType.ENUM, RV_AuxSBusPortElemNames, RV_AuxSBusPortEnumOptions) ); + + List RV_FlexiPortElemNames = new ArrayList(); + RV_FlexiPortElemNames.add("0"); + List RV_FlexiPortEnumOptions = new ArrayList(); + RV_FlexiPortEnumOptions.add("Disabled"); + RV_FlexiPortEnumOptions.add("I2C"); + RV_FlexiPortEnumOptions.add("DSM2"); + RV_FlexiPortEnumOptions.add("DSMX (10bit)"); + RV_FlexiPortEnumOptions.add("DSMX (11bit)"); + RV_FlexiPortEnumOptions.add("ComAux"); + RV_FlexiPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("RV_FlexiPort", "function", UAVObjectField.FieldType.ENUM, RV_FlexiPortElemNames, RV_FlexiPortEnumOptions) ); + + List RV_TelemetryPortElemNames = new ArrayList(); + RV_TelemetryPortElemNames.add("0"); + List RV_TelemetryPortEnumOptions = new ArrayList(); + RV_TelemetryPortEnumOptions.add("Disabled"); + RV_TelemetryPortEnumOptions.add("Telemetry"); + RV_TelemetryPortEnumOptions.add("ComAux"); + RV_TelemetryPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("RV_TelemetryPort", "function", UAVObjectField.FieldType.ENUM, RV_TelemetryPortElemNames, RV_TelemetryPortEnumOptions) ); + + List RV_GPSPortElemNames = new ArrayList(); + RV_GPSPortElemNames.add("0"); + List RV_GPSPortEnumOptions = new ArrayList(); + RV_GPSPortEnumOptions.add("Disabled"); + RV_GPSPortEnumOptions.add("Telemetry"); + RV_GPSPortEnumOptions.add("GPS"); + RV_GPSPortEnumOptions.add("ComAux"); + RV_GPSPortEnumOptions.add("ComBridge"); + fields.add( new UAVObjectField("RV_GPSPort", "function", UAVObjectField.FieldType.ENUM, RV_GPSPortElemNames, RV_GPSPortEnumOptions) ); List TelemetrySpeedElemNames = new ArrayList(); TelemetrySpeedElemNames.add("0"); @@ -180,6 +219,7 @@ public class HwSettings extends UAVDataObject { OptionalModulesElemNames.add("ComUsbBridge"); OptionalModulesElemNames.add("Fault"); OptionalModulesElemNames.add("Altitude"); + OptionalModulesElemNames.add("TxPID"); List OptionalModulesEnumOptions = new ArrayList(); OptionalModulesEnumOptions.add("Disabled"); OptionalModulesEnumOptions.add("Enabled"); @@ -237,9 +277,12 @@ public class HwSettings extends UAVDataObject { getField("CC_RcvrPort").setValue("PWM"); getField("CC_MainPort").setValue("Disabled"); getField("CC_FlexiPort").setValue("Disabled"); - getField("OP_RcvrPort").setValue("PWM"); - getField("OP_MainPort").setValue("Telemetry"); - getField("OP_FlexiPort").setValue("GPS"); + getField("RV_RcvrPort").setValue("PWM"); + getField("RV_AuxPort").setValue("Disabled"); + getField("RV_AuxSBusPort").setValue("Disabled"); + getField("RV_FlexiPort").setValue("Disabled"); + getField("RV_TelemetryPort").setValue("Telemetry"); + getField("RV_GPSPort").setValue("GPS"); getField("TelemetrySpeed").setValue("57600"); getField("GPSSpeed").setValue("57600"); getField("ComUsbBridgeSpeed").setValue("57600"); @@ -251,6 +294,7 @@ public class HwSettings extends UAVDataObject { getField("OptionalModules").setValue("Disabled",2); getField("OptionalModules").setValue("Disabled",3); getField("OptionalModules").setValue("Disabled",4); + getField("OptionalModules").setValue("Disabled",5); getField("DSMxBind").setValue(0); } @@ -280,7 +324,7 @@ public class HwSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x2EE6575A; + protected static final int OBJID = 0x4730375C; protected static final String NAME = "HwSettings"; protected static String DESCRIPTION = "Selection of optional hardware configurations."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java index bb846695d..c8f460bc4 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java @@ -181,8 +181,10 @@ public class ManualControlSettings extends UAVDataObject { FlightModePositionEnumOptions.add("Stabilized1"); FlightModePositionEnumOptions.add("Stabilized2"); FlightModePositionEnumOptions.add("Stabilized3"); + FlightModePositionEnumOptions.add("AltitudeHold"); FlightModePositionEnumOptions.add("VelocityControl"); FlightModePositionEnumOptions.add("PositionHold"); + FlightModePositionEnumOptions.add("PathPlanner"); fields.add( new UAVObjectField("FlightModePosition", "", UAVObjectField.FieldType.ENUM, FlightModePositionElemNames, FlightModePositionEnumOptions) ); @@ -317,7 +319,7 @@ public class ManualControlSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x24959BB0; + protected static final int OBJID = 0x59C4551C; protected static final String NAME = "ManualControlSettings"; protected static String DESCRIPTION = "Settings to indicate how to decode receiver input by @ref ManualControlModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java index 106220a8c..80e3b15bf 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java @@ -83,6 +83,14 @@ public class MixerStatus extends UAVDataObject { Mixer8ElemNames.add("0"); fields.add( new UAVObjectField("Mixer8", "", UAVObjectField.FieldType.FLOAT32, Mixer8ElemNames, null) ); + List Mixer9ElemNames = new ArrayList(); + Mixer9ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer9", "", UAVObjectField.FieldType.FLOAT32, Mixer9ElemNames, null) ); + + List Mixer10ElemNames = new ArrayList(); + Mixer10ElemNames.add("0"); + fields.add( new UAVObjectField("Mixer10", "", UAVObjectField.FieldType.FLOAT32, Mixer10ElemNames, null) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -156,7 +164,7 @@ public class MixerStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0x11CFB4E6; + protected static final int OBJID = 0x124E28A; protected static final String NAME = "MixerStatus"; protected static String DESCRIPTION = "Status for the matrix mixer showing the output of each mixer after all scaling"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java index 3b09dd1f8..1629a19d2 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java @@ -53,15 +53,15 @@ public class NedAccel extends UAVDataObject { List NorthElemNames = new ArrayList(); NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "cm/s^2", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); + fields.add( new UAVObjectField("North", "m/s^2", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); List EastElemNames = new ArrayList(); EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "cm/s^2", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); + fields.add( new UAVObjectField("East", "m/s^2", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); List DownElemNames = new ArrayList(); DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "cm/s^2", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); + fields.add( new UAVObjectField("Down", "m/s^2", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); // Compute the number of bytes for this object diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java index ac30ad4f5..184098a16 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java @@ -53,15 +53,15 @@ public class PositionActual extends UAVDataObject { List NorthElemNames = new ArrayList(); NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "cm", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + fields.add( new UAVObjectField("North", "m", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); List EastElemNames = new ArrayList(); EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "cm", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + fields.add( new UAVObjectField("East", "m", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); List DownElemNames = new ArrayList(); DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "cm", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + fields.add( new UAVObjectField("Down", "m", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); // Compute the number of bytes for this object @@ -136,7 +136,7 @@ public class PositionActual extends UAVDataObject { } // Constants - protected static final int OBJID = 0xF9691DA4; + protected static final int OBJID = 0xFA9E2D42; protected static final String NAME = "PositionActual"; protected static String DESCRIPTION = "Contains the current position relative to @ref HomeLocation"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java index 2ff5a5586..123ca58af 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java @@ -53,15 +53,15 @@ public class PositionDesired extends UAVDataObject { List NorthElemNames = new ArrayList(); NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "cm", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + fields.add( new UAVObjectField("North", "m", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); List EastElemNames = new ArrayList(); EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "cm", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + fields.add( new UAVObjectField("East", "m", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); List DownElemNames = new ArrayList(); DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "cm", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + fields.add( new UAVObjectField("Down", "m", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); // Compute the number of bytes for this object @@ -136,7 +136,7 @@ public class PositionDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0x33C9EAB4; + protected static final int OBJID = 0x778DBE24; protected static final String NAME = "PositionDesired"; protected static String DESCRIPTION = "The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner "; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java index 458dd9d10..bc4bf0625 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java @@ -61,6 +61,7 @@ public class SystemAlarms extends UAVDataObject { AlarmElemNames.add("ManualControl"); AlarmElemNames.add("Actuator"); AlarmElemNames.add("Attitude"); + AlarmElemNames.add("Sensors"); AlarmElemNames.add("Stabilization"); AlarmElemNames.add("Guidance"); AlarmElemNames.add("AHRSComms"); @@ -139,6 +140,7 @@ public class SystemAlarms extends UAVDataObject { getField("Alarm").setValue("Uninitialised",14); getField("Alarm").setValue("Uninitialised",15); getField("Alarm").setValue("Uninitialised",16); + getField("Alarm").setValue("Uninitialised",17); } @@ -167,7 +169,7 @@ public class SystemAlarms extends UAVDataObject { } // Constants - protected static final int OBJID = 0x737ADCF2; + protected static final int OBJID = 0x9C7CBFE; protected static final String NAME = "SystemAlarms"; protected static String DESCRIPTION = "Alarms from OpenPilot to indicate failure conditions or warnings. Set by various modules."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java index d1c51d43f..26d01f2a0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java @@ -55,6 +55,18 @@ public class SystemStats extends UAVDataObject { FlightTimeElemNames.add("0"); fields.add( new UAVObjectField("FlightTime", "ms", UAVObjectField.FieldType.UINT32, FlightTimeElemNames, null) ); + List EventSystemWarningIDElemNames = new ArrayList(); + EventSystemWarningIDElemNames.add("0"); + fields.add( new UAVObjectField("EventSystemWarningID", "uavoid", UAVObjectField.FieldType.UINT32, EventSystemWarningIDElemNames, null) ); + + List ObjectManagerCallbackIDElemNames = new ArrayList(); + ObjectManagerCallbackIDElemNames.add("0"); + fields.add( new UAVObjectField("ObjectManagerCallbackID", "uavoid", UAVObjectField.FieldType.UINT32, ObjectManagerCallbackIDElemNames, null) ); + + List ObjectManagerQueueIDElemNames = new ArrayList(); + ObjectManagerQueueIDElemNames.add("0"); + fields.add( new UAVObjectField("ObjectManagerQueueID", "uavoid", UAVObjectField.FieldType.UINT32, ObjectManagerQueueIDElemNames, null) ); + List HeapRemainingElemNames = new ArrayList(); HeapRemainingElemNames.add("0"); fields.add( new UAVObjectField("HeapRemaining", "bytes", UAVObjectField.FieldType.UINT16, HeapRemainingElemNames, null) ); @@ -144,7 +156,7 @@ public class SystemStats extends UAVDataObject { } // Constants - protected static final int OBJID = 0xD610A0F0; + protected static final int OBJID = 0x364D1406; protected static final String NAME = "SystemStats"; protected static String DESCRIPTION = "CPU and memory usage from OpenPilot computer. "; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java index 54825fafe..eefcef6d9 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java @@ -55,36 +55,42 @@ public class TaskInfo extends UAVDataObject { StackRemainingElemNames.add("System"); StackRemainingElemNames.add("Actuator"); StackRemainingElemNames.add("Attitude"); + StackRemainingElemNames.add("Sensors"); StackRemainingElemNames.add("TelemetryTx"); StackRemainingElemNames.add("TelemetryTxPri"); StackRemainingElemNames.add("TelemetryRx"); StackRemainingElemNames.add("GPS"); StackRemainingElemNames.add("ManualControl"); StackRemainingElemNames.add("Altitude"); - StackRemainingElemNames.add("AHRSComms"); StackRemainingElemNames.add("Stabilization"); + StackRemainingElemNames.add("AltitudeHold"); StackRemainingElemNames.add("Guidance"); StackRemainingElemNames.add("FlightPlan"); + StackRemainingElemNames.add("PathPlanner"); StackRemainingElemNames.add("Com2UsbBridge"); StackRemainingElemNames.add("Usb2ComBridge"); + StackRemainingElemNames.add("OveroSync"); fields.add( new UAVObjectField("StackRemaining", "bytes", UAVObjectField.FieldType.UINT16, StackRemainingElemNames, null) ); List RunningElemNames = new ArrayList(); RunningElemNames.add("System"); RunningElemNames.add("Actuator"); RunningElemNames.add("Attitude"); + RunningElemNames.add("Sensors"); RunningElemNames.add("TelemetryTx"); RunningElemNames.add("TelemetryTxPri"); RunningElemNames.add("TelemetryRx"); RunningElemNames.add("GPS"); RunningElemNames.add("ManualControl"); RunningElemNames.add("Altitude"); - RunningElemNames.add("AHRSComms"); RunningElemNames.add("Stabilization"); + RunningElemNames.add("AltitudeHold"); RunningElemNames.add("Guidance"); RunningElemNames.add("FlightPlan"); + RunningElemNames.add("PathPlanner"); RunningElemNames.add("Com2UsbBridge"); RunningElemNames.add("Usb2ComBridge"); + RunningElemNames.add("OveroSync"); List RunningEnumOptions = new ArrayList(); RunningEnumOptions.add("False"); RunningEnumOptions.add("True"); @@ -94,18 +100,21 @@ public class TaskInfo extends UAVDataObject { RunningTimeElemNames.add("System"); RunningTimeElemNames.add("Actuator"); RunningTimeElemNames.add("Attitude"); + RunningTimeElemNames.add("Sensors"); RunningTimeElemNames.add("TelemetryTx"); RunningTimeElemNames.add("TelemetryTxPri"); RunningTimeElemNames.add("TelemetryRx"); RunningTimeElemNames.add("GPS"); RunningTimeElemNames.add("ManualControl"); RunningTimeElemNames.add("Altitude"); - RunningTimeElemNames.add("AHRSComms"); RunningTimeElemNames.add("Stabilization"); + RunningTimeElemNames.add("AltitudeHold"); RunningTimeElemNames.add("Guidance"); RunningTimeElemNames.add("FlightPlan"); + RunningTimeElemNames.add("PathPlanner"); RunningTimeElemNames.add("Com2UsbBridge"); RunningTimeElemNames.add("Usb2ComBridge"); + RunningTimeElemNames.add("OveroSync"); fields.add( new UAVObjectField("RunningTime", "%", UAVObjectField.FieldType.UINT8, RunningTimeElemNames, null) ); @@ -181,7 +190,7 @@ public class TaskInfo extends UAVDataObject { } // Constants - protected static final int OBJID = 0xE34A7C32; + protected static final int OBJID = 0x498F54BA; protected static final String NAME = "TaskInfo"; protected static String DESCRIPTION = "Task information"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java index c2cf64d49..823643130 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java @@ -35,15 +35,15 @@ public class UAVObjectsInitialize { public static void register(UAVObjectManager objMngr) { try { + objMngr.registerObject( new Accels() ); objMngr.registerObject( new AccessoryDesired() ); objMngr.registerObject( new ActuatorCommand() ); objMngr.registerObject( new ActuatorDesired() ); objMngr.registerObject( new ActuatorSettings() ); - objMngr.registerObject( new AHRSCalibration() ); - objMngr.registerObject( new AHRSSettings() ); - objMngr.registerObject( new AhrsStatus() ); + objMngr.registerObject( new AltHoldSmoothed() ); + objMngr.registerObject( new AltitudeHoldDesired() ); + objMngr.registerObject( new AltitudeHoldSettings() ); objMngr.registerObject( new AttitudeActual() ); - objMngr.registerObject( new AttitudeRaw() ); objMngr.registerObject( new AttitudeSettings() ); objMngr.registerObject( new BaroAltitude() ); objMngr.registerObject( new CameraDesired() ); @@ -62,16 +62,23 @@ public class UAVObjectsInitialize { objMngr.registerObject( new GPSPosition() ); objMngr.registerObject( new GPSSatellites() ); objMngr.registerObject( new GPSTime() ); + objMngr.registerObject( new GPSVelocity() ); + objMngr.registerObject( new Gyros() ); + objMngr.registerObject( new GyrosBias() ); objMngr.registerObject( new GuidanceSettings() ); objMngr.registerObject( new HomeLocation() ); objMngr.registerObject( new HwSettings() ); objMngr.registerObject( new I2CStats() ); + objMngr.registerObject( new GPSPosition() ); + objMngr.registerObject( new Magnetometer() ); objMngr.registerObject( new ManualControlCommand() ); objMngr.registerObject( new ManualControlSettings() ); objMngr.registerObject( new MixerSettings() ); objMngr.registerObject( new MixerStatus() ); + objMngr.registerObject( new NEDPosition() ); objMngr.registerObject( new NedAccel() ); objMngr.registerObject( new ObjectPersistence() ); + objMngr.registerObject( new PathDesired() ); objMngr.registerObject( new PositionActual() ); objMngr.registerObject( new PositionDesired() ); objMngr.registerObject( new RateDesired() ); @@ -82,10 +89,13 @@ public class UAVObjectsInitialize { objMngr.registerObject( new SystemAlarms() ); objMngr.registerObject( new SystemSettings() ); objMngr.registerObject( new SystemStats() ); + objMngr.registerObject( new TxPIDSettings() ); objMngr.registerObject( new TaskInfo() ); objMngr.registerObject( new VelocityActual() ); objMngr.registerObject( new VelocityDesired() ); objMngr.registerObject( new WatchdogStatus() ); + objMngr.registerObject( new Waypoint() ); + objMngr.registerObject( new WaypointActive() ); } catch (Exception e) { e.printStackTrace(); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java index 97d038cfe..2a8cd3754 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java @@ -53,15 +53,15 @@ public class VelocityActual extends UAVDataObject { List NorthElemNames = new ArrayList(); NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "cm/s", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + fields.add( new UAVObjectField("North", "m/s", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); List EastElemNames = new ArrayList(); EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "cm/s", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + fields.add( new UAVObjectField("East", "m/s", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); List DownElemNames = new ArrayList(); DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "cm/s", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + fields.add( new UAVObjectField("Down", "m/s", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); // Compute the number of bytes for this object @@ -136,7 +136,7 @@ public class VelocityActual extends UAVDataObject { } // Constants - protected static final int OBJID = 0x43007EB0; + protected static final int OBJID = 0x5A08F61A; protected static final String NAME = "VelocityActual"; protected static String DESCRIPTION = "Updated by @ref AHRSCommsModule and used within @ref GuidanceModule for velocity control"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java index f39fbd6de..436ef6448 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java @@ -53,15 +53,15 @@ public class VelocityDesired extends UAVDataObject { List NorthElemNames = new ArrayList(); NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "cm/s", UAVObjectField.FieldType.INT32, NorthElemNames, null) ); + fields.add( new UAVObjectField("North", "m/s", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); List EastElemNames = new ArrayList(); EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "cm/s", UAVObjectField.FieldType.INT32, EastElemNames, null) ); + fields.add( new UAVObjectField("East", "m/s", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); List DownElemNames = new ArrayList(); DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "cm/s", UAVObjectField.FieldType.INT32, DownElemNames, null) ); + fields.add( new UAVObjectField("Down", "m/s", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); // Compute the number of bytes for this object @@ -136,7 +136,7 @@ public class VelocityDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0x25139D1A; + protected static final int OBJID = 0x9E946992; protected static final String NAME = "VelocityDesired"; protected static String DESCRIPTION = "Used within @ref GuidanceModule to communicate between the task computing the desired velocity and the PID loop to achieve it (running at different rates)."; protected static final boolean ISSINGLEINST = 1 == 1; From 0e6cffaaf68647f586f16ebccdf7b65004e585f9 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 16:12:45 -0500 Subject: [PATCH 169/284] Update fake telemetry object --- .../org/openpilot/androidgcs/OPTelemetryService.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index bc711560d..074049d79 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -222,18 +222,6 @@ public class OPTelemetryService extends Service { homeLocation.getField("Latitude").setDouble(379420315); homeLocation.getField("Longitude").setDouble(-88330078); - homeLocation.getField("ECEF").setDouble(497665694,0); - homeLocation.getField("ECEF").setDouble(-77336320,1); - homeLocation.getField("ECEF").setDouble(390037169,2); - homeLocation.getField("RNE").setDouble(-0.60757166,0); - homeLocation.getField("RNE").setDouble(0.09441550,1); - homeLocation.getField("RNE").setDouble(0.78863323,2); - homeLocation.getField("RNE").setDouble(0.15355512,3); - homeLocation.getField("RNE").setDouble(0.98814011,4); - homeLocation.getField("RNE").setDouble(0,5); - homeLocation.getField("RNE").setDouble(-0.77928013,6); - homeLocation.getField("RNE").setDouble(0.12109867,7); - homeLocation.getField("RNE").setDouble(-0.61486387,8); homeLocation.getField("Be").setDouble(26702.78710938,0); homeLocation.getField("Be").setDouble(-1468.33605957,1); homeLocation.getField("Be").setDouble(34181.78515625,2); From cd89d97bbb99e5ca498a3720b6eadb188a3332dc Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 10 May 2012 16:38:49 -0500 Subject: [PATCH 170/284] Lower all the debugging levels again --- .../org/openpilot/androidgcs/OPTelemetryService.java | 2 +- androidgcs/src/org/openpilot/uavtalk/Telemetry.java | 2 +- .../src/org/openpilot/uavtalk/TelemetryMonitor.java | 10 ++++++++-- androidgcs/src/org/openpilot/uavtalk/UAVTalk.java | 10 ++++------ 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 074049d79..1a4b61eb8 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -33,7 +33,7 @@ public class OPTelemetryService extends Service { // Logging settings private final String TAG = "OPTelemetryService"; - public static int LOGLEVEL = 2; + public static int LOGLEVEL = 0; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 11e6cb2ca..1395a5c08 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -17,7 +17,7 @@ import android.util.Log; public class Telemetry { private final String TAG = "Telemetry"; - public static int LOGLEVEL = 2; + public static int LOGLEVEL = 0; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index 903b6b29f..87a0cdc70 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -13,7 +13,7 @@ import android.util.Log; public class TelemetryMonitor extends Observable{ private static final String TAG = "TelemetryMonitor"; - public static int LOGLEVEL = 2; + public static int LOGLEVEL = 0; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; @@ -204,6 +204,8 @@ public class TelemetryMonitor extends Observable{ Telemetry.TelemetryStats telStats = tel.getStats(); tel.resetStats(); + if (DEBUG) Log.d(TAG, "processStatsUpdates() - stats reset"); + // Update stats object gcsStatsObj.getField("RxDataRate").setDouble( (float)telStats.rxBytes / ((float)currentPeriod/1000.0) ); gcsStatsObj.getField("TxDataRate").setDouble( (float)telStats.txBytes / ((float)currentPeriod/1000.0) ); @@ -214,6 +216,8 @@ public class TelemetryMonitor extends Observable{ field = gcsStatsObj.getField("TxRetries"); field.setDouble(field.getDouble() + telStats.txRetries); + if (DEBUG) Log.d(TAG, "processStatsUpdates() - stats updated"); + // Check for a connection timeout boolean connectionTimeout; if ( telStats.rxObjects > 0 ) @@ -296,8 +300,10 @@ public class TelemetryMonitor extends Observable{ objects_updated = false; setChanged(); } + + if (DEBUG) Log.d(TAG, "processStatsUpdates() - before notify"); notifyObservers(); - + if (DEBUG) Log.d(TAG, "processStatsUpdates() - after notify"); } private void setPeriod(int ms) { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java index 5a3a9a1a5..9cdd11ccb 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java @@ -12,7 +12,7 @@ import android.util.Log; public class UAVTalk extends Observable { static final String TAG = "UAVTalk"; - public static int LOGLEVEL = 2; + public static int LOGLEVEL = 0; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; @@ -504,8 +504,7 @@ public class UAVTalk extends Observable { case TYPE_OBJ_ACK: // All instances, not allowed for OBJ_ACK messages if (!allInstances) { - System.out.println("Received object ack: " + objId + " " + - objMngr.getObject(objId).getName()); + if (DEBUG) Log.d(TAG,"Received object ack: " + objId + " " + objMngr.getObject(objId).getName()); // Get object and update its data obj = updateObject(objId, instId, data); // Transmit ACK @@ -521,7 +520,7 @@ public class UAVTalk extends Observable { case TYPE_OBJ_REQ: // Get object, if all instances are requested get instance 0 of the // object - System.out.println("Received object request: " + objId + " " + + if (DEBUG) Log.d(TAG,"Received object request: " + objId + " " + objMngr.getObject(objId).getName()); if (allInstances) { obj = objMngr.getObject(objId); @@ -538,8 +537,7 @@ public class UAVTalk extends Observable { case TYPE_ACK: // All instances, not allowed for ACK messages if (!allInstances) { - System.out.println("Received ack: " + objId + " " + - objMngr.getObject(objId).getName()); + if (DEBUG) Log.d(TAG,"Received ack: " + objId + " " + objMngr.getObject(objId).getName()); // Get object obj = objMngr.getObject(objId, instId); // Check if an ack is pending From c736488c3bd80a9e423261adc146ed284cc5ddbd Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 2 Aug 2012 11:04:35 -0500 Subject: [PATCH 171/284] First step to fixing metat data representation for android --- .../org/openpilot/uavtalk/UAVMetaObject.java | 46 ++++-------- .../src/org/openpilot/uavtalk/UAVObject.java | 70 +++++++------------ .../org/openpilot/uavtalk/UAVObjectField.java | 48 ++++++++++++- 3 files changed, 85 insertions(+), 79 deletions(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java index 7aab176ef..c57b6c2fe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java @@ -13,43 +13,25 @@ public class UAVMetaObject extends UAVObject { ownMetadata = new Metadata(); - ownMetadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - ownMetadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - ownMetadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - ownMetadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - ownMetadata.flightTelemetryUpdatePeriod = 0; - ownMetadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - ownMetadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; + ownMetadata.flags = 0; // TODO: Fix flags ownMetadata.gcsTelemetryUpdatePeriod = 0; - ownMetadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; ownMetadata.loggingUpdatePeriod = 0; - // Setup fields - List boolEnum = new ArrayList(); - boolEnum.add("False"); - boolEnum.add("True"); - List updateModeEnum = new ArrayList(); - updateModeEnum.add("Periodic"); - updateModeEnum.add("On Change"); - updateModeEnum.add("Manual"); - updateModeEnum.add("Never"); + List modesBitField = new ArrayList(); + modesBitField.add("FlightReadOnly"); + modesBitField.add("GCSReadOnly"); + modesBitField.add("FlightTelemetryAcked"); + modesBitField.add("GCSTelemetryAcked"); + modesBitField.add("FlightUpdatePeriodic"); + modesBitField.add("FlightUpdateOnChange"); + modesBitField.add("GCSUpdatePeriodic"); + modesBitField.add("GCSUpdateOnChange"); - List accessModeEnum = new ArrayList(); - accessModeEnum.add("Read/Write"); - accessModeEnum.add("Read Only"); - - List fields = new ArrayList(); - fields.add( new UAVObjectField("Flight Access Mode", "", UAVObjectField.FieldType.ENUM, 1, accessModeEnum) ); - fields.add( new UAVObjectField("GCS Access Mode", "", UAVObjectField.FieldType.ENUM, 1, accessModeEnum) ); - fields.add( new UAVObjectField("Flight Telemetry Acked", "", UAVObjectField.FieldType.ENUM, 1, boolEnum) ); - fields.add( new UAVObjectField("Flight Telemetry Update Mode", "", UAVObjectField.FieldType.ENUM, 1, updateModeEnum) ); - fields.add( new UAVObjectField("Flight Telemetry Update Period", "", UAVObjectField.FieldType.UINT32, 1, null) ); - fields.add( new UAVObjectField("GCS Telemetry Acked", "", UAVObjectField.FieldType.ENUM, 1, boolEnum) ); - fields.add( new UAVObjectField("GCS Telemetry Update Mode", "", UAVObjectField.FieldType.ENUM, 1, updateModeEnum) ); - fields.add( new UAVObjectField("GCS Telemetry Update Period", "", UAVObjectField.FieldType.UINT32, 1, null ) ); - fields.add( new UAVObjectField("Logging Update Mode", "", UAVObjectField.FieldType.ENUM, 1, updateModeEnum) ); - fields.add( new UAVObjectField("Logging Update Period", "", UAVObjectField.FieldType.UINT32, 1, null ) ); + fields.add( new UAVObjectField("Modes", "", UAVObjectField.FieldType.BITFIELD, 1, modesBitField) ); + fields.add( new UAVObjectField("Flight Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); + fields.add( new UAVObjectField("GCS Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); + fields.add( new UAVObjectField("Logging Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); int numBytes = 0; ListIterator li = fields.listIterator(); diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 940b076a5..20d4cb02a 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -120,17 +120,10 @@ public abstract class UAVObject { * Object update mode */ public enum UpdateMode { - UPDATEMODE_PERIODIC, /** - * Automatically update object at periodic - * intervals - */ + UPDATEMODE_MANUAL, /** Manually update object, by calling the updated() function */ + UPDATEMODE_PERIODIC, /** Automatically update object at periodic intervals */ UPDATEMODE_ONCHANGE, /** Only update object when its data changes */ - UPDATEMODE_MANUAL, /** - * Manually update object, by calling the updated() - * function - */ - UPDATEMODE_NEVER - /** Object is never updated */ + UPDATEMODE_THROTTLED /** Object is updated on change, but not more often than the interval time */ }; /** @@ -140,47 +133,32 @@ public abstract class UAVObject { ACCESS_READWRITE, ACCESS_READONLY }; - /** - * Access mode - */ - public enum Acked { - FALSE, TRUE - }; - public final class Metadata { - public AccessMode flightAccess; /** - * Defines the access level for the local flight transactions (readonly - * and readwrite) + * Object metadata, each object has a meta object that holds its metadata. The metadata define + * properties for each object and can be used by multiple modules (e.g. telemetry and logger) + * + * The object metadata flags are packed into a single 16 bit integer. + * The bits in the flag field are defined as: + * + * Bit(s) Name Meaning + * ------ ---- ------- + * 0 access Defines the access level for the local transactions (readonly=0 and readwrite=1) + * 1 gcsAccess Defines the access level for the local GCS transactions (readonly=0 and readwrite=1), not used in the flight s/w + * 2 telemetryAcked Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) + * 3 gcsTelemetryAcked Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) + * 4-5 telemetryUpdateMode Update mode used by the telemetry module (UAVObjUpdateMode) + * 6-7 gcsTelemetryUpdateMode Update mode used by the GCS (UAVObjUpdateMode) */ - public AccessMode gcsAccess; - /** - * Defines the access level for the local GCS transactions (readonly and - * readwrite) - */ - public Acked flightTelemetryAcked; - /** - * Defines if an ack is required for the transactions of this object - * (1:acked, 0:not acked) - */ - public UpdateMode flightTelemetryUpdateMode; - /** Update mode used by the autopilot (UpdateMode) */ + public int flags; /** Defines flags for update and logging modes and whether an update should be ACK'd (bits defined above) */ + + /** Update period used by the telemetry module (only if telemetry mode is PERIODIC) */ public int flightTelemetryUpdatePeriod; - /** - * Update period used by the autopilot (only if telemetry mode is - * PERIODIC) - */ - public Acked gcsTelemetryAcked; - /** - * Defines if an ack is required for the transactions of this object - * (1:acked, 0:not acked) - */ - public UpdateMode gcsTelemetryUpdateMode; - /** Update mode used by the GCS (UpdateMode) */ - public int gcsTelemetryUpdatePeriod; + + /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ + public int gcsTelemetryUpdatePeriod; + /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ - public UpdateMode loggingUpdateMode; - /** Update mode used by the logging module (UpdateMode) */ public int loggingUpdatePeriod; /** * Update period used by the logging module (only if logging mode is diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 286859e63..c2965f6cc 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -7,7 +7,7 @@ import java.util.List; public class UAVObjectField { - public enum FieldType { INT8, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, STRING }; + public enum FieldType { INT8, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, BITFIELD, STRING }; public UAVObjectField(String name, String units, FieldType type, int numElements, List options) { List elementNames = new ArrayList(); @@ -56,6 +56,8 @@ public class UAVObjectField { return "float32"; case ENUM: return "enum"; + case BITFIELD: + return "bitfield"; case STRING: return "string"; default: @@ -144,6 +146,11 @@ public class UAVObjectField { for (int index = 0; index < numElements; ++index) dataOut.put((Byte) l.get(index)); break; + case BITFIELD: + for (int index = 0; index < numElements; ++index) { + Integer val = (Integer) getValue(index); + dataOut.put(val.byteValue()); + } case STRING: // TODO: Implement strings throw new Error("Strings not yet implemented"); @@ -224,6 +231,16 @@ public class UAVObjectField { } break; } + case BITFIELD: + { + List l = (List) this.data; + for (int index = 0 ; index < numElements; ++index) { + int signedval = (int) dataIn.get(); // this sign extends it + int unsignedval = signedval & 0xff; // drop sign extension + l.set(index, (short) unsignedval); + } + break; + } case ENUM: { List l = (List) this.data; @@ -275,6 +292,9 @@ public class UAVObjectField { return options.get(val); } + case BITFIELD: + return ((List) data).get(index).intValue(); + case STRING: { //throw new Exception("Shit I should do this"); @@ -354,6 +374,12 @@ public class UAVObjectField { l.set(index, val); break; } + case BITFIELD: + { + List l = (List) this.data; + l.set(index, bound(data).shortValue()); + break; + } case STRING: { //throw new Exception("Sorry I haven't implemented strings yet"); @@ -404,6 +430,8 @@ public class UAVObjectField { return true; case ENUM: return false; + case BITFIELD: + return true; case STRING: return false; default: @@ -430,6 +458,8 @@ public class UAVObjectField { return false; case ENUM: return true; + case BITFIELD: + return false; case STRING: return true; default: @@ -493,6 +523,12 @@ public class UAVObjectField { ((ArrayList) data).add((float) 0); } break; + case BITFIELD: + ((ArrayList) data).clear(); + for(int index = 0; index < numElements; ++index) { + ((ArrayList) data).add((short) 0); + } + break; case ENUM: ((ArrayList) data).clear(); for(int index = 0; index < numElements; ++index) { @@ -549,6 +585,10 @@ public class UAVObjectField { data = (Object) new ArrayList(this.numElements); numBytesPerElement = 1; break; + case BITFIELD: + data = (Object) new ArrayList(this.numElements); + numBytesPerElement = 1; + break; case STRING: data = (Object) new ArrayList(this.numElements); numBytesPerElement = 1; @@ -614,6 +654,12 @@ public class UAVObjectField { if(num > 4294967295L) return 4294967295L; return num; + case BITFIELD: + if(num < 0) + return (long) 0; + if(num > 255) + return (long) 255; + return num; } return num; From 9960411ead0ae7176cef4b2c3b0e3cf3345908f1 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 2 Aug 2012 12:49:34 -0500 Subject: [PATCH 172/284] Finish porting the meta data changes from GCS and update all the UAVOs --- .../src/org/openpilot/uavtalk/Telemetry.java | 29 +- .../openpilot/uavtalk/TelemetryMonitor.java | 37 ++- .../src/org/openpilot/uavtalk/UAVObject.java | 194 +++++++++++- .../org/openpilot/uavtalk/UAVObjectField.java | 2 +- .../uavtalk/uavobjects/AccessoryDesired.java | 23 +- .../uavtalk/uavobjects/ActuatorCommand.java | 23 +- .../uavtalk/uavobjects/ActuatorDesired.java | 23 +- .../uavtalk/uavobjects/ActuatorSettings.java | 280 +----------------- .../uavtalk/uavobjects/AttitudeActual.java | 23 +- .../uavtalk/uavobjects/AttitudeSettings.java | 23 +- .../uavtalk/uavobjects/BaroAltitude.java | 23 +- .../uavtalk/uavobjects/CameraDesired.java | 23 +- .../uavobjects/CameraStabSettings.java | 23 +- .../uavtalk/uavobjects/FaultSettings.java | 23 +- .../uavtalk/uavobjects/FirmwareIAPObj.java | 23 +- .../uavobjects/FlightBatterySettings.java | 36 ++- .../uavobjects/FlightBatteryState.java | 30 +- .../uavtalk/uavobjects/FlightPlanControl.java | 23 +- .../uavobjects/FlightPlanSettings.java | 23 +- .../uavtalk/uavobjects/FlightPlanStatus.java | 23 +- .../uavtalk/uavobjects/FlightStatus.java | 26 +- .../uavobjects/FlightTelemetryStats.java | 23 +- .../uavtalk/uavobjects/GCSReceiver.java | 27 +- .../uavtalk/uavobjects/GCSTelemetryStats.java | 23 +- .../uavtalk/uavobjects/GPSPosition.java | 23 +- .../uavtalk/uavobjects/GPSSatellites.java | 23 +- .../openpilot/uavtalk/uavobjects/GPSTime.java | 23 +- .../uavtalk/uavobjects/GuidanceSettings.java | 211 ------------- .../uavtalk/uavobjects/HomeLocation.java | 23 +- .../uavtalk/uavobjects/HwSettings.java | 44 +-- .../uavtalk/uavobjects/I2CStats.java | 23 +- .../uavobjects/ManualControlCommand.java | 23 +- .../uavobjects/ManualControlSettings.java | 48 ++- .../uavtalk/uavobjects/MixerSettings.java | 23 +- .../uavtalk/uavobjects/MixerStatus.java | 23 +- .../uavtalk/uavobjects/NedAccel.java | 23 +- .../uavtalk/uavobjects/ObjectPersistence.java | 26 +- .../uavtalk/uavobjects/PositionActual.java | 23 +- .../uavtalk/uavobjects/PositionDesired.java | 147 --------- .../uavtalk/uavobjects/RateDesired.java | 23 +- .../uavtalk/uavobjects/ReceiverActivity.java | 23 +- .../uavtalk/uavobjects/SonarAltitude.java | 23 +- .../uavobjects/StabilizationDesired.java | 26 +- .../uavobjects/StabilizationSettings.java | 78 ++++- .../uavtalk/uavobjects/SystemAlarms.java | 29 +- .../uavtalk/uavobjects/SystemSettings.java | 34 ++- .../uavtalk/uavobjects/SystemStats.java | 23 +- .../uavtalk/uavobjects/TaskInfo.java | 40 +-- .../uavobjects/UAVObjectsInitialize.java | 21 +- .../uavtalk/uavobjects/VelocityActual.java | 23 +- .../uavtalk/uavobjects/VelocityDesired.java | 23 +- .../uavtalk/uavobjects/WatchdogStatus.java | 23 +- .../templates/uavobjecttemplate.java | 23 +- 53 files changed, 880 insertions(+), 1244 deletions(-) delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java delete mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 1395a5c08..2ee5ab9a4 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -10,8 +10,6 @@ import java.util.Queue; import java.util.Timer; import java.util.TimerTask; -import org.openpilot.uavtalk.UAVObject.Acked; - import android.util.Log; public class Telemetry { @@ -20,7 +18,7 @@ public class Telemetry { public static int LOGLEVEL = 0; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; - + public class TelemetryStats { public int txBytes; public int rxBytes; @@ -50,7 +48,7 @@ public class Telemetry { boolean allInstances; boolean objRequest; int retriesRemaining; - Acked acked; + boolean acked; } ; /** @@ -249,7 +247,7 @@ public class Telemetry { // Setup object depending on update mode int eventMask; - if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_PERIODIC ) + if ( metadata.GetGcsTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_PERIODIC ) { // Set update period setUpdatePeriod(obj, metadata.gcsTelemetryUpdatePeriod); @@ -260,7 +258,7 @@ public class Telemetry { connectToObjectInstances(obj, eventMask); } - else if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE ) + else if ( metadata.GetGcsTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE ) { // Set update period setUpdatePeriod(obj, 0); @@ -271,7 +269,11 @@ public class Telemetry { connectToObjectInstances(obj, eventMask); } - else if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_MANUAL ) + else if ( metadata.GetGcsTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_THROTTLED ) + { + // TODO + } + else if ( metadata.GetGcsTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_MANUAL ) { // Set update period setUpdatePeriod(obj, 0); @@ -282,13 +284,6 @@ public class Telemetry { connectToObjectInstances(obj, eventMask); } - else if ( metadata.gcsTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_NEVER ) - { - // Set update period - setUpdatePeriod(obj, 0); - // Disconnect from object - connectToObjectInstances(obj, 0); - } } /** @@ -360,10 +355,10 @@ public class Telemetry { } else { - utalk.sendObject(transInfo.obj, transInfo.acked == Acked.TRUE, transInfo.allInstances); + utalk.sendObject(transInfo.obj, transInfo.acked, transInfo.allInstances); } // Start timer if a response is expected - if ( transInfo.objRequest || transInfo.acked == Acked.TRUE ) + if ( transInfo.objRequest || transInfo.acked ) { transTimerSetPeriod(REQ_TIMEOUT_MS); } @@ -476,7 +471,7 @@ public class Telemetry { transInfo.obj = objInfo.obj; transInfo.allInstances = objInfo.allInstances; transInfo.retriesRemaining = MAX_RETRIES; - transInfo.acked = metadata.gcsTelemetryAcked; + transInfo.acked = metadata.GetGcsTelemetryAcked(); if ( objInfo.event == EV_UPDATED || objInfo.event == EV_UPDATED_MANUAL ) { transInfo.objRequest = false; diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index 87a0cdc70..d1d7a9c44 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -76,27 +76,24 @@ public class TelemetryMonitor extends Observable{ List instList = objListIterator.next(); UAVObject obj = instList.get(0); UAVObject.Metadata mdata = obj.getMetadata(); - if ( mdata.gcsTelemetryUpdateMode != UAVObject.UpdateMode.UPDATEMODE_NEVER ) + if ( obj.isMetadata() ) { - if ( obj.isMetadata() ) - { - queue.add(obj); - } - else /* Data object */ - { - UAVDataObject dobj = (UAVDataObject) obj; - if ( dobj.isSettings() ) - { - queue.add(obj); - } - else - { - if ( mdata.flightTelemetryUpdateMode == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE ) - { - queue.add(obj); - } - } - } + queue.add(obj); + } + else /* Data object */ + { + UAVDataObject dobj = (UAVDataObject) obj; + if ( dobj.isSettings() ) + { + queue.add(obj); + } + else + { + if ( mdata.GetFlightTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE ) + { + queue.add(obj); + } + } } } // Start retrieving diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 20d4cb02a..28c279040 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -133,7 +133,15 @@ public abstract class UAVObject { ACCESS_READWRITE, ACCESS_READONLY }; - public final class Metadata { + public final static int UAVOBJ_ACCESS_SHIFT = 0; + public final static int UAVOBJ_GCS_ACCESS_SHIFT = 1; + public final static int UAVOBJ_TELEMETRY_ACKED_SHIFT = 2; + public final static int UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT = 3; + public final static int UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT = 4; + public final static int UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT = 6; + public final static int UAVOBJ_UPDATE_MODE_MASK = 0x3; + + public final static class Metadata { /** * Object metadata, each object has a meta object that holds its metadata. The metadata define * properties for each object and can be used by multiple modules (e.g. telemetry and logger) @@ -164,6 +172,190 @@ public abstract class UAVObject { * Update period used by the logging module (only if logging mode is * PERIODIC) */ + + /** + * @brief Helper method for metadata accessors + * @param var The starting value + * @param shift The offset of these bits + * @param value The new value + * @param mask The mask of these bits + * @return + */ + private void SET_BITS(int shift, int value, int mask) { + this.flags = (this.flags & ~(mask << shift)) | (value << shift); + } + + /** + * Get the UAVObject metadata access member + * \return the access type + */ + public AccessMode GetFlightAccess() + { + return AccessModeEnum((this.flags >> UAVOBJ_ACCESS_SHIFT) & 1); + } + + /** + * Set the UAVObject metadata access member + * \param[in] mode The access mode + */ + public void SetFlightAccess(Metadata metadata, AccessMode mode) + { + // Need to convert java enums which have no numeric value to bits + SET_BITS(UAVOBJ_ACCESS_SHIFT, AccessModeNum(mode), 1); + } + + /** + * Get the UAVObject metadata GCS access member + * \return the GCS access type + */ + public AccessMode GetGcsAccess() + { + return AccessModeEnum((this.flags >> UAVOBJ_GCS_ACCESS_SHIFT) & 1); + } + + /** + * Set the UAVObject metadata GCS access member + * \param[in] mode The access mode + */ + public void SetGcsAccess(Metadata metadata, AccessMode mode) { + // Need to convert java enums which have no numeric value to bits + SET_BITS(UAVOBJ_GCS_ACCESS_SHIFT, AccessModeNum(mode), 1); + } + + /** + * Get the UAVObject metadata telemetry acked member + * \return the telemetry acked boolean + */ + public boolean GetFlightTelemetryAcked() { + return (((this.flags >> UAVOBJ_TELEMETRY_ACKED_SHIFT) & 1) == 1); + } + + /** + * Set the UAVObject metadata telemetry acked member + * \param[in] val The telemetry acked boolean + */ + public void SetFlightTelemetryAcked(boolean val) { + SET_BITS(UAVOBJ_TELEMETRY_ACKED_SHIFT, val ? 1 : 0, 1); + } + + /** + * Get the UAVObject metadata GCS telemetry acked member + * \return the telemetry acked boolean + */ + public boolean GetGcsTelemetryAcked() { + return ((this.flags >> UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT) & 1) == 1; + } + + /** + * Set the UAVObject metadata GCS telemetry acked member + * \param[in] val The GCS telemetry acked boolean + */ + public void SetGcsTelemetryAcked(boolean val) { + SET_BITS(UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT, val ? 1 : 0, 1); + } + + /** + * Maps from the bitfield number to the symbolic java enumeration + * @param num The value in the bitfield after shifting + * @return The update mode + */ + public static AccessMode AccessModeEnum(int num) { + switch(num) { + case 0: + return AccessMode.ACCESS_READONLY; + case 1: + return AccessMode.ACCESS_READWRITE; + } + return AccessMode.ACCESS_READONLY; + } + + /** + * Maps from the java symbolic enumeration of update mode to the bitfield value + * @param e The update mode + * @return The numeric value to use on the wire + */ + public static int AccessModeNum(AccessMode e) { + switch(e) { + case ACCESS_READONLY: + return 0; + case ACCESS_READWRITE: + return 1; + } + return 0; + } + + /** + * Maps from the bitfield number to the symbolic java enumeration + * @param num The value in the bitfield after shifting + * @return The update mode + */ + public static UpdateMode UpdateModeEnum(int num) { + switch(num) { + case 0: + return UpdateMode.UPDATEMODE_MANUAL; + case 1: + return UpdateMode.UPDATEMODE_PERIODIC; + case 2: + return UpdateMode.UPDATEMODE_ONCHANGE; + default: + return UpdateMode.UPDATEMODE_THROTTLED; + } + } + + /** + * Maps from the java symbolic enumeration of update mode to the bitfield value + * @param e The update mode + * @return The numeric value to use on the wire + */ + public static int UpdateModeNum(UpdateMode e) { + switch(e) { + case UPDATEMODE_MANUAL: + return 0; + case UPDATEMODE_PERIODIC: + return 1; + case UPDATEMODE_ONCHANGE: + return 2; + case UPDATEMODE_THROTTLED: + return 3; + } + return 0; + } + + /** + * Get the UAVObject metadata telemetry update mode + * \return the telemetry update mode + */ + public UpdateMode GetFlightTelemetryUpdateMode() { + return UpdateModeEnum((this.flags >> UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT) & UAVOBJ_UPDATE_MODE_MASK); + } + + /** + * Set the UAVObject metadata telemetry update mode member + * \param[in] metadata The metadata object + * \param[in] val The telemetry update mode + */ + public void SetFlightTelemetryUpdateMode(UpdateMode val) { + SET_BITS(UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT, UpdateModeNum(val), UAVOBJ_UPDATE_MODE_MASK); + } + + /** + * Get the UAVObject metadata GCS telemetry update mode + * \param[in] metadata The metadata object + * \return the GCS telemetry update mode + */ + public UpdateMode GetGcsTelemetryUpdateMode() { + return UpdateModeEnum((this.flags >> UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT) & UAVOBJ_UPDATE_MODE_MASK); + } + + /** + * Set the UAVObject metadata GCS telemetry update mode member + * \param[in] metadata The metadata object + * \param[in] val The GCS telemetry update mode + */ + public void SetGcsTelemetryUpdateMode(UpdateMode val) { + SET_BITS(UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT, UpdateModeNum(val), UAVOBJ_UPDATE_MODE_MASK); + } + }; public UAVObject(int objID, Boolean isSingleInst, String name) { diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index c2965f6cc..3ed221079 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -314,7 +314,7 @@ public class UAVObjectField { // Get metadata UAVObject.Metadata mdata = obj.getMetadata(); // Update value if the access mode permits - if ( mdata.gcsAccess == UAVObject.AccessMode.ACCESS_READWRITE ) + if ( mdata.GetGcsAccess() == UAVObject.AccessMode.ACCESS_READWRITE ) { switch (type) { diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java index 13c63dfdd..4b7c875a7 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AccessoryDesired.java @@ -78,18 +78,17 @@ public class AccessoryDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java index 08f2ebefe..0120e0ce7 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorCommand.java @@ -99,18 +99,17 @@ public class ActuatorCommand extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java index 03ff1985c..a00517906 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorDesired.java @@ -98,18 +98,17 @@ public class ActuatorDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java index 71b0bb49f..2257da346 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ActuatorSettings.java @@ -97,246 +97,6 @@ public class ActuatorSettings extends UAVDataObject { ChannelMinElemNames.add("9"); fields.add( new UAVObjectField("ChannelMin", "us", UAVObjectField.FieldType.INT16, ChannelMinElemNames, null) ); - List FixedWingRoll1ElemNames = new ArrayList(); - FixedWingRoll1ElemNames.add("0"); - List FixedWingRoll1EnumOptions = new ArrayList(); - FixedWingRoll1EnumOptions.add("Channel1"); - FixedWingRoll1EnumOptions.add("Channel2"); - FixedWingRoll1EnumOptions.add("Channel3"); - FixedWingRoll1EnumOptions.add("Channel4"); - FixedWingRoll1EnumOptions.add("Channel5"); - FixedWingRoll1EnumOptions.add("Channel6"); - FixedWingRoll1EnumOptions.add("Channel7"); - FixedWingRoll1EnumOptions.add("Channel8"); - FixedWingRoll1EnumOptions.add("Channel9"); - FixedWingRoll1EnumOptions.add("Channel10"); - FixedWingRoll1EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingRoll1", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll1ElemNames, FixedWingRoll1EnumOptions) ); - - List FixedWingRoll2ElemNames = new ArrayList(); - FixedWingRoll2ElemNames.add("0"); - List FixedWingRoll2EnumOptions = new ArrayList(); - FixedWingRoll2EnumOptions.add("Channel1"); - FixedWingRoll2EnumOptions.add("Channel2"); - FixedWingRoll2EnumOptions.add("Channel3"); - FixedWingRoll2EnumOptions.add("Channel4"); - FixedWingRoll2EnumOptions.add("Channel5"); - FixedWingRoll2EnumOptions.add("Channel6"); - FixedWingRoll2EnumOptions.add("Channel7"); - FixedWingRoll2EnumOptions.add("Channel8"); - FixedWingRoll2EnumOptions.add("Channel9"); - FixedWingRoll2EnumOptions.add("Channel10"); - FixedWingRoll2EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingRoll2", "channel", UAVObjectField.FieldType.ENUM, FixedWingRoll2ElemNames, FixedWingRoll2EnumOptions) ); - - List FixedWingPitch1ElemNames = new ArrayList(); - FixedWingPitch1ElemNames.add("0"); - List FixedWingPitch1EnumOptions = new ArrayList(); - FixedWingPitch1EnumOptions.add("Channel1"); - FixedWingPitch1EnumOptions.add("Channel2"); - FixedWingPitch1EnumOptions.add("Channel3"); - FixedWingPitch1EnumOptions.add("Channel4"); - FixedWingPitch1EnumOptions.add("Channel5"); - FixedWingPitch1EnumOptions.add("Channel6"); - FixedWingPitch1EnumOptions.add("Channel7"); - FixedWingPitch1EnumOptions.add("Channel8"); - FixedWingPitch1EnumOptions.add("Channel9"); - FixedWingPitch1EnumOptions.add("Channel10"); - FixedWingPitch1EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingPitch1", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch1ElemNames, FixedWingPitch1EnumOptions) ); - - List FixedWingPitch2ElemNames = new ArrayList(); - FixedWingPitch2ElemNames.add("0"); - List FixedWingPitch2EnumOptions = new ArrayList(); - FixedWingPitch2EnumOptions.add("Channel1"); - FixedWingPitch2EnumOptions.add("Channel2"); - FixedWingPitch2EnumOptions.add("Channel3"); - FixedWingPitch2EnumOptions.add("Channel4"); - FixedWingPitch2EnumOptions.add("Channel5"); - FixedWingPitch2EnumOptions.add("Channel6"); - FixedWingPitch2EnumOptions.add("Channel7"); - FixedWingPitch2EnumOptions.add("Channel8"); - FixedWingPitch2EnumOptions.add("Channel9"); - FixedWingPitch2EnumOptions.add("Channel10"); - FixedWingPitch2EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingPitch2", "channel", UAVObjectField.FieldType.ENUM, FixedWingPitch2ElemNames, FixedWingPitch2EnumOptions) ); - - List FixedWingYaw1ElemNames = new ArrayList(); - FixedWingYaw1ElemNames.add("0"); - List FixedWingYaw1EnumOptions = new ArrayList(); - FixedWingYaw1EnumOptions.add("Channel1"); - FixedWingYaw1EnumOptions.add("Channel2"); - FixedWingYaw1EnumOptions.add("Channel3"); - FixedWingYaw1EnumOptions.add("Channel4"); - FixedWingYaw1EnumOptions.add("Channel5"); - FixedWingYaw1EnumOptions.add("Channel6"); - FixedWingYaw1EnumOptions.add("Channel7"); - FixedWingYaw1EnumOptions.add("Channel8"); - FixedWingYaw1EnumOptions.add("Channel9"); - FixedWingYaw1EnumOptions.add("Channel10"); - FixedWingYaw1EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingYaw1", "channel", UAVObjectField.FieldType.ENUM, FixedWingYaw1ElemNames, FixedWingYaw1EnumOptions) ); - - List FixedWingYaw2ElemNames = new ArrayList(); - FixedWingYaw2ElemNames.add("0"); - List FixedWingYaw2EnumOptions = new ArrayList(); - FixedWingYaw2EnumOptions.add("Channel1"); - FixedWingYaw2EnumOptions.add("Channel2"); - FixedWingYaw2EnumOptions.add("Channel3"); - FixedWingYaw2EnumOptions.add("Channel4"); - FixedWingYaw2EnumOptions.add("Channel5"); - FixedWingYaw2EnumOptions.add("Channel6"); - FixedWingYaw2EnumOptions.add("Channel7"); - FixedWingYaw2EnumOptions.add("Channel8"); - FixedWingYaw2EnumOptions.add("Channel9"); - FixedWingYaw2EnumOptions.add("Channel10"); - FixedWingYaw2EnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingYaw2", "channel", UAVObjectField.FieldType.ENUM, FixedWingYaw2ElemNames, FixedWingYaw2EnumOptions) ); - - List FixedWingThrottleElemNames = new ArrayList(); - FixedWingThrottleElemNames.add("0"); - List FixedWingThrottleEnumOptions = new ArrayList(); - FixedWingThrottleEnumOptions.add("Channel1"); - FixedWingThrottleEnumOptions.add("Channel2"); - FixedWingThrottleEnumOptions.add("Channel3"); - FixedWingThrottleEnumOptions.add("Channel4"); - FixedWingThrottleEnumOptions.add("Channel5"); - FixedWingThrottleEnumOptions.add("Channel6"); - FixedWingThrottleEnumOptions.add("Channel7"); - FixedWingThrottleEnumOptions.add("Channel8"); - FixedWingThrottleEnumOptions.add("Channel9"); - FixedWingThrottleEnumOptions.add("Channel10"); - FixedWingThrottleEnumOptions.add("None"); - fields.add( new UAVObjectField("FixedWingThrottle", "channel", UAVObjectField.FieldType.ENUM, FixedWingThrottleElemNames, FixedWingThrottleEnumOptions) ); - - List VTOLMotorNElemNames = new ArrayList(); - VTOLMotorNElemNames.add("0"); - List VTOLMotorNEnumOptions = new ArrayList(); - VTOLMotorNEnumOptions.add("Channel1"); - VTOLMotorNEnumOptions.add("Channel2"); - VTOLMotorNEnumOptions.add("Channel3"); - VTOLMotorNEnumOptions.add("Channel4"); - VTOLMotorNEnumOptions.add("Channel5"); - VTOLMotorNEnumOptions.add("Channel6"); - VTOLMotorNEnumOptions.add("Channel7"); - VTOLMotorNEnumOptions.add("Channel8"); - VTOLMotorNEnumOptions.add("Channel9"); - VTOLMotorNEnumOptions.add("Channel10"); - VTOLMotorNEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorN", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNElemNames, VTOLMotorNEnumOptions) ); - - List VTOLMotorNEElemNames = new ArrayList(); - VTOLMotorNEElemNames.add("0"); - List VTOLMotorNEEnumOptions = new ArrayList(); - VTOLMotorNEEnumOptions.add("Channel1"); - VTOLMotorNEEnumOptions.add("Channel2"); - VTOLMotorNEEnumOptions.add("Channel3"); - VTOLMotorNEEnumOptions.add("Channel4"); - VTOLMotorNEEnumOptions.add("Channel5"); - VTOLMotorNEEnumOptions.add("Channel6"); - VTOLMotorNEEnumOptions.add("Channel7"); - VTOLMotorNEEnumOptions.add("Channel8"); - VTOLMotorNEEnumOptions.add("Channel9"); - VTOLMotorNEEnumOptions.add("Channel10"); - VTOLMotorNEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorNE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNEElemNames, VTOLMotorNEEnumOptions) ); - - List VTOLMotorEElemNames = new ArrayList(); - VTOLMotorEElemNames.add("0"); - List VTOLMotorEEnumOptions = new ArrayList(); - VTOLMotorEEnumOptions.add("Channel1"); - VTOLMotorEEnumOptions.add("Channel2"); - VTOLMotorEEnumOptions.add("Channel3"); - VTOLMotorEEnumOptions.add("Channel4"); - VTOLMotorEEnumOptions.add("Channel5"); - VTOLMotorEEnumOptions.add("Channel6"); - VTOLMotorEEnumOptions.add("Channel7"); - VTOLMotorEEnumOptions.add("Channel8"); - VTOLMotorEEnumOptions.add("Channel9"); - VTOLMotorEEnumOptions.add("Channel10"); - VTOLMotorEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorEElemNames, VTOLMotorEEnumOptions) ); - - List VTOLMotorSEElemNames = new ArrayList(); - VTOLMotorSEElemNames.add("0"); - List VTOLMotorSEEnumOptions = new ArrayList(); - VTOLMotorSEEnumOptions.add("Channel1"); - VTOLMotorSEEnumOptions.add("Channel2"); - VTOLMotorSEEnumOptions.add("Channel3"); - VTOLMotorSEEnumOptions.add("Channel4"); - VTOLMotorSEEnumOptions.add("Channel5"); - VTOLMotorSEEnumOptions.add("Channel6"); - VTOLMotorSEEnumOptions.add("Channel7"); - VTOLMotorSEEnumOptions.add("Channel8"); - VTOLMotorSEEnumOptions.add("Channel9"); - VTOLMotorSEEnumOptions.add("Channel10"); - VTOLMotorSEEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorSE", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSEElemNames, VTOLMotorSEEnumOptions) ); - - List VTOLMotorSElemNames = new ArrayList(); - VTOLMotorSElemNames.add("0"); - List VTOLMotorSEnumOptions = new ArrayList(); - VTOLMotorSEnumOptions.add("Channel1"); - VTOLMotorSEnumOptions.add("Channel2"); - VTOLMotorSEnumOptions.add("Channel3"); - VTOLMotorSEnumOptions.add("Channel4"); - VTOLMotorSEnumOptions.add("Channel5"); - VTOLMotorSEnumOptions.add("Channel6"); - VTOLMotorSEnumOptions.add("Channel7"); - VTOLMotorSEnumOptions.add("Channel8"); - VTOLMotorSEnumOptions.add("Channel9"); - VTOLMotorSEnumOptions.add("Channel10"); - VTOLMotorSEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorS", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSElemNames, VTOLMotorSEnumOptions) ); - - List VTOLMotorSWElemNames = new ArrayList(); - VTOLMotorSWElemNames.add("0"); - List VTOLMotorSWEnumOptions = new ArrayList(); - VTOLMotorSWEnumOptions.add("Channel1"); - VTOLMotorSWEnumOptions.add("Channel2"); - VTOLMotorSWEnumOptions.add("Channel3"); - VTOLMotorSWEnumOptions.add("Channel4"); - VTOLMotorSWEnumOptions.add("Channel5"); - VTOLMotorSWEnumOptions.add("Channel6"); - VTOLMotorSWEnumOptions.add("Channel7"); - VTOLMotorSWEnumOptions.add("Channel8"); - VTOLMotorSWEnumOptions.add("Channel9"); - VTOLMotorSWEnumOptions.add("Channel10"); - VTOLMotorSWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorSW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorSWElemNames, VTOLMotorSWEnumOptions) ); - - List VTOLMotorWElemNames = new ArrayList(); - VTOLMotorWElemNames.add("0"); - List VTOLMotorWEnumOptions = new ArrayList(); - VTOLMotorWEnumOptions.add("Channel1"); - VTOLMotorWEnumOptions.add("Channel2"); - VTOLMotorWEnumOptions.add("Channel3"); - VTOLMotorWEnumOptions.add("Channel4"); - VTOLMotorWEnumOptions.add("Channel5"); - VTOLMotorWEnumOptions.add("Channel6"); - VTOLMotorWEnumOptions.add("Channel7"); - VTOLMotorWEnumOptions.add("Channel8"); - VTOLMotorWEnumOptions.add("Channel9"); - VTOLMotorWEnumOptions.add("Channel10"); - VTOLMotorWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorWElemNames, VTOLMotorWEnumOptions) ); - - List VTOLMotorNWElemNames = new ArrayList(); - VTOLMotorNWElemNames.add("0"); - List VTOLMotorNWEnumOptions = new ArrayList(); - VTOLMotorNWEnumOptions.add("Channel1"); - VTOLMotorNWEnumOptions.add("Channel2"); - VTOLMotorNWEnumOptions.add("Channel3"); - VTOLMotorNWEnumOptions.add("Channel4"); - VTOLMotorNWEnumOptions.add("Channel5"); - VTOLMotorNWEnumOptions.add("Channel6"); - VTOLMotorNWEnumOptions.add("Channel7"); - VTOLMotorNWEnumOptions.add("Channel8"); - VTOLMotorNWEnumOptions.add("Channel9"); - VTOLMotorNWEnumOptions.add("Channel10"); - VTOLMotorNWEnumOptions.add("None"); - fields.add( new UAVObjectField("VTOLMotorNW", "channel", UAVObjectField.FieldType.ENUM, VTOLMotorNWElemNames, VTOLMotorNWEnumOptions) ); - List ChannelTypeElemNames = new ArrayList(); ChannelTypeElemNames.add("0"); ChannelTypeElemNames.add("1"); @@ -398,18 +158,17 @@ public class ActuatorSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -454,21 +213,6 @@ public class ActuatorSettings extends UAVDataObject { getField("ChannelMin").setValue(1000,7); getField("ChannelMin").setValue(1000,8); getField("ChannelMin").setValue(1000,9); - getField("FixedWingRoll1").setValue("None"); - getField("FixedWingRoll2").setValue("None"); - getField("FixedWingPitch1").setValue("None"); - getField("FixedWingPitch2").setValue("None"); - getField("FixedWingYaw1").setValue("None"); - getField("FixedWingYaw2").setValue("None"); - getField("FixedWingThrottle").setValue("None"); - getField("VTOLMotorN").setValue("None"); - getField("VTOLMotorNE").setValue("None"); - getField("VTOLMotorE").setValue("None"); - getField("VTOLMotorSE").setValue("None"); - getField("VTOLMotorS").setValue("None"); - getField("VTOLMotorSW").setValue("None"); - getField("VTOLMotorW").setValue("None"); - getField("VTOLMotorNW").setValue("None"); getField("ChannelType").setValue("PWM",0); getField("ChannelType").setValue("PWM",1); getField("ChannelType").setValue("PWM",2); @@ -518,7 +262,7 @@ public class ActuatorSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0xF2875746; + protected static final int OBJID = 0x7D555646; protected static final String NAME = "ActuatorSettings"; protected static String DESCRIPTION = "Settings for the @ref ActuatorModule that controls the channel assignments for the mixer based on AircraftType"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java index 7c9272cad..b117e501a 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeActual.java @@ -102,18 +102,17 @@ public class AttitudeActual extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 100; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 100; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java index 3034a99ad..9bcce7bf3 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSettings.java @@ -130,18 +130,17 @@ public class AttitudeSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java index ecde53985..cd649f84c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAltitude.java @@ -86,18 +86,17 @@ public class BaroAltitude extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java index 7a36ec1ea..34c23e612 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraDesired.java @@ -86,18 +86,17 @@ public class CameraDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java index a8e03df32..0b2f3b3f5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/CameraStabSettings.java @@ -125,18 +125,17 @@ public class CameraStabSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java index b22b8185e..8da58f793 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FaultSettings.java @@ -85,18 +85,17 @@ public class FaultSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java index 71c681bd2..58fadcee5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java @@ -152,18 +152,17 @@ public class FirmwareIAPObj extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java index a3bc23eb3..850f64103 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java @@ -80,9 +80,12 @@ public class FlightBatterySettings extends UAVDataObject { fields.add( new UAVObjectField("NbCells", "", UAVObjectField.FieldType.UINT8, NbCellsElemNames, null) ); List SensorTypeElemNames = new ArrayList(); - SensorTypeElemNames.add("0"); + SensorTypeElemNames.add("BatteryCurrent"); + SensorTypeElemNames.add("BatteryVoltage"); + SensorTypeElemNames.add("BoardVoltage"); List SensorTypeEnumOptions = new ArrayList(); - SensorTypeEnumOptions.add("None"); + SensorTypeEnumOptions.add("Disabled"); + SensorTypeEnumOptions.add("Enabled"); fields.add( new UAVObjectField("SensorType", "", UAVObjectField.FieldType.ENUM, SensorTypeElemNames, SensorTypeEnumOptions) ); @@ -108,18 +111,17 @@ public class FlightBatterySettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -137,7 +139,9 @@ public class FlightBatterySettings extends UAVDataObject { getField("SensorCalibrations").setValue(1,1); getField("Type").setValue("LiPo"); getField("NbCells").setValue(3); - getField("SensorType").setValue("None"); + getField("SensorType").setValue("Disabled",0); + getField("SensorType").setValue("Disabled",1); + getField("SensorType").setValue("Disabled",2); } @@ -166,7 +170,7 @@ public class FlightBatterySettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0xF172BB18; + protected static final int OBJID = 0x94AC6AD2; protected static final String NAME = "FlightBatterySettings"; protected static String DESCRIPTION = "Flight Battery configuration."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java index 82fcfae47..d54648ad5 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java @@ -59,6 +59,10 @@ public class FlightBatteryState extends UAVDataObject { CurrentElemNames.add("0"); fields.add( new UAVObjectField("Current", "A", UAVObjectField.FieldType.FLOAT32, CurrentElemNames, null) ); + List BoardSupplyVoltageElemNames = new ArrayList(); + BoardSupplyVoltageElemNames.add("0"); + fields.add( new UAVObjectField("BoardSupplyVoltage", "V", UAVObjectField.FieldType.FLOAT32, BoardSupplyVoltageElemNames, null) ); + List PeakCurrentElemNames = new ArrayList(); PeakCurrentElemNames.add("0"); fields.add( new UAVObjectField("PeakCurrent", "A", UAVObjectField.FieldType.FLOAT32, PeakCurrentElemNames, null) ); @@ -98,18 +102,17 @@ public class FlightBatteryState extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READONLY; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READONLY) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -122,6 +125,7 @@ public class FlightBatteryState extends UAVDataObject { { getField("Voltage").setValue(0); getField("Current").setValue(0); + getField("BoardSupplyVoltage").setValue(0); getField("PeakCurrent").setValue(0); getField("AvgCurrent").setValue(0); getField("ConsumedEnergy").setValue(0); @@ -154,7 +158,7 @@ public class FlightBatteryState extends UAVDataObject { } // Constants - protected static final int OBJID = 0x8C0D756; + protected static final int OBJID = 0xD2083596; protected static final String NAME = "FlightBatteryState"; protected static String DESCRIPTION = "Battery status information."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java index dbe959f96..cdea28a0f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanControl.java @@ -82,18 +82,17 @@ public class FlightPlanControl extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java index 6fc39a26e..184bbd1b7 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanSettings.java @@ -78,18 +78,17 @@ public class FlightPlanSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java index 7b78bce71..8aa152789 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightPlanStatus.java @@ -119,18 +119,17 @@ public class FlightPlanStatus extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 2000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 2000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java index ac3812aa6..38697e573 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java @@ -70,6 +70,7 @@ public class FlightStatus extends UAVDataObject { FlightModeEnumOptions.add("VelocityControl"); FlightModeEnumOptions.add("PositionHold"); FlightModeEnumOptions.add("PathPlanner"); + FlightModeEnumOptions.add("RTH"); fields.add( new UAVObjectField("FlightMode", "", UAVObjectField.FieldType.ENUM, FlightModeElemNames, FlightModeEnumOptions) ); @@ -95,18 +96,17 @@ public class FlightStatus extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 5000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 5000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -146,7 +146,7 @@ public class FlightStatus extends UAVDataObject { } // Constants - protected static final int OBJID = 0x19B92D8; + protected static final int OBJID = 0x884FEF66; protected static final String NAME = "FlightStatus"; protected static String DESCRIPTION = "Contains major flight status information for other modules."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java index 403ea1d5e..3a042f52e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightTelemetryStats.java @@ -103,18 +103,17 @@ public class FlightTelemetryStats extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 5000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 5000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 5000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 5000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java index 3cb3811ae..05fa87efb 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSReceiver.java @@ -58,6 +58,8 @@ public class GCSReceiver extends UAVDataObject { ChannelElemNames.add("3"); ChannelElemNames.add("4"); ChannelElemNames.add("5"); + ChannelElemNames.add("6"); + ChannelElemNames.add("7"); fields.add( new UAVObjectField("Channel", "us", UAVObjectField.FieldType.UINT16, ChannelElemNames, null) ); @@ -83,18 +85,17 @@ public class GCSReceiver extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READONLY; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -133,7 +134,7 @@ public class GCSReceiver extends UAVDataObject { } // Constants - protected static final int OBJID = 0xCC7E2BBC; + protected static final int OBJID = 0xCC7E1470; protected static final String NAME = "GCSReceiver"; protected static String DESCRIPTION = "A receiver channel group carried over the telemetry link."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java index b32f551ce..754272c8c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GCSTelemetryStats.java @@ -103,18 +103,17 @@ public class GCSTelemetryStats extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.gcsTelemetryUpdatePeriod = 5000; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 5000; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java index 5f4e20b46..c2c8544a9 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSPosition.java @@ -123,18 +123,17 @@ public class GPSPosition extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java index bb331132d..0f5b0161a 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSatellites.java @@ -154,18 +154,17 @@ public class GPSSatellites extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 10000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 30000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 10000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 30000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java index 5aa4df7bf..7095aa18e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSTime.java @@ -98,18 +98,17 @@ public class GPSTime extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 10000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 30000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 10000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 30000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java deleted file mode 100644 index 5510a901d..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GuidanceSettings.java +++ /dev/null @@ -1,211 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * Settings for the @ref GuidanceModule - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -Settings for the @ref GuidanceModule - -generated from guidancesettings.xml - **/ -public class GuidanceSettings extends UAVDataObject { - - public GuidanceSettings() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List HorizontalPosPIElemNames = new ArrayList(); - HorizontalPosPIElemNames.add("Kp"); - HorizontalPosPIElemNames.add("Ki"); - HorizontalPosPIElemNames.add("ILimit"); - fields.add( new UAVObjectField("HorizontalPosPI", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) ); - - List HorizontalVelPIDElemNames = new ArrayList(); - HorizontalVelPIDElemNames.add("Kp"); - HorizontalVelPIDElemNames.add("Ki"); - HorizontalVelPIDElemNames.add("Kd"); - HorizontalVelPIDElemNames.add("ILimit"); - fields.add( new UAVObjectField("HorizontalVelPID", "deg/(m/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); - - List VerticalPosPIElemNames = new ArrayList(); - VerticalPosPIElemNames.add("Kp"); - VerticalPosPIElemNames.add("Ki"); - VerticalPosPIElemNames.add("ILimit"); - fields.add( new UAVObjectField("VerticalPosPI", "", UAVObjectField.FieldType.FLOAT32, VerticalPosPIElemNames, null) ); - - List VerticalVelPIDElemNames = new ArrayList(); - VerticalVelPIDElemNames.add("Kp"); - VerticalVelPIDElemNames.add("Ki"); - VerticalVelPIDElemNames.add("Kd"); - VerticalVelPIDElemNames.add("ILimit"); - fields.add( new UAVObjectField("VerticalVelPID", "", UAVObjectField.FieldType.FLOAT32, VerticalVelPIDElemNames, null) ); - - List MaxRollPitchElemNames = new ArrayList(); - MaxRollPitchElemNames.add("0"); - fields.add( new UAVObjectField("MaxRollPitch", "deg", UAVObjectField.FieldType.FLOAT32, MaxRollPitchElemNames, null) ); - - List UpdatePeriodElemNames = new ArrayList(); - UpdatePeriodElemNames.add("0"); - fields.add( new UAVObjectField("UpdatePeriod", "", UAVObjectField.FieldType.INT32, UpdatePeriodElemNames, null) ); - - List HorizontalVelMaxElemNames = new ArrayList(); - HorizontalVelMaxElemNames.add("0"); - fields.add( new UAVObjectField("HorizontalVelMax", "m/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) ); - - List VerticalVelMaxElemNames = new ArrayList(); - VerticalVelMaxElemNames.add("0"); - fields.add( new UAVObjectField("VerticalVelMax", "m/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) ); - - List GuidanceModeElemNames = new ArrayList(); - GuidanceModeElemNames.add("0"); - List GuidanceModeEnumOptions = new ArrayList(); - GuidanceModeEnumOptions.add("DUAL_LOOP"); - GuidanceModeEnumOptions.add("VELOCITY_CONTROL"); - fields.add( new UAVObjectField("GuidanceMode", "", UAVObjectField.FieldType.ENUM, GuidanceModeElemNames, GuidanceModeEnumOptions) ); - - List ThrottleControlElemNames = new ArrayList(); - ThrottleControlElemNames.add("0"); - List ThrottleControlEnumOptions = new ArrayList(); - ThrottleControlEnumOptions.add("FALSE"); - ThrottleControlEnumOptions.add("TRUE"); - fields.add( new UAVObjectField("ThrottleControl", "", UAVObjectField.FieldType.ENUM, ThrottleControlElemNames, ThrottleControlEnumOptions) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - getField("HorizontalPosPI").setValue(0.1,0); - getField("HorizontalPosPI").setValue(0.001,1); - getField("HorizontalPosPI").setValue(300,2); - getField("HorizontalVelPID").setValue(0.05,0); - getField("HorizontalVelPID").setValue(0.002,1); - getField("HorizontalVelPID").setValue(0,2); - getField("HorizontalVelPID").setValue(1000,3); - getField("VerticalPosPI").setValue(0.1,0); - getField("VerticalPosPI").setValue(0.001,1); - getField("VerticalPosPI").setValue(200,2); - getField("VerticalVelPID").setValue(0.1,0); - getField("VerticalVelPID").setValue(0,1); - getField("VerticalVelPID").setValue(0,2); - getField("VerticalVelPID").setValue(0,3); - getField("MaxRollPitch").setValue(10); - getField("UpdatePeriod").setValue(100); - getField("HorizontalVelMax").setValue(300); - getField("VerticalVelMax").setValue(150); - getField("GuidanceMode").setValue("DUAL_LOOP"); - getField("ThrottleControl").setValue("FALSE"); - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - GuidanceSettings obj = new GuidanceSettings(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public GuidanceSettings GetInstance(UAVObjectManager objMngr, int instID) - { - return (GuidanceSettings)(objMngr.getObject(GuidanceSettings.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0x6EA79FB4; - protected static final String NAME = "GuidanceSettings"; - protected static String DESCRIPTION = "Settings for the @ref GuidanceModule"; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 1 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java index 3f3b3d8dd..0cd45db1b 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java @@ -103,18 +103,17 @@ public class HomeLocation extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java index f56982e69..9d8113846 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java @@ -190,14 +190,6 @@ public class HwSettings extends UAVDataObject { ComUsbBridgeSpeedEnumOptions.add("115200"); fields.add( new UAVObjectField("ComUsbBridgeSpeed", "bps", UAVObjectField.FieldType.ENUM, ComUsbBridgeSpeedElemNames, ComUsbBridgeSpeedEnumOptions) ); - List USB_DeviceTypeElemNames = new ArrayList(); - USB_DeviceTypeElemNames.add("0"); - List USB_DeviceTypeEnumOptions = new ArrayList(); - USB_DeviceTypeEnumOptions.add("HID-only"); - USB_DeviceTypeEnumOptions.add("HID+VCP"); - USB_DeviceTypeEnumOptions.add("VCP-only"); - fields.add( new UAVObjectField("USB_DeviceType", "descriptor", UAVObjectField.FieldType.ENUM, USB_DeviceTypeElemNames, USB_DeviceTypeEnumOptions) ); - List USB_HIDPortElemNames = new ArrayList(); USB_HIDPortElemNames.add("0"); List USB_HIDPortEnumOptions = new ArrayList(); @@ -219,7 +211,12 @@ public class HwSettings extends UAVDataObject { OptionalModulesElemNames.add("ComUsbBridge"); OptionalModulesElemNames.add("Fault"); OptionalModulesElemNames.add("Altitude"); + OptionalModulesElemNames.add("Airspeed"); OptionalModulesElemNames.add("TxPID"); + OptionalModulesElemNames.add("VtolPathFollower"); + OptionalModulesElemNames.add("FixedWingPathFollower"); + OptionalModulesElemNames.add("Battery"); + OptionalModulesElemNames.add("Overo"); List OptionalModulesEnumOptions = new ArrayList(); OptionalModulesEnumOptions.add("Disabled"); OptionalModulesEnumOptions.add("Enabled"); @@ -252,18 +249,17 @@ public class HwSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -286,7 +282,6 @@ public class HwSettings extends UAVDataObject { getField("TelemetrySpeed").setValue("57600"); getField("GPSSpeed").setValue("57600"); getField("ComUsbBridgeSpeed").setValue("57600"); - getField("USB_DeviceType").setValue("HID-only"); getField("USB_HIDPort").setValue("USBTelemetry"); getField("USB_VCPPort").setValue("Disabled"); getField("OptionalModules").setValue("Disabled",0); @@ -295,6 +290,11 @@ public class HwSettings extends UAVDataObject { getField("OptionalModules").setValue("Disabled",3); getField("OptionalModules").setValue("Disabled",4); getField("OptionalModules").setValue("Disabled",5); + getField("OptionalModules").setValue("Disabled",6); + getField("OptionalModules").setValue("Disabled",7); + getField("OptionalModules").setValue("Disabled",8); + getField("OptionalModules").setValue("Disabled",9); + getField("OptionalModules").setValue("Disabled",10); getField("DSMxBind").setValue(0); } @@ -324,7 +324,7 @@ public class HwSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x4730375C; + protected static final int OBJID = 0x5D950E50; protected static final String NAME = "HwSettings"; protected static String DESCRIPTION = "Selection of optional hardware configurations."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java index abd8f41f6..a09e4404d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/I2CStats.java @@ -177,18 +177,17 @@ public class I2CStats extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 10000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 30000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 10000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 30000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java index 6ac5a1b2c..5ce51c245 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlCommand.java @@ -113,18 +113,17 @@ public class ManualControlCommand extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 2000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 2000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java index c8f460bc4..47ebbc230 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java @@ -51,6 +51,10 @@ public class ManualControlSettings extends UAVDataObject { List fields = new ArrayList(); + List DeadbandElemNames = new ArrayList(); + DeadbandElemNames.add("0"); + fields.add( new UAVObjectField("Deadband", "%", UAVObjectField.FieldType.FLOAT32, DeadbandElemNames, null) ); + List ChannelMinElemNames = new ArrayList(); ChannelMinElemNames.add("Throttle"); ChannelMinElemNames.add("Roll"); @@ -146,6 +150,7 @@ public class ManualControlSettings extends UAVDataObject { Stabilization1SettingsEnumOptions.add("Attitude"); Stabilization1SettingsEnumOptions.add("AxisLock"); Stabilization1SettingsEnumOptions.add("WeakLeveling"); + Stabilization1SettingsEnumOptions.add("VirtualBar"); fields.add( new UAVObjectField("Stabilization1Settings", "", UAVObjectField.FieldType.ENUM, Stabilization1SettingsElemNames, Stabilization1SettingsEnumOptions) ); List Stabilization2SettingsElemNames = new ArrayList(); @@ -158,6 +163,7 @@ public class ManualControlSettings extends UAVDataObject { Stabilization2SettingsEnumOptions.add("Attitude"); Stabilization2SettingsEnumOptions.add("AxisLock"); Stabilization2SettingsEnumOptions.add("WeakLeveling"); + Stabilization2SettingsEnumOptions.add("VirtualBar"); fields.add( new UAVObjectField("Stabilization2Settings", "", UAVObjectField.FieldType.ENUM, Stabilization2SettingsElemNames, Stabilization2SettingsEnumOptions) ); List Stabilization3SettingsElemNames = new ArrayList(); @@ -170,6 +176,7 @@ public class ManualControlSettings extends UAVDataObject { Stabilization3SettingsEnumOptions.add("Attitude"); Stabilization3SettingsEnumOptions.add("AxisLock"); Stabilization3SettingsEnumOptions.add("WeakLeveling"); + Stabilization3SettingsEnumOptions.add("VirtualBar"); fields.add( new UAVObjectField("Stabilization3Settings", "", UAVObjectField.FieldType.ENUM, Stabilization3SettingsElemNames, Stabilization3SettingsEnumOptions) ); List FlightModePositionElemNames = new ArrayList(); @@ -185,8 +192,21 @@ public class ManualControlSettings extends UAVDataObject { FlightModePositionEnumOptions.add("VelocityControl"); FlightModePositionEnumOptions.add("PositionHold"); FlightModePositionEnumOptions.add("PathPlanner"); + FlightModePositionEnumOptions.add("RTH"); + FlightModePositionEnumOptions.add("Land"); fields.add( new UAVObjectField("FlightModePosition", "", UAVObjectField.FieldType.ENUM, FlightModePositionElemNames, FlightModePositionEnumOptions) ); + List FlightModeNumberElemNames = new ArrayList(); + FlightModeNumberElemNames.add("0"); + fields.add( new UAVObjectField("FlightModeNumber", "", UAVObjectField.FieldType.UINT8, FlightModeNumberElemNames, null) ); + + List FailsafeBehaviorElemNames = new ArrayList(); + FailsafeBehaviorElemNames.add("0"); + List FailsafeBehaviorEnumOptions = new ArrayList(); + FailsafeBehaviorEnumOptions.add("None"); + FailsafeBehaviorEnumOptions.add("RTH"); + fields.add( new UAVObjectField("FailsafeBehavior", "", UAVObjectField.FieldType.ENUM, FailsafeBehaviorElemNames, FailsafeBehaviorEnumOptions) ); + // Compute the number of bytes for this object int numBytes = 0; @@ -210,18 +230,17 @@ public class ManualControlSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -232,6 +251,7 @@ public class ManualControlSettings extends UAVDataObject { */ public void setDefaultFieldValues() { + getField("Deadband").setValue(0); getField("ChannelMin").setValue(1000,0); getField("ChannelMin").setValue(1000,1); getField("ChannelMin").setValue(1000,2); @@ -291,6 +311,8 @@ public class ManualControlSettings extends UAVDataObject { getField("FlightModePosition").setValue("Manual",0); getField("FlightModePosition").setValue("Stabilized1",1); getField("FlightModePosition").setValue("Stabilized2",2); + getField("FlightModeNumber").setValue(3); + getField("FailsafeBehavior").setValue("None"); } @@ -319,7 +341,7 @@ public class ManualControlSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x59C4551C; + protected static final int OBJID = 0x6C188320; protected static final String NAME = "ManualControlSettings"; protected static String DESCRIPTION = "Settings to indicate how to decode receiver input by @ref ManualControlModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java index 76841d8ff..094d91545 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerSettings.java @@ -372,18 +372,17 @@ public class MixerSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java index 80e3b15bf..1f767c5ba 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MixerStatus.java @@ -114,18 +114,17 @@ public class MixerStatus extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java index 1629a19d2..6d09a799e 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NedAccel.java @@ -86,18 +86,17 @@ public class NedAccel extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 10001; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 10001; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java index dccd85d36..42a65e3ab 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ObjectPersistence.java @@ -68,6 +68,7 @@ public class ObjectPersistence extends UAVDataObject { OperationEnumOptions.add("Delete"); OperationEnumOptions.add("FullErase"); OperationEnumOptions.add("Completed"); + OperationEnumOptions.add("Error"); fields.add( new UAVObjectField("Operation", "", UAVObjectField.FieldType.ENUM, OperationElemNames, OperationEnumOptions) ); List SelectionElemNames = new ArrayList(); @@ -102,18 +103,17 @@ public class ObjectPersistence extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -152,7 +152,7 @@ public class ObjectPersistence extends UAVDataObject { } // Constants - protected static final int OBJID = 0xF69AD8B8; + protected static final int OBJID = 0x99C63292; protected static final String NAME = "ObjectPersistence"; protected static String DESCRIPTION = "Someone who knows please enter this"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java index 184098a16..1c87c21c3 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java @@ -86,18 +86,17 @@ public class PositionActual extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 1000; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java deleted file mode 100644 index 123ca58af..000000000 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionDesired.java +++ /dev/null @@ -1,147 +0,0 @@ -/** - ****************************************************************************** - * - * @file uavobjecttemplate.cpp - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Template for an uavobject in java - * This is a autogenerated file!! Do not modify and expect a result. - * The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner - * - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package org.openpilot.uavtalk.uavobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import org.openpilot.uavtalk.UAVObjectManager; -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVDataObject; -import org.openpilot.uavtalk.UAVObjectField; - -/** -The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner - -generated from positiondesired.xml - **/ -public class PositionDesired extends UAVDataObject { - - public PositionDesired() { - super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); - - List fields = new ArrayList(); - - - List NorthElemNames = new ArrayList(); - NorthElemNames.add("0"); - fields.add( new UAVObjectField("North", "m", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); - - List EastElemNames = new ArrayList(); - EastElemNames.add("0"); - fields.add( new UAVObjectField("East", "m", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); - - List DownElemNames = new ArrayList(); - DownElemNames.add("0"); - fields.add( new UAVObjectField("Down", "m", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); - - - // Compute the number of bytes for this object - int numBytes = 0; - ListIterator li = fields.listIterator(); - while(li.hasNext()) { - numBytes += li.next().getNumBytes(); - } - NUMBYTES = numBytes; - - // Initialize object - initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); - // Set the default field values - setDefaultFieldValues(); - // Set the object description - setDescription(DESCRIPTION); - } - - /** - * Create a Metadata object filled with default values for this object - * @return Metadata object with default values - */ - public Metadata getDefaultMetadata() { - UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; - return metadata; - } - - /** - * Initialize object fields with the default values. - * If a default value is not specified the object fields - * will be initialized to zero. - */ - public void setDefaultFieldValues() - { - - } - - /** - * Create a clone of this object, a new instance ID must be specified. - * Do not use this function directly to create new instances, the - * UAVObjectManager should be used instead. - */ - public UAVDataObject clone(int instID) { - // TODO: Need to get specific instance to clone - try { - PositionDesired obj = new PositionDesired(); - obj.initialize(instID, this.getMetaObject()); - return obj; - } catch (Exception e) { - return null; - } - } - - /** - * Static function to retrieve an instance of the object. - */ - public PositionDesired GetInstance(UAVObjectManager objMngr, int instID) - { - return (PositionDesired)(objMngr.getObject(PositionDesired.OBJID, instID)); - } - - // Constants - protected static final int OBJID = 0x778DBE24; - protected static final String NAME = "PositionDesired"; - protected static String DESCRIPTION = "The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner "; - protected static final boolean ISSINGLEINST = 1 == 1; - protected static final boolean ISSETTINGS = 0 == 1; - protected static int NUMBYTES = 0; - - -} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java index ddeacd8d4..51f7faa7d 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RateDesired.java @@ -86,18 +86,17 @@ public class RateDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java index a40b27e38..15391ce71 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/ReceiverActivity.java @@ -90,18 +90,17 @@ public class ReceiverActivity extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READONLY; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READONLY) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java index 18cf6f4d6..1a5679d6a 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SonarAltitude.java @@ -78,18 +78,17 @@ public class SonarAltitude extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java index 32d2c735c..8ca5df722 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationDesired.java @@ -77,6 +77,7 @@ public class StabilizationDesired extends UAVDataObject { StabilizationModeEnumOptions.add("Attitude"); StabilizationModeEnumOptions.add("AxisLock"); StabilizationModeEnumOptions.add("WeakLeveling"); + StabilizationModeEnumOptions.add("VirtualBar"); fields.add( new UAVObjectField("StabilizationMode", "", UAVObjectField.FieldType.ENUM, StabilizationModeElemNames, StabilizationModeEnumOptions) ); @@ -102,18 +103,17 @@ public class StabilizationDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -152,7 +152,7 @@ public class StabilizationDesired extends UAVDataObject { } // Constants - protected static final int OBJID = 0xDB8FFC3C; + protected static final int OBJID = 0xDE1EAAD6; protected static final String NAME = "StabilizationDesired"; protected static String DESCRIPTION = "The desired attitude that @ref StabilizationModule will try and achieve if FlightMode is Stabilized. Comes from @ref ManaulControlModule."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java index ab78bdc74..cc2c69e8f 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/StabilizationSettings.java @@ -102,6 +102,31 @@ public class StabilizationSettings extends UAVDataObject { YawPIElemNames.add("ILimit"); fields.add( new UAVObjectField("YawPI", "", UAVObjectField.FieldType.FLOAT32, YawPIElemNames, null) ); + List VbarSensitivityElemNames = new ArrayList(); + VbarSensitivityElemNames.add("Roll"); + VbarSensitivityElemNames.add("Pitch"); + VbarSensitivityElemNames.add("Yaw"); + fields.add( new UAVObjectField("VbarSensitivity", "frac", UAVObjectField.FieldType.FLOAT32, VbarSensitivityElemNames, null) ); + + List VbarRollPIElemNames = new ArrayList(); + VbarRollPIElemNames.add("Kp"); + VbarRollPIElemNames.add("Ki"); + fields.add( new UAVObjectField("VbarRollPI", "1/(deg/s)", UAVObjectField.FieldType.FLOAT32, VbarRollPIElemNames, null) ); + + List VbarPitchPIElemNames = new ArrayList(); + VbarPitchPIElemNames.add("Kp"); + VbarPitchPIElemNames.add("Ki"); + fields.add( new UAVObjectField("VbarPitchPI", "1/(deg/s)", UAVObjectField.FieldType.FLOAT32, VbarPitchPIElemNames, null) ); + + List VbarYawPIElemNames = new ArrayList(); + VbarYawPIElemNames.add("Kp"); + VbarYawPIElemNames.add("Ki"); + fields.add( new UAVObjectField("VbarYawPI", "1/(deg/s)", UAVObjectField.FieldType.FLOAT32, VbarYawPIElemNames, null) ); + + List VbarTauElemNames = new ArrayList(); + VbarTauElemNames.add("0"); + fields.add( new UAVObjectField("VbarTau", "sec", UAVObjectField.FieldType.FLOAT32, VbarTauElemNames, null) ); + List GyroTauElemNames = new ArrayList(); GyroTauElemNames.add("0"); fields.add( new UAVObjectField("GyroTau", "", UAVObjectField.FieldType.FLOAT32, GyroTauElemNames, null) ); @@ -122,6 +147,21 @@ public class StabilizationSettings extends UAVDataObject { YawMaxElemNames.add("0"); fields.add( new UAVObjectField("YawMax", "degrees", UAVObjectField.FieldType.UINT8, YawMaxElemNames, null) ); + List VbarGyroSuppressElemNames = new ArrayList(); + VbarGyroSuppressElemNames.add("0"); + fields.add( new UAVObjectField("VbarGyroSuppress", "%", UAVObjectField.FieldType.INT8, VbarGyroSuppressElemNames, null) ); + + List VbarPiroCompElemNames = new ArrayList(); + VbarPiroCompElemNames.add("0"); + List VbarPiroCompEnumOptions = new ArrayList(); + VbarPiroCompEnumOptions.add("FALSE"); + VbarPiroCompEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("VbarPiroComp", "", UAVObjectField.FieldType.ENUM, VbarPiroCompElemNames, VbarPiroCompEnumOptions) ); + + List VbarMaxAngleElemNames = new ArrayList(); + VbarMaxAngleElemNames.add("0"); + fields.add( new UAVObjectField("VbarMaxAngle", "deg", UAVObjectField.FieldType.UINT8, VbarMaxAngleElemNames, null) ); + List MaxAxisLockElemNames = new ArrayList(); MaxAxisLockElemNames.add("0"); fields.add( new UAVObjectField("MaxAxisLock", "deg", UAVObjectField.FieldType.UINT8, MaxAxisLockElemNames, null) ); @@ -164,18 +204,17 @@ public class StabilizationSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -213,11 +252,24 @@ public class StabilizationSettings extends UAVDataObject { getField("YawPI").setValue(2,0); getField("YawPI").setValue(0,1); getField("YawPI").setValue(50,2); + getField("VbarSensitivity").setValue(0.5,0); + getField("VbarSensitivity").setValue(0.5,1); + getField("VbarSensitivity").setValue(0.5,2); + getField("VbarRollPI").setValue(0.005,0); + getField("VbarRollPI").setValue(0.002,1); + getField("VbarPitchPI").setValue(0.005,0); + getField("VbarPitchPI").setValue(0.002,1); + getField("VbarYawPI").setValue(0.005,0); + getField("VbarYawPI").setValue(0.002,1); + getField("VbarTau").setValue(0.5); getField("GyroTau").setValue(0.005); getField("WeakLevelingKp").setValue(0.1); getField("RollMax").setValue(55); getField("PitchMax").setValue(55); getField("YawMax").setValue(35); + getField("VbarGyroSuppress").setValue(30); + getField("VbarPiroComp").setValue("FALSE"); + getField("VbarMaxAngle").setValue(10); getField("MaxAxisLock").setValue(15); getField("MaxAxisLockRate").setValue(2); getField("MaxWeakLevelingRate").setValue(5); @@ -250,7 +302,7 @@ public class StabilizationSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x5F78C51E; + protected static final int OBJID = 0xBBC337D4; protected static final String NAME = "StabilizationSettings"; protected static String DESCRIPTION = "PID settings used by the Stabilization module to combine the @ref AttitudeActual and @ref AttitudeDesired to compute @ref ActuatorDesired"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java index bc4bf0625..3b34763fe 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java @@ -56,7 +56,6 @@ public class SystemAlarms extends UAVDataObject { AlarmElemNames.add("StackOverflow"); AlarmElemNames.add("CPUOverload"); AlarmElemNames.add("EventSystem"); - AlarmElemNames.add("SDCard"); AlarmElemNames.add("Telemetry"); AlarmElemNames.add("ManualControl"); AlarmElemNames.add("Actuator"); @@ -64,12 +63,12 @@ public class SystemAlarms extends UAVDataObject { AlarmElemNames.add("Sensors"); AlarmElemNames.add("Stabilization"); AlarmElemNames.add("Guidance"); - AlarmElemNames.add("AHRSComms"); AlarmElemNames.add("Battery"); AlarmElemNames.add("FlightTime"); AlarmElemNames.add("I2C"); AlarmElemNames.add("GPS"); AlarmElemNames.add("BootFault"); + AlarmElemNames.add("Power"); List AlarmEnumOptions = new ArrayList(); AlarmEnumOptions.add("Uninitialised"); AlarmEnumOptions.add("OK"); @@ -101,18 +100,17 @@ public class SystemAlarms extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } @@ -140,7 +138,6 @@ public class SystemAlarms extends UAVDataObject { getField("Alarm").setValue("Uninitialised",14); getField("Alarm").setValue("Uninitialised",15); getField("Alarm").setValue("Uninitialised",16); - getField("Alarm").setValue("Uninitialised",17); } @@ -169,7 +166,7 @@ public class SystemAlarms extends UAVDataObject { } // Constants - protected static final int OBJID = 0x9C7CBFE; + protected static final int OBJID = 0x737ADCF2; protected static final String NAME = "SystemAlarms"; protected static String DESCRIPTION = "Alarms from OpenPilot to indicate failure conditions or warnings. Set by various modules."; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java index e3c2cf0b0..bffbced31 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemSettings.java @@ -54,6 +54,8 @@ public class SystemSettings extends UAVDataObject { List GUIConfigDataElemNames = new ArrayList(); GUIConfigDataElemNames.add("0"); GUIConfigDataElemNames.add("1"); + GUIConfigDataElemNames.add("2"); + GUIConfigDataElemNames.add("3"); fields.add( new UAVObjectField("GUIConfigData", "bits", UAVObjectField.FieldType.UINT32, GUIConfigDataElemNames, null) ); List AirframeTypeElemNames = new ArrayList(); @@ -75,6 +77,9 @@ public class SystemSettings extends UAVDataObject { AirframeTypeEnumOptions.add("OctoCoaxX"); AirframeTypeEnumOptions.add("HexaCoax"); AirframeTypeEnumOptions.add("Tri"); + AirframeTypeEnumOptions.add("GroundVehicleCar"); + AirframeTypeEnumOptions.add("GroundVehicleDifferential"); + AirframeTypeEnumOptions.add("GroundVehicleMotorcycle"); fields.add( new UAVObjectField("AirframeType", "", UAVObjectField.FieldType.ENUM, AirframeTypeElemNames, AirframeTypeEnumOptions) ); @@ -100,18 +105,17 @@ public class SystemSettings extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.flightTelemetryUpdatePeriod = 0; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_NEVER; - metadata.loggingUpdatePeriod = 0; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + return metadata; } @@ -124,7 +128,9 @@ public class SystemSettings extends UAVDataObject { { getField("GUIConfigData").setValue(0,0); getField("GUIConfigData").setValue(0,1); - getField("AirframeType").setValue("FixedWing"); + getField("GUIConfigData").setValue(0,2); + getField("GUIConfigData").setValue(0,3); + getField("AirframeType").setValue("QuadX"); } @@ -153,7 +159,7 @@ public class SystemSettings extends UAVDataObject { } // Constants - protected static final int OBJID = 0x30BD5D7C; + protected static final int OBJID = 0xC72A326E; protected static final String NAME = "SystemSettings"; protected static String DESCRIPTION = "Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java index 26d01f2a0..888474261 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemStats.java @@ -106,18 +106,17 @@ public class SystemStats extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java index eefcef6d9..9f530e6a9 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java @@ -62,11 +62,12 @@ public class TaskInfo extends UAVDataObject { StackRemainingElemNames.add("GPS"); StackRemainingElemNames.add("ManualControl"); StackRemainingElemNames.add("Altitude"); + StackRemainingElemNames.add("Airspeed"); StackRemainingElemNames.add("Stabilization"); StackRemainingElemNames.add("AltitudeHold"); - StackRemainingElemNames.add("Guidance"); - StackRemainingElemNames.add("FlightPlan"); StackRemainingElemNames.add("PathPlanner"); + StackRemainingElemNames.add("PathFollower"); + StackRemainingElemNames.add("FlightPlan"); StackRemainingElemNames.add("Com2UsbBridge"); StackRemainingElemNames.add("Usb2ComBridge"); StackRemainingElemNames.add("OveroSync"); @@ -83,11 +84,12 @@ public class TaskInfo extends UAVDataObject { RunningElemNames.add("GPS"); RunningElemNames.add("ManualControl"); RunningElemNames.add("Altitude"); + RunningElemNames.add("Airspeed"); RunningElemNames.add("Stabilization"); RunningElemNames.add("AltitudeHold"); - RunningElemNames.add("Guidance"); - RunningElemNames.add("FlightPlan"); RunningElemNames.add("PathPlanner"); + RunningElemNames.add("PathFollower"); + RunningElemNames.add("FlightPlan"); RunningElemNames.add("Com2UsbBridge"); RunningElemNames.add("Usb2ComBridge"); RunningElemNames.add("OveroSync"); @@ -107,11 +109,12 @@ public class TaskInfo extends UAVDataObject { RunningTimeElemNames.add("GPS"); RunningTimeElemNames.add("ManualControl"); RunningTimeElemNames.add("Altitude"); + RunningTimeElemNames.add("Airspeed"); RunningTimeElemNames.add("Stabilization"); RunningTimeElemNames.add("AltitudeHold"); - RunningTimeElemNames.add("Guidance"); - RunningTimeElemNames.add("FlightPlan"); RunningTimeElemNames.add("PathPlanner"); + RunningTimeElemNames.add("PathFollower"); + RunningTimeElemNames.add("FlightPlan"); RunningTimeElemNames.add("Com2UsbBridge"); RunningTimeElemNames.add("Usb2ComBridge"); RunningTimeElemNames.add("OveroSync"); @@ -140,18 +143,17 @@ public class TaskInfo extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.TRUE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_ONCHANGE; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.TRUE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 10000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 10000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } @@ -190,7 +192,7 @@ public class TaskInfo extends UAVDataObject { } // Constants - protected static final int OBJID = 0x498F54BA; + protected static final int OBJID = 0xB81CD2AE; protected static final String NAME = "TaskInfo"; protected static String DESCRIPTION = "Task information"; protected static final boolean ISSINGLEINST = 1 == 1; diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java index 823643130..7968c37c3 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java @@ -45,11 +45,15 @@ public class UAVObjectsInitialize { objMngr.registerObject( new AltitudeHoldSettings() ); objMngr.registerObject( new AttitudeActual() ); objMngr.registerObject( new AttitudeSettings() ); + objMngr.registerObject( new AttitudeSimulated() ); + objMngr.registerObject( new BaroAirspeed() ); objMngr.registerObject( new BaroAltitude() ); objMngr.registerObject( new CameraDesired() ); objMngr.registerObject( new CameraStabSettings() ); objMngr.registerObject( new FaultSettings() ); objMngr.registerObject( new FirmwareIAPObj() ); + objMngr.registerObject( new FixedWingPathFollowerSettings() ); + objMngr.registerObject( new FixedWingPathFollowerStatus() ); objMngr.registerObject( new FlightBatterySettings() ); objMngr.registerObject( new FlightBatteryState() ); objMngr.registerObject( new FlightPlanControl() ); @@ -61,38 +65,45 @@ public class UAVObjectsInitialize { objMngr.registerObject( new GCSTelemetryStats() ); objMngr.registerObject( new GPSPosition() ); objMngr.registerObject( new GPSSatellites() ); + objMngr.registerObject( new GPSSettings() ); objMngr.registerObject( new GPSTime() ); objMngr.registerObject( new GPSVelocity() ); objMngr.registerObject( new Gyros() ); objMngr.registerObject( new GyrosBias() ); - objMngr.registerObject( new GuidanceSettings() ); objMngr.registerObject( new HomeLocation() ); objMngr.registerObject( new HwSettings() ); objMngr.registerObject( new I2CStats() ); - objMngr.registerObject( new GPSPosition() ); + objMngr.registerObject( new MagBias() ); objMngr.registerObject( new Magnetometer() ); objMngr.registerObject( new ManualControlCommand() ); objMngr.registerObject( new ManualControlSettings() ); objMngr.registerObject( new MixerSettings() ); objMngr.registerObject( new MixerStatus() ); - objMngr.registerObject( new NEDPosition() ); objMngr.registerObject( new NedAccel() ); + objMngr.registerObject( new NEDPosition() ); objMngr.registerObject( new ObjectPersistence() ); + objMngr.registerObject( new OveroSyncSettings() ); + objMngr.registerObject( new OveroSyncStats() ); objMngr.registerObject( new PathDesired() ); + objMngr.registerObject( new PathPlannerSettings() ); + objMngr.registerObject( new PipXSettings() ); + objMngr.registerObject( new PipXStatus() ); objMngr.registerObject( new PositionActual() ); - objMngr.registerObject( new PositionDesired() ); objMngr.registerObject( new RateDesired() ); objMngr.registerObject( new ReceiverActivity() ); + objMngr.registerObject( new RevoCalibration() ); + objMngr.registerObject( new RevoSettings() ); objMngr.registerObject( new SonarAltitude() ); objMngr.registerObject( new StabilizationDesired() ); objMngr.registerObject( new StabilizationSettings() ); objMngr.registerObject( new SystemAlarms() ); objMngr.registerObject( new SystemSettings() ); objMngr.registerObject( new SystemStats() ); - objMngr.registerObject( new TxPIDSettings() ); objMngr.registerObject( new TaskInfo() ); + objMngr.registerObject( new TxPIDSettings() ); objMngr.registerObject( new VelocityActual() ); objMngr.registerObject( new VelocityDesired() ); + objMngr.registerObject( new VtolPathFollowerSettings() ); objMngr.registerObject( new WatchdogStatus() ); objMngr.registerObject( new Waypoint() ); objMngr.registerObject( new WaypointActive() ); diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java index 2a8cd3754..a545bca16 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityActual.java @@ -86,18 +86,17 @@ public class VelocityActual extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java index 436ef6448..f506a594c 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VelocityDesired.java @@ -86,18 +86,17 @@ public class VelocityDesired extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 1000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 1000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + return metadata; } diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java index acbdb43d1..94e85f57b 100644 --- a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WatchdogStatus.java @@ -82,18 +82,17 @@ public class WatchdogStatus extends UAVDataObject { */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.gcsTelemetryAcked = UAVObject.Acked.FALSE; - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_MANUAL; - metadata.gcsTelemetryUpdatePeriod = 0; - - metadata.flightAccess = UAVObject.AccessMode.ACCESS_READWRITE; - metadata.flightTelemetryAcked = UAVObject.Acked.FALSE; - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.flightTelemetryUpdatePeriod = 5000; - - metadata.loggingUpdateMode = UAVObject.UpdateMode.UPDATEMODE_PERIODIC; - metadata.loggingUpdatePeriod = 5000; + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 5000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 5000; + return metadata; } diff --git a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java index 64e2461f5..1283f03cb 100644 --- a/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java +++ b/ground/openpilotgcs/src/libs/juavobjects/templates/uavobjecttemplate.java @@ -74,18 +74,17 @@ $(FIELDSINIT) */ public Metadata getDefaultMetadata() { UAVObject.Metadata metadata = new UAVObject.Metadata(); - metadata.gcsAccess = UAVObject.AccessMode.$(GCSACCESS); - metadata.gcsTelemetryAcked = UAVObject.Acked.$(GCSTELEM_ACKEDTF); - metadata.gcsTelemetryUpdateMode = UAVObject.UpdateMode.$(GCSTELEM_UPDATEMODE); - metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD); - - metadata.flightAccess = UAVObject.AccessMode.$(FLIGHTACCESS); - metadata.flightTelemetryAcked = UAVObject.Acked.$(FLIGHTTELEM_ACKEDTF); - metadata.flightTelemetryUpdateMode = UAVObject.UpdateMode.$(FLIGHTTELEM_UPDATEMODE); - metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD); - - metadata.loggingUpdateMode = UAVObject.UpdateMode.$(LOGGING_UPDATEMODE); - metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.$(FLIGHTACCESS)) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.$(GCSACCESS)) << UAVOBJ_GCS_ACCESS_SHIFT | + $(FLIGHTTELEM_ACKED) << UAVOBJ_TELEMETRY_ACKED_SHIFT | + $(GCSTELEM_ACKED) << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.$(FLIGHTTELEM_UPDATEMODE)) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.$(GCSTELEM_UPDATEMODE)) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD); + metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD); + metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD); + return metadata; } From 32ec48412d8a2178f7e82be24dfde4bef16c3f89 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Thu, 2 Aug 2012 13:08:47 -0500 Subject: [PATCH 173/284] Forgot to initialize the fields for metadata --- androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java index c57b6c2fe..98a3bf8df 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java @@ -27,7 +27,8 @@ public class UAVMetaObject extends UAVObject { modesBitField.add("FlightUpdateOnChange"); modesBitField.add("GCSUpdatePeriodic"); modesBitField.add("GCSUpdateOnChange"); - + + List fields = new ArrayList(); fields.add( new UAVObjectField("Modes", "", UAVObjectField.FieldType.BITFIELD, 1, modesBitField) ); fields.add( new UAVObjectField("Flight Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); fields.add( new UAVObjectField("GCS Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); From 95218802daf0b496d71c68359894308de842ba46 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Fri, 3 Aug 2012 13:49:16 -0500 Subject: [PATCH 174/284] Catch invalid number decoding to cover cases where there is no IP address. --- .../src/org/openpilot/androidgcs/OPTelemetryService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 1a4b61eb8..917dfb116 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -72,8 +72,14 @@ public class OPTelemetryService extends Service { break; case MSG_CONNECT: terminate = false; + int connection_type; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this); - int connection_type = Integer.decode(prefs.getString("connection_type", "")); + try { + connection_type = Integer.decode(prefs.getString("connection_type", "")); + } catch (NumberFormatException e) { + connection_type = 0; + } + switch(connection_type) { case 0: // No connection return; From 65861b4b8d7be00b4ae05c666a65a5a5190c3dca Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 01:35:49 -0500 Subject: [PATCH 175/284] Update the UAVO files --- .../openpilot/uavtalk/uavobjects/Accels.java | 150 ++++++++ .../uavtalk/uavobjects/AltHoldSmoothed.java | 146 ++++++++ .../uavobjects/AltitudeHoldDesired.java | 150 ++++++++ .../uavobjects/AltitudeHoldSettings.java | 169 +++++++++ .../uavtalk/uavobjects/AttitudeSimulated.java | 174 ++++++++++ .../uavtalk/uavobjects/BaroAirspeed.java | 153 ++++++++ .../FixedWingPathFollowerSettings.java | 239 +++++++++++++ .../FixedWingPathFollowerStatus.java | 164 +++++++++ .../uavtalk/uavobjects/GPSSettings.java | 142 ++++++++ .../uavtalk/uavobjects/GPSVelocity.java | 146 ++++++++ .../openpilot/uavtalk/uavobjects/Gyros.java | 150 ++++++++ .../uavtalk/uavobjects/GyrosBias.java | 146 ++++++++ .../openpilot/uavtalk/uavobjects/MagBias.java | 146 ++++++++ .../uavtalk/uavobjects/Magnetometer.java | 146 ++++++++ .../uavtalk/uavobjects/NEDPosition.java | 146 ++++++++ .../uavtalk/uavobjects/OveroSyncSettings.java | 143 ++++++++ .../uavtalk/uavobjects/OveroSyncStats.java | 165 +++++++++ .../uavtalk/uavobjects/PathDesired.java | 162 +++++++++ .../uavobjects/PathPlannerSettings.java | 151 ++++++++ .../uavtalk/uavobjects/PipXSettings.java | 326 ++++++++++++++++++ .../uavtalk/uavobjects/PipXStatus.java | 301 ++++++++++++++++ .../uavtalk/uavobjects/RevoCalibration.java | 249 +++++++++++++ .../uavtalk/uavobjects/RevoSettings.java | 143 ++++++++ .../uavtalk/uavobjects/TxPIDSettings.java | 225 ++++++++++++ .../uavobjects/VtolPathFollowerSettings.java | 232 +++++++++++++ .../uavtalk/uavobjects/Waypoint.java | 159 +++++++++ .../uavtalk/uavobjects/WaypointActive.java | 138 ++++++++ 27 files changed, 4761 insertions(+) create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/Accels.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AltHoldSmoothed.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSimulated.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAirspeed.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerStatus.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSVelocity.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/Gyros.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/GyrosBias.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/MagBias.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/Magnetometer.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/NEDPosition.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncStats.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PathDesired.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PathPlannerSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXStatus.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoCalibration.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/TxPIDSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/VtolPathFollowerSettings.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/Waypoint.java create mode 100644 androidgcs/src/org/openpilot/uavtalk/uavobjects/WaypointActive.java diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/Accels.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Accels.java new file mode 100644 index 000000000..32437e63e --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Accels.java @@ -0,0 +1,150 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The accel data. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The accel data. + +generated from accels.xml + **/ +public class Accels extends UAVDataObject { + + public Accels() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List xElemNames = new ArrayList(); + xElemNames.add("0"); + fields.add( new UAVObjectField("x", "m/s^2", UAVObjectField.FieldType.FLOAT32, xElemNames, null) ); + + List yElemNames = new ArrayList(); + yElemNames.add("0"); + fields.add( new UAVObjectField("y", "m/s^2", UAVObjectField.FieldType.FLOAT32, yElemNames, null) ); + + List zElemNames = new ArrayList(); + zElemNames.add("0"); + fields.add( new UAVObjectField("z", "m/s^2", UAVObjectField.FieldType.FLOAT32, zElemNames, null) ); + + List temperatureElemNames = new ArrayList(); + temperatureElemNames.add("0"); + fields.add( new UAVObjectField("temperature", "deg C", UAVObjectField.FieldType.FLOAT32, temperatureElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + Accels obj = new Accels(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public Accels GetInstance(UAVObjectManager objMngr, int instID) + { + return (Accels)(objMngr.getObject(Accels.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xDD9D5FC0; + protected static final String NAME = "Accels"; + protected static String DESCRIPTION = "The accel data."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltHoldSmoothed.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltHoldSmoothed.java new file mode 100644 index 000000000..46d03a544 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltHoldSmoothed.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The output on the kalman filter on altitude. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The output on the kalman filter on altitude. + +generated from altholdsmoothed.xml + **/ +public class AltHoldSmoothed extends UAVDataObject { + + public AltHoldSmoothed() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AltitudeElemNames = new ArrayList(); + AltitudeElemNames.add("0"); + fields.add( new UAVObjectField("Altitude", "m", UAVObjectField.FieldType.FLOAT32, AltitudeElemNames, null) ); + + List VelocityElemNames = new ArrayList(); + VelocityElemNames.add("0"); + fields.add( new UAVObjectField("Velocity", "m/s", UAVObjectField.FieldType.FLOAT32, VelocityElemNames, null) ); + + List AccelElemNames = new ArrayList(); + AccelElemNames.add("0"); + fields.add( new UAVObjectField("Accel", "m/s^2", UAVObjectField.FieldType.FLOAT32, AccelElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AltHoldSmoothed obj = new AltHoldSmoothed(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AltHoldSmoothed GetInstance(UAVObjectManager objMngr, int instID) + { + return (AltHoldSmoothed)(objMngr.getObject(AltHoldSmoothed.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x2BC6B9D2; + protected static final String NAME = "AltHoldSmoothed"; + protected static String DESCRIPTION = "The output on the kalman filter on altitude."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldDesired.java new file mode 100644 index 000000000..efe860340 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldDesired.java @@ -0,0 +1,150 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Holds the desired altitude (from manual control) as well as the desired attitude to pass through + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Holds the desired altitude (from manual control) as well as the desired attitude to pass through + +generated from altitudeholddesired.xml + **/ +public class AltitudeHoldDesired extends UAVDataObject { + + public AltitudeHoldDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AltitudeElemNames = new ArrayList(); + AltitudeElemNames.add("0"); + fields.add( new UAVObjectField("Altitude", "m", UAVObjectField.FieldType.FLOAT32, AltitudeElemNames, null) ); + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "deg", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "deg", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "deg/s", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AltitudeHoldDesired obj = new AltitudeHoldDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AltitudeHoldDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (AltitudeHoldDesired)(objMngr.getObject(AltitudeHoldDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x495BAD6E; + protected static final String NAME = "AltitudeHoldDesired"; + protected static String DESCRIPTION = "Holds the desired altitude (from manual control) as well as the desired attitude to pass through"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldSettings.java new file mode 100644 index 000000000..77b6774b9 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldSettings.java @@ -0,0 +1,169 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref AltitudeHold module + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref AltitudeHold module + +generated from altitudeholdsettings.xml + **/ +public class AltitudeHoldSettings extends UAVDataObject { + + public AltitudeHoldSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List KpElemNames = new ArrayList(); + KpElemNames.add("0"); + fields.add( new UAVObjectField("Kp", "throttle/m", UAVObjectField.FieldType.FLOAT32, KpElemNames, null) ); + + List KiElemNames = new ArrayList(); + KiElemNames.add("0"); + fields.add( new UAVObjectField("Ki", "throttle/m", UAVObjectField.FieldType.FLOAT32, KiElemNames, null) ); + + List KdElemNames = new ArrayList(); + KdElemNames.add("0"); + fields.add( new UAVObjectField("Kd", "throttle/m", UAVObjectField.FieldType.FLOAT32, KdElemNames, null) ); + + List KaElemNames = new ArrayList(); + KaElemNames.add("0"); + fields.add( new UAVObjectField("Ka", "throttle/(m/s^2)", UAVObjectField.FieldType.FLOAT32, KaElemNames, null) ); + + List PressureNoiseElemNames = new ArrayList(); + PressureNoiseElemNames.add("0"); + fields.add( new UAVObjectField("PressureNoise", "m", UAVObjectField.FieldType.FLOAT32, PressureNoiseElemNames, null) ); + + List AccelNoiseElemNames = new ArrayList(); + AccelNoiseElemNames.add("0"); + fields.add( new UAVObjectField("AccelNoise", "m/s^2", UAVObjectField.FieldType.FLOAT32, AccelNoiseElemNames, null) ); + + List AccelDriftElemNames = new ArrayList(); + AccelDriftElemNames.add("0"); + fields.add( new UAVObjectField("AccelDrift", "m/s^2", UAVObjectField.FieldType.FLOAT32, AccelDriftElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("Kp").setValue(0.03); + getField("Ki").setValue(0); + getField("Kd").setValue(0.03); + getField("Ka").setValue(0.005); + getField("PressureNoise").setValue(0.4); + getField("AccelNoise").setValue(5); + getField("AccelDrift").setValue(0.001); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AltitudeHoldSettings obj = new AltitudeHoldSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AltitudeHoldSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (AltitudeHoldSettings)(objMngr.getObject(AltitudeHoldSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xFEC55B42; + protected static final String NAME = "AltitudeHoldSettings"; + protected static String DESCRIPTION = "Settings for the @ref AltitudeHold module"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSimulated.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSimulated.java new file mode 100644 index 000000000..3a713ab04 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/AttitudeSimulated.java @@ -0,0 +1,174 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The simulated Attitude estimation from @ref Sensors. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The simulated Attitude estimation from @ref Sensors. + +generated from attitudesimulated.xml + **/ +public class AttitudeSimulated extends UAVDataObject { + + public AttitudeSimulated() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List q1ElemNames = new ArrayList(); + q1ElemNames.add("0"); + fields.add( new UAVObjectField("q1", "", UAVObjectField.FieldType.FLOAT32, q1ElemNames, null) ); + + List q2ElemNames = new ArrayList(); + q2ElemNames.add("0"); + fields.add( new UAVObjectField("q2", "", UAVObjectField.FieldType.FLOAT32, q2ElemNames, null) ); + + List q3ElemNames = new ArrayList(); + q3ElemNames.add("0"); + fields.add( new UAVObjectField("q3", "", UAVObjectField.FieldType.FLOAT32, q3ElemNames, null) ); + + List q4ElemNames = new ArrayList(); + q4ElemNames.add("0"); + fields.add( new UAVObjectField("q4", "", UAVObjectField.FieldType.FLOAT32, q4ElemNames, null) ); + + List RollElemNames = new ArrayList(); + RollElemNames.add("0"); + fields.add( new UAVObjectField("Roll", "degrees", UAVObjectField.FieldType.FLOAT32, RollElemNames, null) ); + + List PitchElemNames = new ArrayList(); + PitchElemNames.add("0"); + fields.add( new UAVObjectField("Pitch", "degrees", UAVObjectField.FieldType.FLOAT32, PitchElemNames, null) ); + + List YawElemNames = new ArrayList(); + YawElemNames.add("0"); + fields.add( new UAVObjectField("Yaw", "degrees", UAVObjectField.FieldType.FLOAT32, YawElemNames, null) ); + + List VelocityElemNames = new ArrayList(); + VelocityElemNames.add("North"); + VelocityElemNames.add("East"); + VelocityElemNames.add("Down"); + fields.add( new UAVObjectField("Velocity", "m/s", UAVObjectField.FieldType.FLOAT32, VelocityElemNames, null) ); + + List PositionElemNames = new ArrayList(); + PositionElemNames.add("North"); + PositionElemNames.add("East"); + PositionElemNames.add("Down"); + fields.add( new UAVObjectField("Position", "m", UAVObjectField.FieldType.FLOAT32, PositionElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 100; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + AttitudeSimulated obj = new AttitudeSimulated(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public AttitudeSimulated GetInstance(UAVObjectManager objMngr, int instID) + { + return (AttitudeSimulated)(objMngr.getObject(AttitudeSimulated.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x9266CE74; + protected static final String NAME = "AttitudeSimulated"; + protected static String DESCRIPTION = "The simulated Attitude estimation from @ref Sensors."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAirspeed.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAirspeed.java new file mode 100644 index 000000000..439915741 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/BaroAirspeed.java @@ -0,0 +1,153 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The raw data from the dynamic pressure sensor with pressure, temperature and airspeed. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The raw data from the dynamic pressure sensor with pressure, temperature and airspeed. + +generated from baroairspeed.xml + **/ +public class BaroAirspeed extends UAVDataObject { + + public BaroAirspeed() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AirspeedElemNames = new ArrayList(); + AirspeedElemNames.add("0"); + fields.add( new UAVObjectField("Airspeed", "m/s", UAVObjectField.FieldType.FLOAT32, AirspeedElemNames, null) ); + + List SensorValueElemNames = new ArrayList(); + SensorValueElemNames.add("0"); + fields.add( new UAVObjectField("SensorValue", "raw", UAVObjectField.FieldType.UINT16, SensorValueElemNames, null) ); + + List ZeroPointElemNames = new ArrayList(); + ZeroPointElemNames.add("0"); + fields.add( new UAVObjectField("ZeroPoint", "raw", UAVObjectField.FieldType.UINT16, ZeroPointElemNames, null) ); + + List ConnectedElemNames = new ArrayList(); + ConnectedElemNames.add("0"); + List ConnectedEnumOptions = new ArrayList(); + ConnectedEnumOptions.add("False"); + ConnectedEnumOptions.add("True"); + fields.add( new UAVObjectField("Connected", "", UAVObjectField.FieldType.ENUM, ConnectedElemNames, ConnectedEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + BaroAirspeed obj = new BaroAirspeed(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public BaroAirspeed GetInstance(UAVObjectManager objMngr, int instID) + { + return (BaroAirspeed)(objMngr.getObject(BaroAirspeed.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x169EA4A; + protected static final String NAME = "BaroAirspeed"; + protected static String DESCRIPTION = "The raw data from the dynamic pressure sensor with pressure, temperature and airspeed."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerSettings.java new file mode 100644 index 000000000..00419bc4c --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerSettings.java @@ -0,0 +1,239 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref FixedWingPathFollowerModule + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref FixedWingPathFollowerModule + +generated from fixedwingpathfollowersettings.xml + **/ +public class FixedWingPathFollowerSettings extends UAVDataObject { + + public FixedWingPathFollowerSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List AirSpeedMaxElemNames = new ArrayList(); + AirSpeedMaxElemNames.add("0"); + fields.add( new UAVObjectField("AirSpeedMax", "m/s", UAVObjectField.FieldType.FLOAT32, AirSpeedMaxElemNames, null) ); + + List AirSpeedMinElemNames = new ArrayList(); + AirSpeedMinElemNames.add("0"); + fields.add( new UAVObjectField("AirSpeedMin", "m/s", UAVObjectField.FieldType.FLOAT32, AirSpeedMinElemNames, null) ); + + List VerticalVelMaxElemNames = new ArrayList(); + VerticalVelMaxElemNames.add("0"); + fields.add( new UAVObjectField("VerticalVelMax", "m/s", UAVObjectField.FieldType.FLOAT32, VerticalVelMaxElemNames, null) ); + + List HorizontalPosPElemNames = new ArrayList(); + HorizontalPosPElemNames.add("0"); + fields.add( new UAVObjectField("HorizontalPosP", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, HorizontalPosPElemNames, null) ); + + List VerticalPosPElemNames = new ArrayList(); + VerticalPosPElemNames.add("0"); + fields.add( new UAVObjectField("VerticalPosP", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, VerticalPosPElemNames, null) ); + + List CoursePIElemNames = new ArrayList(); + CoursePIElemNames.add("Kp"); + CoursePIElemNames.add("Ki"); + CoursePIElemNames.add("ILimit"); + fields.add( new UAVObjectField("CoursePI", "deg/deg", UAVObjectField.FieldType.FLOAT32, CoursePIElemNames, null) ); + + List SpeedPElemNames = new ArrayList(); + SpeedPElemNames.add("Kp"); + SpeedPElemNames.add("Max"); + fields.add( new UAVObjectField("SpeedP", "(m/s^2) / ((m/s)/(m/s)", UAVObjectField.FieldType.FLOAT32, SpeedPElemNames, null) ); + + List AccelPIElemNames = new ArrayList(); + AccelPIElemNames.add("Kp"); + AccelPIElemNames.add("Ki"); + AccelPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("AccelPI", "deg / (m/s^2)", UAVObjectField.FieldType.FLOAT32, AccelPIElemNames, null) ); + + List VerticalToPitchCrossFeedElemNames = new ArrayList(); + VerticalToPitchCrossFeedElemNames.add("Kp"); + VerticalToPitchCrossFeedElemNames.add("Max"); + fields.add( new UAVObjectField("VerticalToPitchCrossFeed", "deg / ((m/s)/(m/s))", UAVObjectField.FieldType.FLOAT32, VerticalToPitchCrossFeedElemNames, null) ); + + List AirspeedToVerticalCrossFeedElemNames = new ArrayList(); + AirspeedToVerticalCrossFeedElemNames.add("Kp"); + AirspeedToVerticalCrossFeedElemNames.add("Max"); + fields.add( new UAVObjectField("AirspeedToVerticalCrossFeed", "(m/s) / ((m/s)/(m/s))", UAVObjectField.FieldType.FLOAT32, AirspeedToVerticalCrossFeedElemNames, null) ); + + List PowerPIElemNames = new ArrayList(); + PowerPIElemNames.add("Kp"); + PowerPIElemNames.add("Ki"); + PowerPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("PowerPI", "1/(m/s)", UAVObjectField.FieldType.FLOAT32, PowerPIElemNames, null) ); + + List RollLimitElemNames = new ArrayList(); + RollLimitElemNames.add("Min"); + RollLimitElemNames.add("Neutral"); + RollLimitElemNames.add("Max"); + fields.add( new UAVObjectField("RollLimit", "deg", UAVObjectField.FieldType.FLOAT32, RollLimitElemNames, null) ); + + List PitchLimitElemNames = new ArrayList(); + PitchLimitElemNames.add("Min"); + PitchLimitElemNames.add("Neutral"); + PitchLimitElemNames.add("Max"); + fields.add( new UAVObjectField("PitchLimit", "deg", UAVObjectField.FieldType.FLOAT32, PitchLimitElemNames, null) ); + + List ThrottleLimitElemNames = new ArrayList(); + ThrottleLimitElemNames.add("Min"); + ThrottleLimitElemNames.add("Neutral"); + ThrottleLimitElemNames.add("Max"); + fields.add( new UAVObjectField("ThrottleLimit", "", UAVObjectField.FieldType.FLOAT32, ThrottleLimitElemNames, null) ); + + List UpdatePeriodElemNames = new ArrayList(); + UpdatePeriodElemNames.add("0"); + fields.add( new UAVObjectField("UpdatePeriod", "ms", UAVObjectField.FieldType.INT32, UpdatePeriodElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("AirSpeedMax").setValue(15); + getField("AirSpeedMin").setValue(10); + getField("VerticalVelMax").setValue(10); + getField("HorizontalPosP").setValue(0.05); + getField("VerticalPosP").setValue(0.05); + getField("CoursePI").setValue(0.2,0); + getField("CoursePI").setValue(0,1); + getField("CoursePI").setValue(0,2); + getField("SpeedP").setValue(10,0); + getField("SpeedP").setValue(10,1); + getField("AccelPI").setValue(1.5,0); + getField("AccelPI").setValue(1.5,1); + getField("AccelPI").setValue(20,2); + getField("VerticalToPitchCrossFeed").setValue(50,0); + getField("VerticalToPitchCrossFeed").setValue(5,1); + getField("AirspeedToVerticalCrossFeed").setValue(100,0); + getField("AirspeedToVerticalCrossFeed").setValue(100,1); + getField("PowerPI").setValue(0.01,0); + getField("PowerPI").setValue(0.01,1); + getField("PowerPI").setValue(0.8,2); + getField("RollLimit").setValue(-35,0); + getField("RollLimit").setValue(0,1); + getField("RollLimit").setValue(35,2); + getField("PitchLimit").setValue(-10,0); + getField("PitchLimit").setValue(5,1); + getField("PitchLimit").setValue(20,2); + getField("ThrottleLimit").setValue(0.1,0); + getField("ThrottleLimit").setValue(0.5,1); + getField("ThrottleLimit").setValue(0.9,2); + getField("UpdatePeriod").setValue(100); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FixedWingPathFollowerSettings obj = new FixedWingPathFollowerSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FixedWingPathFollowerSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (FixedWingPathFollowerSettings)(objMngr.getObject(FixedWingPathFollowerSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x8A3F1E02; + protected static final String NAME = "FixedWingPathFollowerSettings"; + protected static String DESCRIPTION = "Settings for the @ref FixedWingPathFollowerModule"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerStatus.java new file mode 100644 index 000000000..a40be35cf --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/FixedWingPathFollowerStatus.java @@ -0,0 +1,164 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Object Storing Debugging Information on PID internals + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Object Storing Debugging Information on PID internals + +generated from fixedwingpathfollowerstatus.xml + **/ +public class FixedWingPathFollowerStatus extends UAVDataObject { + + public FixedWingPathFollowerStatus() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List EElemNames = new ArrayList(); + EElemNames.add("Course"); + EElemNames.add("Speed"); + EElemNames.add("Accel"); + EElemNames.add("Power"); + fields.add( new UAVObjectField("E", "", UAVObjectField.FieldType.FLOAT32, EElemNames, null) ); + + List AElemNames = new ArrayList(); + AElemNames.add("Course"); + AElemNames.add("Speed"); + AElemNames.add("Accel"); + AElemNames.add("Power"); + fields.add( new UAVObjectField("A", "", UAVObjectField.FieldType.FLOAT32, AElemNames, null) ); + + List CElemNames = new ArrayList(); + CElemNames.add("Course"); + CElemNames.add("Speed"); + CElemNames.add("Accel"); + CElemNames.add("Power"); + fields.add( new UAVObjectField("C", "", UAVObjectField.FieldType.FLOAT32, CElemNames, null) ); + + List ErrorsElemNames = new ArrayList(); + ErrorsElemNames.add("Wind"); + ErrorsElemNames.add("Lowspeed"); + ErrorsElemNames.add("Highspeed"); + ErrorsElemNames.add("Lowpower"); + ErrorsElemNames.add("Highpower"); + ErrorsElemNames.add("Pitchcontrol"); + fields.add( new UAVObjectField("Errors", "", UAVObjectField.FieldType.UINT8, ErrorsElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 500; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + FixedWingPathFollowerStatus obj = new FixedWingPathFollowerStatus(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public FixedWingPathFollowerStatus GetInstance(UAVObjectManager objMngr, int instID) + { + return (FixedWingPathFollowerStatus)(objMngr.getObject(FixedWingPathFollowerStatus.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xA0D6F6D4; + protected static final String NAME = "FixedWingPathFollowerStatus"; + protected static String DESCRIPTION = "Object Storing Debugging Information on PID internals"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSettings.java new file mode 100644 index 000000000..f534fc89c --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSSettings.java @@ -0,0 +1,142 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the GPS + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the GPS + +generated from gpssettings.xml + **/ +public class GPSSettings extends UAVDataObject { + + public GPSSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List DataProtocolElemNames = new ArrayList(); + DataProtocolElemNames.add("0"); + List DataProtocolEnumOptions = new ArrayList(); + DataProtocolEnumOptions.add("NMEA"); + DataProtocolEnumOptions.add("UBX"); + fields.add( new UAVObjectField("DataProtocol", "", UAVObjectField.FieldType.ENUM, DataProtocolElemNames, DataProtocolEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("DataProtocol").setValue("NMEA"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GPSSettings obj = new GPSSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GPSSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (GPSSettings)(objMngr.getObject(GPSSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xAC5F6370; + protected static final String NAME = "GPSSettings"; + protected static String DESCRIPTION = "Settings for the GPS"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSVelocity.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSVelocity.java new file mode 100644 index 000000000..2ce4a3c62 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GPSVelocity.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Raw GPS data from @ref GPSModule. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Raw GPS data from @ref GPSModule. + +generated from gpsvelocity.xml + **/ +public class GPSVelocity extends UAVDataObject { + + public GPSVelocity() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List NorthElemNames = new ArrayList(); + NorthElemNames.add("0"); + fields.add( new UAVObjectField("North", "m/s", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); + + List EastElemNames = new ArrayList(); + EastElemNames.add("0"); + fields.add( new UAVObjectField("East", "m/s", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); + + List DownElemNames = new ArrayList(); + DownElemNames.add("0"); + fields.add( new UAVObjectField("Down", "m/s", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GPSVelocity obj = new GPSVelocity(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GPSVelocity GetInstance(UAVObjectManager objMngr, int instID) + { + return (GPSVelocity)(objMngr.getObject(GPSVelocity.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x8245DC80; + protected static final String NAME = "GPSVelocity"; + protected static String DESCRIPTION = "Raw GPS data from @ref GPSModule."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/Gyros.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Gyros.java new file mode 100644 index 000000000..5c960d2e6 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Gyros.java @@ -0,0 +1,150 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The gyro data. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The gyro data. + +generated from gyros.xml + **/ +public class Gyros extends UAVDataObject { + + public Gyros() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List xElemNames = new ArrayList(); + xElemNames.add("0"); + fields.add( new UAVObjectField("x", "deg/s", UAVObjectField.FieldType.FLOAT32, xElemNames, null) ); + + List yElemNames = new ArrayList(); + yElemNames.add("0"); + fields.add( new UAVObjectField("y", "deg/s", UAVObjectField.FieldType.FLOAT32, yElemNames, null) ); + + List zElemNames = new ArrayList(); + zElemNames.add("0"); + fields.add( new UAVObjectField("z", "deg/s", UAVObjectField.FieldType.FLOAT32, zElemNames, null) ); + + List temperatureElemNames = new ArrayList(); + temperatureElemNames.add("0"); + fields.add( new UAVObjectField("temperature", "deg C", UAVObjectField.FieldType.FLOAT32, temperatureElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + Gyros obj = new Gyros(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public Gyros GetInstance(UAVObjectManager objMngr, int instID) + { + return (Gyros)(objMngr.getObject(Gyros.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x4228AF6; + protected static final String NAME = "Gyros"; + protected static String DESCRIPTION = "The gyro data."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/GyrosBias.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GyrosBias.java new file mode 100644 index 000000000..00bc7da2d --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/GyrosBias.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The gyro data. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The gyro data. + +generated from gyrosbias.xml + **/ +public class GyrosBias extends UAVDataObject { + + public GyrosBias() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List xElemNames = new ArrayList(); + xElemNames.add("0"); + fields.add( new UAVObjectField("x", "deg/s", UAVObjectField.FieldType.FLOAT32, xElemNames, null) ); + + List yElemNames = new ArrayList(); + yElemNames.add("0"); + fields.add( new UAVObjectField("y", "deg/s", UAVObjectField.FieldType.FLOAT32, yElemNames, null) ); + + List zElemNames = new ArrayList(); + zElemNames.add("0"); + fields.add( new UAVObjectField("z", "deg/s", UAVObjectField.FieldType.FLOAT32, zElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + GyrosBias obj = new GyrosBias(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public GyrosBias GetInstance(UAVObjectManager objMngr, int instID) + { + return (GyrosBias)(objMngr.getObject(GyrosBias.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xE4B6F980; + protected static final String NAME = "GyrosBias"; + protected static String DESCRIPTION = "The gyro data."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/MagBias.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MagBias.java new file mode 100644 index 000000000..398f455d5 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/MagBias.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The gyro data. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The gyro data. + +generated from magbias.xml + **/ +public class MagBias extends UAVDataObject { + + public MagBias() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List xElemNames = new ArrayList(); + xElemNames.add("0"); + fields.add( new UAVObjectField("x", "mGau", UAVObjectField.FieldType.FLOAT32, xElemNames, null) ); + + List yElemNames = new ArrayList(); + yElemNames.add("0"); + fields.add( new UAVObjectField("y", "mGau", UAVObjectField.FieldType.FLOAT32, yElemNames, null) ); + + List zElemNames = new ArrayList(); + zElemNames.add("0"); + fields.add( new UAVObjectField("z", "mGau", UAVObjectField.FieldType.FLOAT32, zElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + MagBias obj = new MagBias(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public MagBias GetInstance(UAVObjectManager objMngr, int instID) + { + return (MagBias)(objMngr.getObject(MagBias.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x5043E510; + protected static final String NAME = "MagBias"; + protected static String DESCRIPTION = "The gyro data."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/Magnetometer.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Magnetometer.java new file mode 100644 index 000000000..583817cca --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Magnetometer.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The mag data. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The mag data. + +generated from magnetometer.xml + **/ +public class Magnetometer extends UAVDataObject { + + public Magnetometer() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List xElemNames = new ArrayList(); + xElemNames.add("0"); + fields.add( new UAVObjectField("x", "mGa", UAVObjectField.FieldType.FLOAT32, xElemNames, null) ); + + List yElemNames = new ArrayList(); + yElemNames.add("0"); + fields.add( new UAVObjectField("y", "mGa", UAVObjectField.FieldType.FLOAT32, yElemNames, null) ); + + List zElemNames = new ArrayList(); + zElemNames.add("0"); + fields.add( new UAVObjectField("z", "mGa", UAVObjectField.FieldType.FLOAT32, zElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + Magnetometer obj = new Magnetometer(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public Magnetometer GetInstance(UAVObjectManager objMngr, int instID) + { + return (Magnetometer)(objMngr.getObject(Magnetometer.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x813B55DE; + protected static final String NAME = "Magnetometer"; + protected static String DESCRIPTION = "The mag data."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/NEDPosition.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NEDPosition.java new file mode 100644 index 000000000..0aa67862e --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/NEDPosition.java @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Contains the current position relative to @ref HomeLocation + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Contains the current position relative to @ref HomeLocation + +generated from nedposition.xml + **/ +public class NEDPosition extends UAVDataObject { + + public NEDPosition() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List NorthElemNames = new ArrayList(); + NorthElemNames.add("0"); + fields.add( new UAVObjectField("North", "m", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) ); + + List EastElemNames = new ArrayList(); + EastElemNames.add("0"); + fields.add( new UAVObjectField("East", "m", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) ); + + List DownElemNames = new ArrayList(); + DownElemNames.add("0"); + fields.add( new UAVObjectField("Down", "m", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + NEDPosition obj = new NEDPosition(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public NEDPosition GetInstance(UAVObjectManager objMngr, int instID) + { + return (NEDPosition)(objMngr.getObject(NEDPosition.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x1FB15A00; + protected static final String NAME = "NEDPosition"; + protected static String DESCRIPTION = "Contains the current position relative to @ref HomeLocation"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncSettings.java new file mode 100644 index 000000000..c680d230c --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncSettings.java @@ -0,0 +1,143 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings to control the behavior of the overo sync module + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings to control the behavior of the overo sync module + +generated from overosyncsettings.xml + **/ +public class OveroSyncSettings extends UAVDataObject { + + public OveroSyncSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List LogOnElemNames = new ArrayList(); + LogOnElemNames.add("0"); + List LogOnEnumOptions = new ArrayList(); + LogOnEnumOptions.add("Never"); + LogOnEnumOptions.add("Always"); + LogOnEnumOptions.add("Armed"); + fields.add( new UAVObjectField("LogOn", "", UAVObjectField.FieldType.ENUM, LogOnElemNames, LogOnEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("LogOn").setValue("Armed"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + OveroSyncSettings obj = new OveroSyncSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public OveroSyncSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (OveroSyncSettings)(objMngr.getObject(OveroSyncSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xA1ABC278; + protected static final String NAME = "OveroSyncSettings"; + protected static String DESCRIPTION = "Settings to control the behavior of the overo sync module"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncStats.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncStats.java new file mode 100644 index 000000000..4c31f21dd --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncStats.java @@ -0,0 +1,165 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Maintains statistics on transfer rate to and from over + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Maintains statistics on transfer rate to and from over + +generated from overosyncstats.xml + **/ +public class OveroSyncStats extends UAVDataObject { + + public OveroSyncStats() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List SendElemNames = new ArrayList(); + SendElemNames.add("0"); + fields.add( new UAVObjectField("Send", "B/s", UAVObjectField.FieldType.UINT32, SendElemNames, null) ); + + List ReceivedElemNames = new ArrayList(); + ReceivedElemNames.add("0"); + fields.add( new UAVObjectField("Received", "B/s", UAVObjectField.FieldType.UINT32, ReceivedElemNames, null) ); + + List FramesyncErrorsElemNames = new ArrayList(); + FramesyncErrorsElemNames.add("0"); + fields.add( new UAVObjectField("FramesyncErrors", "count", UAVObjectField.FieldType.UINT32, FramesyncErrorsElemNames, null) ); + + List UnderrunErrorsElemNames = new ArrayList(); + UnderrunErrorsElemNames.add("0"); + fields.add( new UAVObjectField("UnderrunErrors", "count", UAVObjectField.FieldType.UINT32, UnderrunErrorsElemNames, null) ); + + List DroppedUpdatesElemNames = new ArrayList(); + DroppedUpdatesElemNames.add("0"); + fields.add( new UAVObjectField("DroppedUpdates", "", UAVObjectField.FieldType.UINT32, DroppedUpdatesElemNames, null) ); + + List PacketsElemNames = new ArrayList(); + PacketsElemNames.add("0"); + fields.add( new UAVObjectField("Packets", "", UAVObjectField.FieldType.UINT32, PacketsElemNames, null) ); + + List ConnectedElemNames = new ArrayList(); + ConnectedElemNames.add("0"); + List ConnectedEnumOptions = new ArrayList(); + ConnectedEnumOptions.add("False"); + ConnectedEnumOptions.add("True"); + fields.add( new UAVObjectField("Connected", "", UAVObjectField.FieldType.ENUM, ConnectedElemNames, ConnectedEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + OveroSyncStats obj = new OveroSyncStats(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public OveroSyncStats GetInstance(UAVObjectManager objMngr, int instID) + { + return (OveroSyncStats)(objMngr.getObject(OveroSyncStats.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xD2085FAC; + protected static final String NAME = "OveroSyncStats"; + protected static String DESCRIPTION = "Maintains statistics on transfer rate to and from over"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathDesired.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathDesired.java new file mode 100644 index 000000000..38e710477 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathDesired.java @@ -0,0 +1,162 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * The endpoint or path the craft is trying to achieve. Can come from @ref ManualControl or @ref PathPlanner + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +The endpoint or path the craft is trying to achieve. Can come from @ref ManualControl or @ref PathPlanner + +generated from pathdesired.xml + **/ +public class PathDesired extends UAVDataObject { + + public PathDesired() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List StartElemNames = new ArrayList(); + StartElemNames.add("North"); + StartElemNames.add("East"); + StartElemNames.add("Down"); + fields.add( new UAVObjectField("Start", "m", UAVObjectField.FieldType.FLOAT32, StartElemNames, null) ); + + List EndElemNames = new ArrayList(); + EndElemNames.add("North"); + EndElemNames.add("East"); + EndElemNames.add("Down"); + fields.add( new UAVObjectField("End", "m", UAVObjectField.FieldType.FLOAT32, EndElemNames, null) ); + + List StartingVelocityElemNames = new ArrayList(); + StartingVelocityElemNames.add("0"); + fields.add( new UAVObjectField("StartingVelocity", "m/s", UAVObjectField.FieldType.FLOAT32, StartingVelocityElemNames, null) ); + + List EndingVelocityElemNames = new ArrayList(); + EndingVelocityElemNames.add("0"); + fields.add( new UAVObjectField("EndingVelocity", "m/s", UAVObjectField.FieldType.FLOAT32, EndingVelocityElemNames, null) ); + + List ModeElemNames = new ArrayList(); + ModeElemNames.add("0"); + List ModeEnumOptions = new ArrayList(); + ModeEnumOptions.add("Endpoint"); + ModeEnumOptions.add("Path"); + ModeEnumOptions.add("Land"); + fields.add( new UAVObjectField("Mode", "", UAVObjectField.FieldType.ENUM, ModeElemNames, ModeEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 1000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + PathDesired obj = new PathDesired(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public PathDesired GetInstance(UAVObjectManager objMngr, int instID) + { + return (PathDesired)(objMngr.getObject(PathDesired.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x5A4DC71A; + protected static final String NAME = "PathDesired"; + protected static String DESCRIPTION = "The endpoint or path the craft is trying to achieve. Can come from @ref ManualControl or @ref PathPlanner "; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathPlannerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathPlannerSettings.java new file mode 100644 index 000000000..fb6b66e19 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PathPlannerSettings.java @@ -0,0 +1,151 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref PathPlanner Module + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref PathPlanner Module + +generated from pathplannersettings.xml + **/ +public class PathPlannerSettings extends UAVDataObject { + + public PathPlannerSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List PathModeElemNames = new ArrayList(); + PathModeElemNames.add("0"); + List PathModeEnumOptions = new ArrayList(); + PathModeEnumOptions.add("ENDPOINT"); + PathModeEnumOptions.add("PATH"); + fields.add( new UAVObjectField("PathMode", "", UAVObjectField.FieldType.ENUM, PathModeElemNames, PathModeEnumOptions) ); + + List PreprogrammedPathElemNames = new ArrayList(); + PreprogrammedPathElemNames.add("0"); + List PreprogrammedPathEnumOptions = new ArrayList(); + PreprogrammedPathEnumOptions.add("NONE"); + PreprogrammedPathEnumOptions.add("10M_BOX"); + PreprogrammedPathEnumOptions.add("LOGO"); + fields.add( new UAVObjectField("PreprogrammedPath", "", UAVObjectField.FieldType.ENUM, PreprogrammedPathElemNames, PreprogrammedPathEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("PathMode").setValue("PATH"); + getField("PreprogrammedPath").setValue("NONE"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + PathPlannerSettings obj = new PathPlannerSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public PathPlannerSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (PathPlannerSettings)(objMngr.getObject(PathPlannerSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x290E45DA; + protected static final String NAME = "PathPlannerSettings"; + protected static String DESCRIPTION = "Settings for the @ref PathPlanner Module"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXSettings.java new file mode 100644 index 000000000..aa5387148 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXSettings.java @@ -0,0 +1,326 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * PipXtreme configurations options. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +PipXtreme configurations options. + +generated from pipxsettings.xml + **/ +public class PipXSettings extends UAVDataObject { + + public PipXSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List PairIDElemNames = new ArrayList(); + PairIDElemNames.add("0"); + fields.add( new UAVObjectField("PairID", "", UAVObjectField.FieldType.UINT32, PairIDElemNames, null) ); + + List FrequencyElemNames = new ArrayList(); + FrequencyElemNames.add("0"); + fields.add( new UAVObjectField("Frequency", "", UAVObjectField.FieldType.UINT32, FrequencyElemNames, null) ); + + List SendTimeoutElemNames = new ArrayList(); + SendTimeoutElemNames.add("0"); + fields.add( new UAVObjectField("SendTimeout", "ms", UAVObjectField.FieldType.UINT16, SendTimeoutElemNames, null) ); + + List TelemetryConfigElemNames = new ArrayList(); + TelemetryConfigElemNames.add("0"); + List TelemetryConfigEnumOptions = new ArrayList(); + TelemetryConfigEnumOptions.add("Disabled"); + TelemetryConfigEnumOptions.add("Serial"); + TelemetryConfigEnumOptions.add("UAVTalk"); + TelemetryConfigEnumOptions.add("GCS"); + TelemetryConfigEnumOptions.add("Debug"); + fields.add( new UAVObjectField("TelemetryConfig", "function", UAVObjectField.FieldType.ENUM, TelemetryConfigElemNames, TelemetryConfigEnumOptions) ); + + List TelemetrySpeedElemNames = new ArrayList(); + TelemetrySpeedElemNames.add("0"); + List TelemetrySpeedEnumOptions = new ArrayList(); + TelemetrySpeedEnumOptions.add("2400"); + TelemetrySpeedEnumOptions.add("4800"); + TelemetrySpeedEnumOptions.add("9600"); + TelemetrySpeedEnumOptions.add("19200"); + TelemetrySpeedEnumOptions.add("38400"); + TelemetrySpeedEnumOptions.add("57600"); + TelemetrySpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("TelemetrySpeed", "bps", UAVObjectField.FieldType.ENUM, TelemetrySpeedElemNames, TelemetrySpeedEnumOptions) ); + + List FlexiConfigElemNames = new ArrayList(); + FlexiConfigElemNames.add("0"); + List FlexiConfigEnumOptions = new ArrayList(); + FlexiConfigEnumOptions.add("Disabled"); + FlexiConfigEnumOptions.add("Serial"); + FlexiConfigEnumOptions.add("UAVTalk"); + FlexiConfigEnumOptions.add("GCS"); + FlexiConfigEnumOptions.add("PPM_In"); + FlexiConfigEnumOptions.add("PPM_Out"); + FlexiConfigEnumOptions.add("RSSI"); + FlexiConfigEnumOptions.add("Debug"); + fields.add( new UAVObjectField("FlexiConfig", "function", UAVObjectField.FieldType.ENUM, FlexiConfigElemNames, FlexiConfigEnumOptions) ); + + List FlexiSpeedElemNames = new ArrayList(); + FlexiSpeedElemNames.add("0"); + List FlexiSpeedEnumOptions = new ArrayList(); + FlexiSpeedEnumOptions.add("2400"); + FlexiSpeedEnumOptions.add("4800"); + FlexiSpeedEnumOptions.add("9600"); + FlexiSpeedEnumOptions.add("19200"); + FlexiSpeedEnumOptions.add("38400"); + FlexiSpeedEnumOptions.add("57600"); + FlexiSpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("FlexiSpeed", "bps", UAVObjectField.FieldType.ENUM, FlexiSpeedElemNames, FlexiSpeedEnumOptions) ); + + List VCPConfigElemNames = new ArrayList(); + VCPConfigElemNames.add("0"); + List VCPConfigEnumOptions = new ArrayList(); + VCPConfigEnumOptions.add("Disabled"); + VCPConfigEnumOptions.add("Serial"); + VCPConfigEnumOptions.add("Debug"); + fields.add( new UAVObjectField("VCPConfig", "function", UAVObjectField.FieldType.ENUM, VCPConfigElemNames, VCPConfigEnumOptions) ); + + List VCPSpeedElemNames = new ArrayList(); + VCPSpeedElemNames.add("0"); + List VCPSpeedEnumOptions = new ArrayList(); + VCPSpeedEnumOptions.add("2400"); + VCPSpeedEnumOptions.add("4800"); + VCPSpeedEnumOptions.add("9600"); + VCPSpeedEnumOptions.add("19200"); + VCPSpeedEnumOptions.add("38400"); + VCPSpeedEnumOptions.add("57600"); + VCPSpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("VCPSpeed", "bps", UAVObjectField.FieldType.ENUM, VCPSpeedElemNames, VCPSpeedEnumOptions) ); + + List RFSpeedElemNames = new ArrayList(); + RFSpeedElemNames.add("0"); + List RFSpeedEnumOptions = new ArrayList(); + RFSpeedEnumOptions.add("2400"); + RFSpeedEnumOptions.add("4800"); + RFSpeedEnumOptions.add("9600"); + RFSpeedEnumOptions.add("19200"); + RFSpeedEnumOptions.add("38400"); + RFSpeedEnumOptions.add("57600"); + RFSpeedEnumOptions.add("115200"); + fields.add( new UAVObjectField("RFSpeed", "bps", UAVObjectField.FieldType.ENUM, RFSpeedElemNames, RFSpeedEnumOptions) ); + + List MaxRFPowerElemNames = new ArrayList(); + MaxRFPowerElemNames.add("0"); + List MaxRFPowerEnumOptions = new ArrayList(); + MaxRFPowerEnumOptions.add("1.25"); + MaxRFPowerEnumOptions.add("1.6"); + MaxRFPowerEnumOptions.add("3.16"); + MaxRFPowerEnumOptions.add("6.3"); + MaxRFPowerEnumOptions.add("12.6"); + MaxRFPowerEnumOptions.add("25"); + MaxRFPowerEnumOptions.add("50"); + MaxRFPowerEnumOptions.add("100"); + fields.add( new UAVObjectField("MaxRFPower", "mW", UAVObjectField.FieldType.ENUM, MaxRFPowerElemNames, MaxRFPowerEnumOptions) ); + + List MinPacketSizeElemNames = new ArrayList(); + MinPacketSizeElemNames.add("0"); + fields.add( new UAVObjectField("MinPacketSize", "bytes", UAVObjectField.FieldType.UINT8, MinPacketSizeElemNames, null) ); + + List FrequencyCalibrationElemNames = new ArrayList(); + FrequencyCalibrationElemNames.add("0"); + fields.add( new UAVObjectField("FrequencyCalibration", "", UAVObjectField.FieldType.UINT8, FrequencyCalibrationElemNames, null) ); + + List AESKeyElemNames = new ArrayList(); + AESKeyElemNames.add("0"); + AESKeyElemNames.add("1"); + AESKeyElemNames.add("2"); + AESKeyElemNames.add("3"); + AESKeyElemNames.add("4"); + AESKeyElemNames.add("5"); + AESKeyElemNames.add("6"); + AESKeyElemNames.add("7"); + AESKeyElemNames.add("8"); + AESKeyElemNames.add("9"); + AESKeyElemNames.add("10"); + AESKeyElemNames.add("11"); + AESKeyElemNames.add("12"); + AESKeyElemNames.add("13"); + AESKeyElemNames.add("14"); + AESKeyElemNames.add("15"); + AESKeyElemNames.add("16"); + AESKeyElemNames.add("17"); + AESKeyElemNames.add("18"); + AESKeyElemNames.add("19"); + AESKeyElemNames.add("20"); + AESKeyElemNames.add("21"); + AESKeyElemNames.add("22"); + AESKeyElemNames.add("23"); + AESKeyElemNames.add("24"); + AESKeyElemNames.add("25"); + AESKeyElemNames.add("26"); + AESKeyElemNames.add("27"); + AESKeyElemNames.add("28"); + AESKeyElemNames.add("29"); + AESKeyElemNames.add("30"); + AESKeyElemNames.add("31"); + fields.add( new UAVObjectField("AESKey", "", UAVObjectField.FieldType.UINT8, AESKeyElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("PairID").setValue(0); + getField("Frequency").setValue(434000000); + getField("SendTimeout").setValue(50); + getField("TelemetryConfig").setValue("UAVTalk"); + getField("TelemetrySpeed").setValue("57600"); + getField("FlexiConfig").setValue("Disabled"); + getField("FlexiSpeed").setValue("57600"); + getField("VCPConfig").setValue("Disabled"); + getField("VCPSpeed").setValue("57600"); + getField("RFSpeed").setValue("115200"); + getField("MaxRFPower").setValue("100"); + getField("MinPacketSize").setValue(50); + getField("FrequencyCalibration").setValue(127); + getField("AESKey").setValue(0,0); + getField("AESKey").setValue(0,1); + getField("AESKey").setValue(0,2); + getField("AESKey").setValue(0,3); + getField("AESKey").setValue(0,4); + getField("AESKey").setValue(0,5); + getField("AESKey").setValue(0,6); + getField("AESKey").setValue(0,7); + getField("AESKey").setValue(0,8); + getField("AESKey").setValue(0,9); + getField("AESKey").setValue(0,10); + getField("AESKey").setValue(0,11); + getField("AESKey").setValue(0,12); + getField("AESKey").setValue(0,13); + getField("AESKey").setValue(0,14); + getField("AESKey").setValue(0,15); + getField("AESKey").setValue(0,16); + getField("AESKey").setValue(0,17); + getField("AESKey").setValue(0,18); + getField("AESKey").setValue(0,19); + getField("AESKey").setValue(0,20); + getField("AESKey").setValue(0,21); + getField("AESKey").setValue(0,22); + getField("AESKey").setValue(0,23); + getField("AESKey").setValue(0,24); + getField("AESKey").setValue(0,25); + getField("AESKey").setValue(0,26); + getField("AESKey").setValue(0,27); + getField("AESKey").setValue(0,28); + getField("AESKey").setValue(0,29); + getField("AESKey").setValue(0,30); + getField("AESKey").setValue(0,31); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + PipXSettings obj = new PipXSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public PipXSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (PipXSettings)(objMngr.getObject(PipXSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xBA192BCA; + protected static final String NAME = "PipXSettings"; + protected static String DESCRIPTION = "PipXtreme configurations options."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXStatus.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXStatus.java new file mode 100644 index 000000000..fb6a91e33 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/PipXStatus.java @@ -0,0 +1,301 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * PipXtreme device status. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +PipXtreme device status. + +generated from pipxstatus.xml + **/ +public class PipXStatus extends UAVDataObject { + + public PipXStatus() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List MinFrequencyElemNames = new ArrayList(); + MinFrequencyElemNames.add("0"); + fields.add( new UAVObjectField("MinFrequency", "Hz", UAVObjectField.FieldType.UINT32, MinFrequencyElemNames, null) ); + + List MaxFrequencyElemNames = new ArrayList(); + MaxFrequencyElemNames.add("0"); + fields.add( new UAVObjectField("MaxFrequency", "Hz", UAVObjectField.FieldType.UINT32, MaxFrequencyElemNames, null) ); + + List FrequencyStepSizeElemNames = new ArrayList(); + FrequencyStepSizeElemNames.add("0"); + fields.add( new UAVObjectField("FrequencyStepSize", "", UAVObjectField.FieldType.FLOAT32, FrequencyStepSizeElemNames, null) ); + + List DeviceIDElemNames = new ArrayList(); + DeviceIDElemNames.add("0"); + fields.add( new UAVObjectField("DeviceID", "", UAVObjectField.FieldType.UINT32, DeviceIDElemNames, null) ); + + List AFCElemNames = new ArrayList(); + AFCElemNames.add("0"); + fields.add( new UAVObjectField("AFC", "", UAVObjectField.FieldType.INT32, AFCElemNames, null) ); + + List PairIDsElemNames = new ArrayList(); + PairIDsElemNames.add("0"); + PairIDsElemNames.add("1"); + PairIDsElemNames.add("2"); + PairIDsElemNames.add("3"); + fields.add( new UAVObjectField("PairIDs", "", UAVObjectField.FieldType.UINT32, PairIDsElemNames, null) ); + + List BoardRevisionElemNames = new ArrayList(); + BoardRevisionElemNames.add("0"); + fields.add( new UAVObjectField("BoardRevision", "", UAVObjectField.FieldType.UINT16, BoardRevisionElemNames, null) ); + + List RetriesElemNames = new ArrayList(); + RetriesElemNames.add("0"); + fields.add( new UAVObjectField("Retries", "", UAVObjectField.FieldType.UINT16, RetriesElemNames, null) ); + + List ErrorsElemNames = new ArrayList(); + ErrorsElemNames.add("0"); + fields.add( new UAVObjectField("Errors", "", UAVObjectField.FieldType.UINT16, ErrorsElemNames, null) ); + + List UAVTalkErrorsElemNames = new ArrayList(); + UAVTalkErrorsElemNames.add("0"); + fields.add( new UAVObjectField("UAVTalkErrors", "", UAVObjectField.FieldType.UINT16, UAVTalkErrorsElemNames, null) ); + + List DroppedElemNames = new ArrayList(); + DroppedElemNames.add("0"); + fields.add( new UAVObjectField("Dropped", "", UAVObjectField.FieldType.UINT16, DroppedElemNames, null) ); + + List ResetsElemNames = new ArrayList(); + ResetsElemNames.add("0"); + fields.add( new UAVObjectField("Resets", "", UAVObjectField.FieldType.UINT16, ResetsElemNames, null) ); + + List TXRateElemNames = new ArrayList(); + TXRateElemNames.add("0"); + fields.add( new UAVObjectField("TXRate", "Bps", UAVObjectField.FieldType.UINT16, TXRateElemNames, null) ); + + List RXRateElemNames = new ArrayList(); + RXRateElemNames.add("0"); + fields.add( new UAVObjectField("RXRate", "Bps", UAVObjectField.FieldType.UINT16, RXRateElemNames, null) ); + + List DescriptionElemNames = new ArrayList(); + DescriptionElemNames.add("0"); + DescriptionElemNames.add("1"); + DescriptionElemNames.add("2"); + DescriptionElemNames.add("3"); + DescriptionElemNames.add("4"); + DescriptionElemNames.add("5"); + DescriptionElemNames.add("6"); + DescriptionElemNames.add("7"); + DescriptionElemNames.add("8"); + DescriptionElemNames.add("9"); + DescriptionElemNames.add("10"); + DescriptionElemNames.add("11"); + DescriptionElemNames.add("12"); + DescriptionElemNames.add("13"); + DescriptionElemNames.add("14"); + DescriptionElemNames.add("15"); + DescriptionElemNames.add("16"); + DescriptionElemNames.add("17"); + DescriptionElemNames.add("18"); + DescriptionElemNames.add("19"); + DescriptionElemNames.add("20"); + DescriptionElemNames.add("21"); + DescriptionElemNames.add("22"); + DescriptionElemNames.add("23"); + DescriptionElemNames.add("24"); + DescriptionElemNames.add("25"); + DescriptionElemNames.add("26"); + DescriptionElemNames.add("27"); + DescriptionElemNames.add("28"); + DescriptionElemNames.add("29"); + DescriptionElemNames.add("30"); + DescriptionElemNames.add("31"); + DescriptionElemNames.add("32"); + DescriptionElemNames.add("33"); + DescriptionElemNames.add("34"); + DescriptionElemNames.add("35"); + DescriptionElemNames.add("36"); + DescriptionElemNames.add("37"); + DescriptionElemNames.add("38"); + DescriptionElemNames.add("39"); + fields.add( new UAVObjectField("Description", "", UAVObjectField.FieldType.UINT8, DescriptionElemNames, null) ); + + List CPUSerialElemNames = new ArrayList(); + CPUSerialElemNames.add("0"); + CPUSerialElemNames.add("1"); + CPUSerialElemNames.add("2"); + CPUSerialElemNames.add("3"); + CPUSerialElemNames.add("4"); + CPUSerialElemNames.add("5"); + CPUSerialElemNames.add("6"); + CPUSerialElemNames.add("7"); + CPUSerialElemNames.add("8"); + CPUSerialElemNames.add("9"); + CPUSerialElemNames.add("10"); + CPUSerialElemNames.add("11"); + fields.add( new UAVObjectField("CPUSerial", "", UAVObjectField.FieldType.UINT8, CPUSerialElemNames, null) ); + + List BoardTypeElemNames = new ArrayList(); + BoardTypeElemNames.add("0"); + fields.add( new UAVObjectField("BoardType", "", UAVObjectField.FieldType.UINT8, BoardTypeElemNames, null) ); + + List FrequencyBandElemNames = new ArrayList(); + FrequencyBandElemNames.add("0"); + fields.add( new UAVObjectField("FrequencyBand", "", UAVObjectField.FieldType.UINT8, FrequencyBandElemNames, null) ); + + List RSSIElemNames = new ArrayList(); + RSSIElemNames.add("0"); + fields.add( new UAVObjectField("RSSI", "dBm", UAVObjectField.FieldType.INT8, RSSIElemNames, null) ); + + List LinkStateElemNames = new ArrayList(); + LinkStateElemNames.add("0"); + List LinkStateEnumOptions = new ArrayList(); + LinkStateEnumOptions.add("Disconnected"); + LinkStateEnumOptions.add("Connecting"); + LinkStateEnumOptions.add("Connected"); + fields.add( new UAVObjectField("LinkState", "function", UAVObjectField.FieldType.ENUM, LinkStateElemNames, LinkStateEnumOptions) ); + + List PairSignalStrengthsElemNames = new ArrayList(); + PairSignalStrengthsElemNames.add("0"); + PairSignalStrengthsElemNames.add("1"); + PairSignalStrengthsElemNames.add("2"); + PairSignalStrengthsElemNames.add("3"); + fields.add( new UAVObjectField("PairSignalStrengths", "dBm", UAVObjectField.FieldType.INT8, PairSignalStrengthsElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READONLY) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("MinFrequency").setValue(0); + getField("MaxFrequency").setValue(0); + getField("FrequencyStepSize").setValue(0); + getField("DeviceID").setValue(0); + getField("AFC").setValue(0); + getField("PairIDs").setValue(0,0); + getField("PairIDs").setValue(0,1); + getField("PairIDs").setValue(0,2); + getField("PairIDs").setValue(0,3); + getField("Retries").setValue(0); + getField("Errors").setValue(0); + getField("UAVTalkErrors").setValue(0); + getField("Dropped").setValue(0); + getField("Resets").setValue(0); + getField("TXRate").setValue(0); + getField("RXRate").setValue(0); + getField("FrequencyBand").setValue(0); + getField("RSSI").setValue(0); + getField("LinkState").setValue("Disconnected"); + getField("PairSignalStrengths").setValue(-127,0); + getField("PairSignalStrengths").setValue(-127,1); + getField("PairSignalStrengths").setValue(-127,2); + getField("PairSignalStrengths").setValue(-127,3); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + PipXStatus obj = new PipXStatus(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public PipXStatus GetInstance(UAVObjectManager objMngr, int instID) + { + return (PipXStatus)(objMngr.getObject(PipXStatus.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x3FC68A86; + protected static final String NAME = "PipXStatus"; + protected static String DESCRIPTION = "PipXtreme device status."; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoCalibration.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoCalibration.java new file mode 100644 index 000000000..940f78875 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoCalibration.java @@ -0,0 +1,249 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the INS to control the algorithm and what is updated + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the INS to control the algorithm and what is updated + +generated from revocalibration.xml + **/ +public class RevoCalibration extends UAVDataObject { + + public RevoCalibration() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List accel_biasElemNames = new ArrayList(); + accel_biasElemNames.add("X"); + accel_biasElemNames.add("Y"); + accel_biasElemNames.add("Z"); + fields.add( new UAVObjectField("accel_bias", "m/s", UAVObjectField.FieldType.FLOAT32, accel_biasElemNames, null) ); + + List accel_scaleElemNames = new ArrayList(); + accel_scaleElemNames.add("X"); + accel_scaleElemNames.add("Y"); + accel_scaleElemNames.add("Z"); + fields.add( new UAVObjectField("accel_scale", "gain", UAVObjectField.FieldType.FLOAT32, accel_scaleElemNames, null) ); + + List accel_varElemNames = new ArrayList(); + accel_varElemNames.add("X"); + accel_varElemNames.add("Y"); + accel_varElemNames.add("Z"); + fields.add( new UAVObjectField("accel_var", "(m/s)^2", UAVObjectField.FieldType.FLOAT32, accel_varElemNames, null) ); + + List gyro_biasElemNames = new ArrayList(); + gyro_biasElemNames.add("X"); + gyro_biasElemNames.add("Y"); + gyro_biasElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_bias", "deg/s", UAVObjectField.FieldType.FLOAT32, gyro_biasElemNames, null) ); + + List gyro_scaleElemNames = new ArrayList(); + gyro_scaleElemNames.add("X"); + gyro_scaleElemNames.add("Y"); + gyro_scaleElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_scale", "gain", UAVObjectField.FieldType.FLOAT32, gyro_scaleElemNames, null) ); + + List gyro_varElemNames = new ArrayList(); + gyro_varElemNames.add("X"); + gyro_varElemNames.add("Y"); + gyro_varElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_var", "(deg/s)^2", UAVObjectField.FieldType.FLOAT32, gyro_varElemNames, null) ); + + List gyro_tempcoeffElemNames = new ArrayList(); + gyro_tempcoeffElemNames.add("X"); + gyro_tempcoeffElemNames.add("Y"); + gyro_tempcoeffElemNames.add("Z"); + fields.add( new UAVObjectField("gyro_tempcoeff", "(deg/s)/deg", UAVObjectField.FieldType.FLOAT32, gyro_tempcoeffElemNames, null) ); + + List mag_biasElemNames = new ArrayList(); + mag_biasElemNames.add("X"); + mag_biasElemNames.add("Y"); + mag_biasElemNames.add("Z"); + fields.add( new UAVObjectField("mag_bias", "mGau", UAVObjectField.FieldType.FLOAT32, mag_biasElemNames, null) ); + + List mag_scaleElemNames = new ArrayList(); + mag_scaleElemNames.add("X"); + mag_scaleElemNames.add("Y"); + mag_scaleElemNames.add("Z"); + fields.add( new UAVObjectField("mag_scale", "gain", UAVObjectField.FieldType.FLOAT32, mag_scaleElemNames, null) ); + + List mag_varElemNames = new ArrayList(); + mag_varElemNames.add("X"); + mag_varElemNames.add("Y"); + mag_varElemNames.add("Z"); + fields.add( new UAVObjectField("mag_var", "mGau^2", UAVObjectField.FieldType.FLOAT32, mag_varElemNames, null) ); + + List gps_varElemNames = new ArrayList(); + gps_varElemNames.add("Pos"); + gps_varElemNames.add("Vel"); + fields.add( new UAVObjectField("gps_var", "m^2", UAVObjectField.FieldType.FLOAT32, gps_varElemNames, null) ); + + List baro_varElemNames = new ArrayList(); + baro_varElemNames.add("0"); + fields.add( new UAVObjectField("baro_var", "m^2", UAVObjectField.FieldType.FLOAT32, baro_varElemNames, null) ); + + List MagBiasNullingRateElemNames = new ArrayList(); + MagBiasNullingRateElemNames.add("0"); + fields.add( new UAVObjectField("MagBiasNullingRate", "", UAVObjectField.FieldType.FLOAT32, MagBiasNullingRateElemNames, null) ); + + List BiasCorrectedRawElemNames = new ArrayList(); + BiasCorrectedRawElemNames.add("0"); + List BiasCorrectedRawEnumOptions = new ArrayList(); + BiasCorrectedRawEnumOptions.add("FALSE"); + BiasCorrectedRawEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("BiasCorrectedRaw", "", UAVObjectField.FieldType.ENUM, BiasCorrectedRawElemNames, BiasCorrectedRawEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("accel_bias").setValue(0,0); + getField("accel_bias").setValue(0,1); + getField("accel_bias").setValue(0,2); + getField("accel_scale").setValue(1,0); + getField("accel_scale").setValue(1,1); + getField("accel_scale").setValue(1,2); + getField("accel_var").setValue(0.01,0); + getField("accel_var").setValue(0.01,1); + getField("accel_var").setValue(0.01,2); + getField("gyro_bias").setValue(0,0); + getField("gyro_bias").setValue(0,1); + getField("gyro_bias").setValue(0,2); + getField("gyro_scale").setValue(1,0); + getField("gyro_scale").setValue(1,1); + getField("gyro_scale").setValue(1,2); + getField("gyro_var").setValue(0.01,0); + getField("gyro_var").setValue(0.01,1); + getField("gyro_var").setValue(0.01,2); + getField("gyro_tempcoeff").setValue(1,0); + getField("gyro_tempcoeff").setValue(1,1); + getField("gyro_tempcoeff").setValue(1,2); + getField("mag_bias").setValue(0,0); + getField("mag_bias").setValue(0,1); + getField("mag_bias").setValue(0,2); + getField("mag_scale").setValue(1,0); + getField("mag_scale").setValue(1,1); + getField("mag_scale").setValue(1,2); + getField("mag_var").setValue(0.01,0); + getField("mag_var").setValue(0.01,1); + getField("mag_var").setValue(10,2); + getField("gps_var").setValue(1,0); + getField("gps_var").setValue(1,1); + getField("baro_var").setValue(1); + getField("MagBiasNullingRate").setValue(0); + getField("BiasCorrectedRaw").setValue("TRUE"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + RevoCalibration obj = new RevoCalibration(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public RevoCalibration GetInstance(UAVObjectManager objMngr, int instID) + { + return (RevoCalibration)(objMngr.getObject(RevoCalibration.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xA2A63C7C; + protected static final String NAME = "RevoCalibration"; + protected static String DESCRIPTION = "Settings for the INS to control the algorithm and what is updated"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoSettings.java new file mode 100644 index 000000000..5e36565b2 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoSettings.java @@ -0,0 +1,143 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the revo to control the algorithm and what is updated + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the revo to control the algorithm and what is updated + +generated from revosettings.xml + **/ +public class RevoSettings extends UAVDataObject { + + public RevoSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List FusionAlgorithmElemNames = new ArrayList(); + FusionAlgorithmElemNames.add("0"); + List FusionAlgorithmEnumOptions = new ArrayList(); + FusionAlgorithmEnumOptions.add("Complimentary"); + FusionAlgorithmEnumOptions.add("INSIndoor"); + FusionAlgorithmEnumOptions.add("INSOutdoor"); + fields.add( new UAVObjectField("FusionAlgorithm", "", UAVObjectField.FieldType.ENUM, FusionAlgorithmElemNames, FusionAlgorithmEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("FusionAlgorithm").setValue("Complimentary"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + RevoSettings obj = new RevoSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public RevoSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (RevoSettings)(objMngr.getObject(RevoSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0xE2DA70EA; + protected static final String NAME = "RevoSettings"; + protected static String DESCRIPTION = "Settings for the revo to control the algorithm and what is updated"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/TxPIDSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TxPIDSettings.java new file mode 100644 index 000000000..789f31b3f --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/TxPIDSettings.java @@ -0,0 +1,225 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings used by @ref TxPID optional module to tune PID settings using R/C transmitter + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings used by @ref TxPID optional module to tune PID settings using R/C transmitter + +generated from txpidsettings.xml + **/ +public class TxPIDSettings extends UAVDataObject { + + public TxPIDSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List ThrottleRangeElemNames = new ArrayList(); + ThrottleRangeElemNames.add("Min"); + ThrottleRangeElemNames.add("Max"); + fields.add( new UAVObjectField("ThrottleRange", "%", UAVObjectField.FieldType.FLOAT32, ThrottleRangeElemNames, null) ); + + List MinPIDElemNames = new ArrayList(); + MinPIDElemNames.add("Instance1"); + MinPIDElemNames.add("Instance2"); + MinPIDElemNames.add("Instance3"); + fields.add( new UAVObjectField("MinPID", "", UAVObjectField.FieldType.FLOAT32, MinPIDElemNames, null) ); + + List MaxPIDElemNames = new ArrayList(); + MaxPIDElemNames.add("Instance1"); + MaxPIDElemNames.add("Instance2"); + MaxPIDElemNames.add("Instance3"); + fields.add( new UAVObjectField("MaxPID", "", UAVObjectField.FieldType.FLOAT32, MaxPIDElemNames, null) ); + + List UpdateModeElemNames = new ArrayList(); + UpdateModeElemNames.add("0"); + List UpdateModeEnumOptions = new ArrayList(); + UpdateModeEnumOptions.add("Never"); + UpdateModeEnumOptions.add("When Armed"); + UpdateModeEnumOptions.add("Always"); + fields.add( new UAVObjectField("UpdateMode", "option", UAVObjectField.FieldType.ENUM, UpdateModeElemNames, UpdateModeEnumOptions) ); + + List InputsElemNames = new ArrayList(); + InputsElemNames.add("Instance1"); + InputsElemNames.add("Instance2"); + InputsElemNames.add("Instance3"); + List InputsEnumOptions = new ArrayList(); + InputsEnumOptions.add("Throttle"); + InputsEnumOptions.add("Accessory0"); + InputsEnumOptions.add("Accessory1"); + InputsEnumOptions.add("Accessory2"); + InputsEnumOptions.add("Accessory3"); + InputsEnumOptions.add("Accessory4"); + InputsEnumOptions.add("Accessory5"); + fields.add( new UAVObjectField("Inputs", "channel", UAVObjectField.FieldType.ENUM, InputsElemNames, InputsEnumOptions) ); + + List PIDsElemNames = new ArrayList(); + PIDsElemNames.add("Instance1"); + PIDsElemNames.add("Instance2"); + PIDsElemNames.add("Instance3"); + List PIDsEnumOptions = new ArrayList(); + PIDsEnumOptions.add("Disabled"); + PIDsEnumOptions.add("Roll Rate.Kp"); + PIDsEnumOptions.add("Pitch Rate.Kp"); + PIDsEnumOptions.add("Roll+Pitch Rate.Kp"); + PIDsEnumOptions.add("Yaw Rate.Kp"); + PIDsEnumOptions.add("Roll Rate.Ki"); + PIDsEnumOptions.add("Pitch Rate.Ki"); + PIDsEnumOptions.add("Roll+Pitch Rate.Ki"); + PIDsEnumOptions.add("Yaw Rate.Ki"); + PIDsEnumOptions.add("Roll Rate.Kd"); + PIDsEnumOptions.add("Pitch Rate.Kd"); + PIDsEnumOptions.add("Roll+Pitch Rate.Kd"); + PIDsEnumOptions.add("Yaw Rate.Kd"); + PIDsEnumOptions.add("Roll Rate.ILimit"); + PIDsEnumOptions.add("Pitch Rate.ILimit"); + PIDsEnumOptions.add("Roll+Pitch Rate.ILimit"); + PIDsEnumOptions.add("Yaw Rate.ILimit"); + PIDsEnumOptions.add("Roll Attitude.Kp"); + PIDsEnumOptions.add("Pitch Attitude.Kp"); + PIDsEnumOptions.add("Roll+Pitch Attitude.Kp"); + PIDsEnumOptions.add("Yaw Attitude.Kp"); + PIDsEnumOptions.add("Roll Attitude.Ki"); + PIDsEnumOptions.add("Pitch Attitude.Ki"); + PIDsEnumOptions.add("Roll+Pitch Attitude.Ki"); + PIDsEnumOptions.add("Yaw Attitude.Ki"); + PIDsEnumOptions.add("Roll Attitude.ILimit"); + PIDsEnumOptions.add("Pitch Attitude.ILimit"); + PIDsEnumOptions.add("Roll+Pitch Attitude.ILimit"); + PIDsEnumOptions.add("Yaw Attitude.ILimit"); + PIDsEnumOptions.add("GyroTau"); + fields.add( new UAVObjectField("PIDs", "option", UAVObjectField.FieldType.ENUM, PIDsElemNames, PIDsEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("ThrottleRange").setValue(0.2,0); + getField("ThrottleRange").setValue(0.8,1); + getField("MinPID").setValue(0,0); + getField("MinPID").setValue(0,1); + getField("MinPID").setValue(0,2); + getField("MaxPID").setValue(0,0); + getField("MaxPID").setValue(0,1); + getField("MaxPID").setValue(0,2); + getField("UpdateMode").setValue("When Armed"); + getField("Inputs").setValue("Throttle",0); + getField("Inputs").setValue("Accessory0",1); + getField("Inputs").setValue("Accessory1",2); + getField("PIDs").setValue("Disabled",0); + getField("PIDs").setValue("Disabled",1); + getField("PIDs").setValue("Disabled",2); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + TxPIDSettings obj = new TxPIDSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public TxPIDSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (TxPIDSettings)(objMngr.getObject(TxPIDSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x42B2D2AE; + protected static final String NAME = "TxPIDSettings"; + protected static String DESCRIPTION = "Settings used by @ref TxPID optional module to tune PID settings using R/C transmitter"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/VtolPathFollowerSettings.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VtolPathFollowerSettings.java new file mode 100644 index 000000000..b3c01dc8a --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/VtolPathFollowerSettings.java @@ -0,0 +1,232 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Settings for the @ref VtolPathFollower module + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Settings for the @ref VtolPathFollower module + +generated from vtolpathfollowersettings.xml + **/ +public class VtolPathFollowerSettings extends UAVDataObject { + + public VtolPathFollowerSettings() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List HorizontalPosPIElemNames = new ArrayList(); + HorizontalPosPIElemNames.add("Kp"); + HorizontalPosPIElemNames.add("Ki"); + HorizontalPosPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("HorizontalPosPI", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) ); + + List HorizontalVelPIDElemNames = new ArrayList(); + HorizontalVelPIDElemNames.add("Kp"); + HorizontalVelPIDElemNames.add("Ki"); + HorizontalVelPIDElemNames.add("Kd"); + HorizontalVelPIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("HorizontalVelPID", "deg/(m/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) ); + + List VerticalPosPIElemNames = new ArrayList(); + VerticalPosPIElemNames.add("Kp"); + VerticalPosPIElemNames.add("Ki"); + VerticalPosPIElemNames.add("ILimit"); + fields.add( new UAVObjectField("VerticalPosPI", "", UAVObjectField.FieldType.FLOAT32, VerticalPosPIElemNames, null) ); + + List VerticalVelPIDElemNames = new ArrayList(); + VerticalVelPIDElemNames.add("Kp"); + VerticalVelPIDElemNames.add("Ki"); + VerticalVelPIDElemNames.add("Kd"); + VerticalVelPIDElemNames.add("ILimit"); + fields.add( new UAVObjectField("VerticalVelPID", "", UAVObjectField.FieldType.FLOAT32, VerticalVelPIDElemNames, null) ); + + List VelocityFeedforwardElemNames = new ArrayList(); + VelocityFeedforwardElemNames.add("0"); + fields.add( new UAVObjectField("VelocityFeedforward", "deg/(m/s)", UAVObjectField.FieldType.FLOAT32, VelocityFeedforwardElemNames, null) ); + + List MaxRollPitchElemNames = new ArrayList(); + MaxRollPitchElemNames.add("0"); + fields.add( new UAVObjectField("MaxRollPitch", "deg", UAVObjectField.FieldType.FLOAT32, MaxRollPitchElemNames, null) ); + + List UpdatePeriodElemNames = new ArrayList(); + UpdatePeriodElemNames.add("0"); + fields.add( new UAVObjectField("UpdatePeriod", "ms", UAVObjectField.FieldType.INT32, UpdatePeriodElemNames, null) ); + + List HorizontalVelMaxElemNames = new ArrayList(); + HorizontalVelMaxElemNames.add("0"); + fields.add( new UAVObjectField("HorizontalVelMax", "m/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) ); + + List VerticalVelMaxElemNames = new ArrayList(); + VerticalVelMaxElemNames.add("0"); + fields.add( new UAVObjectField("VerticalVelMax", "m/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) ); + + List GuidanceModeElemNames = new ArrayList(); + GuidanceModeElemNames.add("0"); + List GuidanceModeEnumOptions = new ArrayList(); + GuidanceModeEnumOptions.add("DUAL_LOOP"); + GuidanceModeEnumOptions.add("VELOCITY_CONTROL"); + fields.add( new UAVObjectField("GuidanceMode", "", UAVObjectField.FieldType.ENUM, GuidanceModeElemNames, GuidanceModeEnumOptions) ); + + List ThrottleControlElemNames = new ArrayList(); + ThrottleControlElemNames.add("0"); + List ThrottleControlEnumOptions = new ArrayList(); + ThrottleControlEnumOptions.add("FALSE"); + ThrottleControlEnumOptions.add("TRUE"); + fields.add( new UAVObjectField("ThrottleControl", "", UAVObjectField.FieldType.ENUM, ThrottleControlElemNames, ThrottleControlEnumOptions) ); + + List VelocitySourceElemNames = new ArrayList(); + VelocitySourceElemNames.add("0"); + List VelocitySourceEnumOptions = new ArrayList(); + VelocitySourceEnumOptions.add("EKF"); + VelocitySourceEnumOptions.add("NEDVEL"); + VelocitySourceEnumOptions.add("GPSPOS"); + fields.add( new UAVObjectField("VelocitySource", "", UAVObjectField.FieldType.ENUM, VelocitySourceElemNames, VelocitySourceEnumOptions) ); + + List PositionSourceElemNames = new ArrayList(); + PositionSourceElemNames.add("0"); + List PositionSourceEnumOptions = new ArrayList(); + PositionSourceEnumOptions.add("EKF"); + PositionSourceEnumOptions.add("GPSPOS"); + fields.add( new UAVObjectField("PositionSource", "", UAVObjectField.FieldType.ENUM, PositionSourceElemNames, PositionSourceEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 0; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + getField("HorizontalPosPI").setValue(1,0); + getField("HorizontalPosPI").setValue(0,1); + getField("HorizontalPosPI").setValue(0,2); + getField("HorizontalVelPID").setValue(5,0); + getField("HorizontalVelPID").setValue(0,1); + getField("HorizontalVelPID").setValue(1,2); + getField("HorizontalVelPID").setValue(0,3); + getField("VerticalPosPI").setValue(0.1,0); + getField("VerticalPosPI").setValue(0.001,1); + getField("VerticalPosPI").setValue(200,2); + getField("VerticalVelPID").setValue(0.1,0); + getField("VerticalVelPID").setValue(0,1); + getField("VerticalVelPID").setValue(0,2); + getField("VerticalVelPID").setValue(0,3); + getField("VelocityFeedforward").setValue(0); + getField("MaxRollPitch").setValue(20); + getField("UpdatePeriod").setValue(100); + getField("HorizontalVelMax").setValue(10); + getField("VerticalVelMax").setValue(1); + getField("GuidanceMode").setValue("DUAL_LOOP"); + getField("ThrottleControl").setValue("FALSE"); + getField("VelocitySource").setValue("EKF"); + getField("PositionSource").setValue("EKF"); + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + VtolPathFollowerSettings obj = new VtolPathFollowerSettings(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public VtolPathFollowerSettings GetInstance(UAVObjectManager objMngr, int instID) + { + return (VtolPathFollowerSettings)(objMngr.getObject(VtolPathFollowerSettings.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x973991F6; + protected static final String NAME = "VtolPathFollowerSettings"; + protected static String DESCRIPTION = "Settings for the @ref VtolPathFollower module"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 1 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/Waypoint.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Waypoint.java new file mode 100644 index 000000000..4db7179ad --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/Waypoint.java @@ -0,0 +1,159 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * A waypoint the aircraft can try and hit. Used by the @ref PathPlanner module + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +A waypoint the aircraft can try and hit. Used by the @ref PathPlanner module + +generated from waypoint.xml + **/ +public class Waypoint extends UAVDataObject { + + public Waypoint() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List PositionElemNames = new ArrayList(); + PositionElemNames.add("North"); + PositionElemNames.add("East"); + PositionElemNames.add("Down"); + fields.add( new UAVObjectField("Position", "m", UAVObjectField.FieldType.FLOAT32, PositionElemNames, null) ); + + List VelocityElemNames = new ArrayList(); + VelocityElemNames.add("North"); + VelocityElemNames.add("East"); + VelocityElemNames.add("Down"); + fields.add( new UAVObjectField("Velocity", "m/s", UAVObjectField.FieldType.FLOAT32, VelocityElemNames, null) ); + + List YawDesiredElemNames = new ArrayList(); + YawDesiredElemNames.add("0"); + fields.add( new UAVObjectField("YawDesired", "deg", UAVObjectField.FieldType.FLOAT32, YawDesiredElemNames, null) ); + + List ActionElemNames = new ArrayList(); + ActionElemNames.add("0"); + List ActionEnumOptions = new ArrayList(); + ActionEnumOptions.add("PathToNext"); + ActionEnumOptions.add("EndpointToNext"); + ActionEnumOptions.add("Land"); + ActionEnumOptions.add("Stop"); + fields.add( new UAVObjectField("Action", "", UAVObjectField.FieldType.ENUM, ActionElemNames, ActionEnumOptions) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_PERIODIC) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 4000; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + Waypoint obj = new Waypoint(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public Waypoint GetInstance(UAVObjectManager objMngr, int instID) + { + return (Waypoint)(objMngr.getObject(Waypoint.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x338C5F90; + protected static final String NAME = "Waypoint"; + protected static String DESCRIPTION = "A waypoint the aircraft can try and hit. Used by the @ref PathPlanner module"; + protected static final boolean ISSINGLEINST = 0 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/uavtalk/uavobjects/WaypointActive.java b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WaypointActive.java new file mode 100644 index 000000000..06f3ab6c4 --- /dev/null +++ b/androidgcs/src/org/openpilot/uavtalk/uavobjects/WaypointActive.java @@ -0,0 +1,138 @@ +/** + ****************************************************************************** + * + * @file uavobjecttemplate.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Template for an uavobject in java + * This is a autogenerated file!! Do not modify and expect a result. + * Indicates the currently active waypoint + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.openpilot.uavtalk.uavobjects; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVDataObject; +import org.openpilot.uavtalk.UAVObjectField; + +/** +Indicates the currently active waypoint + +generated from waypointactive.xml + **/ +public class WaypointActive extends UAVDataObject { + + public WaypointActive() { + super(OBJID, ISSINGLEINST, ISSETTINGS, NAME); + + List fields = new ArrayList(); + + + List IndexElemNames = new ArrayList(); + IndexElemNames.add("0"); + fields.add( new UAVObjectField("Index", "", UAVObjectField.FieldType.UINT8, IndexElemNames, null) ); + + + // Compute the number of bytes for this object + int numBytes = 0; + ListIterator li = fields.listIterator(); + while(li.hasNext()) { + numBytes += li.next().getNumBytes(); + } + NUMBYTES = numBytes; + + // Initialize object + initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES); + // Set the default field values + setDefaultFieldValues(); + // Set the object description + setDescription(DESCRIPTION); + } + + /** + * Create a Metadata object filled with default values for this object + * @return Metadata object with default values + */ + public Metadata getDefaultMetadata() { + UAVObject.Metadata metadata = new UAVObject.Metadata(); + metadata.flags = + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT | + UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT | + 0 << UAVOBJ_TELEMETRY_ACKED_SHIFT | + 0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT | + UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.gcsTelemetryUpdatePeriod = 0; + metadata.loggingUpdatePeriod = 1000; + + return metadata; + } + + /** + * Initialize object fields with the default values. + * If a default value is not specified the object fields + * will be initialized to zero. + */ + public void setDefaultFieldValues() + { + + } + + /** + * Create a clone of this object, a new instance ID must be specified. + * Do not use this function directly to create new instances, the + * UAVObjectManager should be used instead. + */ + public UAVDataObject clone(int instID) { + // TODO: Need to get specific instance to clone + try { + WaypointActive obj = new WaypointActive(); + obj.initialize(instID, this.getMetaObject()); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Static function to retrieve an instance of the object. + */ + public WaypointActive GetInstance(UAVObjectManager objMngr, int instID) + { + return (WaypointActive)(objMngr.getObject(WaypointActive.OBJID, instID)); + } + + // Constants + protected static final int OBJID = 0x1EA5B192; + protected static final String NAME = "WaypointActive"; + protected static String DESCRIPTION = "Indicates the currently active waypoint"; + protected static final boolean ISSINGLEINST = 1 == 1; + protected static final boolean ISSETTINGS = 0 == 1; + protected static int NUMBYTES = 0; + + +} \ No newline at end of file From 45f4ae0701b28581798c4020ee66bb542643bca2 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 02:14:12 -0500 Subject: [PATCH 176/284] Allow selecting the IP address from the preferences --- androidgcs/res/xml/preferences.xml | 2 +- .../src/org/openpilot/androidgcs/TcpUAVTalk.java | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/androidgcs/res/xml/preferences.xml b/androidgcs/res/xml/preferences.xml index 24fd43b5e..285e7b6d7 100644 --- a/androidgcs/res/xml/preferences.xml +++ b/androidgcs/res/xml/preferences.xml @@ -10,6 +10,6 @@ + android:key="ip_address" />
diff --git a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java index 47074f968..f5d40040b 100644 --- a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java +++ b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java @@ -8,6 +8,8 @@ import org.openpilot.uavtalk.UAVObjectManager; import org.openpilot.uavtalk.UAVTalk; import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import android.util.Log; public class TcpUAVTalk { @@ -17,14 +19,17 @@ public class TcpUAVTalk { public static boolean DEBUG = LOGLEVEL > 0; // Temporarily define fixed device name - public final static String IP_ADDRESS = "10.21.18.120"; + private String ip_address = "1"; public final static int PORT = 9001; private UAVTalk uavTalk; private boolean connected; public TcpUAVTalk(Context caller) { - if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + IP_ADDRESS); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(caller); + ip_address = prefs.getString("ip_address","127.0.0.1"); + + if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + ip_address); connected = false; } @@ -47,11 +52,11 @@ public class TcpUAVTalk { private boolean openTelemetryTcp(UAVObjectManager objMngr) { - Log.d(TAG, "Opening conncetion to " + IP_ADDRESS + " at address " + PORT); + Log.d(TAG, "Opening connection to " + ip_address + " at address " + PORT); InetAddress serverAddr = null; try { - serverAddr = InetAddress.getByName(IP_ADDRESS); + serverAddr = InetAddress.getByName(ip_address); } catch (UnknownHostException e1) { // TODO Auto-generated catch block e1.printStackTrace(); From 20b585383d4db87bae20b123676e7cd2a3e27791 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 03:18:26 -0500 Subject: [PATCH 177/284] Make port and bluetooth adapter be listed in the preferences. Using the BT adapter not working yet. --- androidgcs/res/xml/preferences.xml | 8 ++++++++ .../openpilot/androidgcs/BluetoothUAVTalk.java | 17 ++++++++++++----- .../androidgcs/OPTelemetryService.java | 2 +- .../org/openpilot/androidgcs/TcpUAVTalk.java | 12 ++++++++---- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/androidgcs/res/xml/preferences.xml b/androidgcs/res/xml/preferences.xml index 285e7b6d7..3a9103b49 100644 --- a/androidgcs/res/xml/preferences.xml +++ b/androidgcs/res/xml/preferences.xml @@ -11,5 +11,13 @@ android:summary="Enter a TCP/IP address here" android:defaultValue="192.168.0.1" android:title="IP address:" android:key="ip_address" /> + + diff --git a/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java index b240f3adc..c00db0bea 100644 --- a/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java +++ b/androidgcs/src/org/openpilot/androidgcs/BluetoothUAVTalk.java @@ -7,6 +7,7 @@ import java.util.UUID; import org.openpilot.uavtalk.UAVObjectManager; import org.openpilot.uavtalk.UAVTalk; +import android.annotation.TargetApi; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -14,16 +15,18 @@ import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import android.util.Log; -public class BluetoothUAVTalk { +@TargetApi(10) public class BluetoothUAVTalk { private final String TAG = "BluetoothUAVTalk"; public static int LOGLEVEL = 2; public static boolean WARN = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 0; // Temporarily define fixed device name - public final static String DEVICE_NAME = "RN42-222D"; + private String device_name = "RN42-222D"; private final static UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private BluetoothAdapter mBluetoothAdapter; @@ -32,8 +35,12 @@ public class BluetoothUAVTalk { private UAVTalk uavTalk; private boolean connected; - public BluetoothUAVTalk(Context caller, String deviceName) { - if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + deviceName); + public BluetoothUAVTalk(Context caller) { + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(caller); + device_name = prefs.getString("bluetooth_mac",""); + + if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + device_name); connected = false; device = null; @@ -93,7 +100,7 @@ public class BluetoothUAVTalk { // Add the name and address to an array adapter to show in a ListView //mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); Log.d(TAG, "Paired device: " + device.getName()); - if(device.getName().compareTo(DEVICE_NAME) == 0) { + if(device.getName().compareTo(device_name) == 0) { this.device = device; return; } diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java index 917dfb116..13e415c54 100644 --- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java +++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java @@ -277,7 +277,7 @@ public class OPTelemetryService extends Service { Looper.prepare(); - BluetoothUAVTalk bt = new BluetoothUAVTalk(OPTelemetryService.this, BluetoothUAVTalk.DEVICE_NAME); + BluetoothUAVTalk bt = new BluetoothUAVTalk(OPTelemetryService.this); for( int i = 0; i < 10; i++ ) { if (DEBUG) Log.d(TAG, "Attempting Bluetooth Connection"); diff --git a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java index f5d40040b..1f647bd99 100644 --- a/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java +++ b/androidgcs/src/org/openpilot/androidgcs/TcpUAVTalk.java @@ -20,7 +20,7 @@ public class TcpUAVTalk { // Temporarily define fixed device name private String ip_address = "1"; - public final static int PORT = 9001; + private int port = 9001; private UAVTalk uavTalk; private boolean connected; @@ -28,8 +28,12 @@ public class TcpUAVTalk { public TcpUAVTalk(Context caller) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(caller); ip_address = prefs.getString("ip_address","127.0.0.1"); + try { + port = Integer.decode(prefs.getString("port", "")); + } catch (NumberFormatException e) { + } - if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + ip_address); + if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + ip_address); connected = false; } @@ -52,7 +56,7 @@ public class TcpUAVTalk { private boolean openTelemetryTcp(UAVObjectManager objMngr) { - Log.d(TAG, "Opening connection to " + ip_address + " at address " + PORT); + Log.d(TAG, "Opening connection to " + ip_address + " at address " + port); InetAddress serverAddr = null; try { @@ -65,7 +69,7 @@ public class TcpUAVTalk { Socket socket = null; try { - socket = new Socket(serverAddr,PORT); + socket = new Socket(serverAddr,port); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); From a44e84ff9bfad12d35592c155e0e24eb64f5dceb Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 21:00:25 -0500 Subject: [PATCH 178/284] Update the sdk version --- androidgcs/AndroidManifest.xml | 2 +- androidgcs/project.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index c18dc0cb1..40b08c328 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -2,7 +2,7 @@ - + diff --git a/androidgcs/project.properties b/androidgcs/project.properties index 5d85d779c..a43ea8cdc 100644 --- a/androidgcs/project.properties +++ b/androidgcs/project.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=Google Inc.:Google APIs:13 +target=Google Inc.:Google APIs:16 From bf9343532241536197d93031cff7d38af18d93bd Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 21:00:54 -0500 Subject: [PATCH 179/284] Check in a joystick gadget class --- .../Android/Widgets/DockPanel/DockPanel.java | 319 +++++++++++ .../Widgets/DockPanel/DockPosition.java | 5 + .../DragAndDrop/DragAndDropManager.java | 124 +++++ .../Widgets/DragAndDrop/DragSurface.java | 94 ++++ .../Widgets/DragAndDrop/DraggableItem.java | 44 ++ .../DragAndDrop/DraggableViewsFactory.java | 19 + .../Android/Widgets/DragAndDrop/DropZone.java | 67 +++ .../DragAndDrop/DropZoneEventsListener.java | 9 + .../Widgets/Joystick/DualJoystickView.java | 147 +++++ .../Joystick/JoystickClickedListener.java | 6 + .../Joystick/JoystickMovedListener.java | 7 + .../Widgets/Joystick/JoystickView.java | 521 ++++++++++++++++++ .../ThresholdEditText/ThresholdEditText.java | 169 ++++++ .../ThresholdTextChanged.java | 7 + .../Widgets/TilesLayout/SingleTileLayout.java | 68 +++ .../Widgets/TilesLayout/TilePosition.java | 63 +++ .../Widgets/TilesLayout/TilesLayout.java | 299 ++++++++++ .../TilesLayout/TilesLayoutPreset.java | 157 ++++++ 18 files changed, 2125 insertions(+) create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPanel.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPosition.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragAndDropManager.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragSurface.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableItem.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableViewsFactory.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZone.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZoneEventsListener.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/DualJoystickView.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickClickedListener.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickMovedListener.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickView.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdEditText.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdTextChanged.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/SingleTileLayout.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilePosition.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayout.java create mode 100644 androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayoutPreset.java diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPanel.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPanel.java new file mode 100644 index 000000000..e2397394e --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPanel.java @@ -0,0 +1,319 @@ +package com.MobileAnarchy.Android.Widgets.DockPanel; + +import android.content.Context; +import android.graphics.Color; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.Animation; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.TranslateAnimation; +import android.view.animation.Animation.AnimationListener; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.LinearLayout; + +public class DockPanel extends LinearLayout { + + // ========================================= + // Private members + // ========================================= + + private static final String TAG = "DockPanel"; + private DockPosition position; + private int contentLayoutId; + private int handleButtonDrawableId; + private Boolean isOpen; + private Boolean animationRunning; + private FrameLayout contentPlaceHolder; + private ImageButton toggleButton; + private int animationDuration; + + // ========================================= + // Constructors + // ========================================= + + public DockPanel(Context context, int contentLayoutId, + int handleButtonDrawableId, Boolean isOpen) { + super(context); + + this.contentLayoutId = contentLayoutId; + this.handleButtonDrawableId = handleButtonDrawableId; + this.isOpen = isOpen; + + Init(null); + } + + public DockPanel(Context context, AttributeSet attrs) { + super(context, attrs); + + // to prevent from crashing the designer + try { + Init(attrs); + } catch (Exception ex) { + } + } + + // ========================================= + // Initialization + // ========================================= + + private void Init(AttributeSet attrs) { + setDefaultValues(attrs); + + createHandleToggleButton(); + + // create the handle container + FrameLayout handleContainer = new FrameLayout(getContext()); + handleContainer.addView(toggleButton); + + // create and populate the panel's container, and inflate it + contentPlaceHolder = new FrameLayout(getContext()); + String infService = Context.LAYOUT_INFLATER_SERVICE; + LayoutInflater li = (LayoutInflater) getContext().getSystemService( + infService); + li.inflate(contentLayoutId, contentPlaceHolder, true); + + // setting the layout of the panel parameters according to the docking + // position + if (position == DockPosition.LEFT || position == DockPosition.RIGHT) { + handleContainer.setLayoutParams(new LayoutParams( + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, + android.view.ViewGroup.LayoutParams.FILL_PARENT, 1)); + contentPlaceHolder.setLayoutParams(new LayoutParams( + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, + android.view.ViewGroup.LayoutParams.FILL_PARENT, 1)); + } else { + handleContainer.setLayoutParams(new LayoutParams( + android.view.ViewGroup.LayoutParams.FILL_PARENT, + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, 1)); + contentPlaceHolder.setLayoutParams(new LayoutParams( + android.view.ViewGroup.LayoutParams.FILL_PARENT, + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, 1)); + } + + // adding the view to the parent layout according to docking position + if (position == DockPosition.RIGHT || position == DockPosition.BOTTOM) { + this.addView(handleContainer); + this.addView(contentPlaceHolder); + } else { + this.addView(contentPlaceHolder); + this.addView(handleContainer); + } + + if (!isOpen) { + contentPlaceHolder.setVisibility(GONE); + } + } + + private void setDefaultValues(AttributeSet attrs) { + // set default values + isOpen = true; + animationRunning = false; + animationDuration = 500; + setPosition(DockPosition.RIGHT); + + // Try to load values set by xml markup + if (attrs != null) { + String namespace = "http://com.MobileAnarchy.Android.Widgets"; + + animationDuration = attrs.getAttributeIntValue(namespace, + "animationDuration", 500); + contentLayoutId = attrs.getAttributeResourceValue(namespace, + "contentLayoutId", 0); + handleButtonDrawableId = attrs.getAttributeResourceValue( + namespace, "handleButtonDrawableResourceId", 0); + isOpen = attrs.getAttributeBooleanValue(namespace, "isOpen", true); + + // Enums are a bit trickier (needs to be parsed) + try { + position = DockPosition.valueOf(attrs.getAttributeValue( + namespace, "dockPosition").toUpperCase()); + setPosition(position); + } catch (Exception ex) { + // Docking to the left is the default behavior + setPosition(DockPosition.LEFT); + } + } + } + + private void createHandleToggleButton() { + toggleButton = new ImageButton(getContext()); + toggleButton.setPadding(0, 0, 0, 0); + toggleButton.setLayoutParams(new FrameLayout.LayoutParams( + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, + android.view.ViewGroup.LayoutParams.WRAP_CONTENT, + Gravity.CENTER)); + toggleButton.setBackgroundColor(Color.TRANSPARENT); + toggleButton.setImageResource(handleButtonDrawableId); + toggleButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + toggle(); + } + }); + } + + private void setPosition(DockPosition position) { + this.position = position; + switch (position) { + case TOP: + setOrientation(LinearLayout.VERTICAL); + setGravity(Gravity.TOP); + break; + case RIGHT: + setOrientation(LinearLayout.HORIZONTAL); + setGravity(Gravity.RIGHT); + break; + case BOTTOM: + setOrientation(LinearLayout.VERTICAL); + setGravity(Gravity.BOTTOM); + break; + case LEFT: + setOrientation(LinearLayout.HORIZONTAL); + setGravity(Gravity.LEFT); + break; + } + } + + // ========================================= + // Public methods + // ========================================= + + public int getAnimationDuration() { + return animationDuration; + } + + public void setAnimationDuration(int milliseconds) { + animationDuration = milliseconds; + } + + public Boolean getIsRunning() { + return animationRunning; + } + + public void open() { + if (!animationRunning) { + Log.d(TAG, "Opening..."); + + Animation animation = createShowAnimation(); + this.setAnimation(animation); + animation.start(); + + isOpen = true; + } + } + + public void close() { + if (!animationRunning) { + Log.d(TAG, "Closing..."); + + Animation animation = createHideAnimation(); + this.setAnimation(animation); + animation.start(); + isOpen = false; + } + } + + public void toggle() { + if (isOpen) { + close(); + } else { + open(); + } + } + + // ========================================= + // Private methods + // ========================================= + + private Animation createHideAnimation() { + Animation animation = null; + switch (position) { + case TOP: + animation = new TranslateAnimation(0, 0, 0, -contentPlaceHolder + .getHeight()); + break; + case RIGHT: + animation = new TranslateAnimation(0, contentPlaceHolder + .getWidth(), 0, 0); + break; + case BOTTOM: + animation = new TranslateAnimation(0, 0, 0, contentPlaceHolder + .getHeight()); + break; + case LEFT: + animation = new TranslateAnimation(0, -contentPlaceHolder + .getWidth(), 0, 0); + break; + } + + animation.setDuration(animationDuration); + animation.setInterpolator(new AccelerateInterpolator()); + animation.setAnimationListener(new AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + animationRunning = true; + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + contentPlaceHolder.setVisibility(View.GONE); + animationRunning = false; + } + }); + return animation; + } + + private Animation createShowAnimation() { + Animation animation = null; + switch (position) { + case TOP: + animation = new TranslateAnimation(0, 0, -contentPlaceHolder + .getHeight(), 0); + break; + case RIGHT: + animation = new TranslateAnimation(contentPlaceHolder.getWidth(), + 0, 0, 0); + break; + case BOTTOM: + animation = new TranslateAnimation(0, 0, contentPlaceHolder + .getHeight(), 0); + break; + case LEFT: + animation = new TranslateAnimation(-contentPlaceHolder.getWidth(), + 0, 0, 0); + break; + } + Log.d(TAG, "Animation duration: " + animationDuration); + animation.setDuration(animationDuration); + animation.setInterpolator(new DecelerateInterpolator()); + animation.setAnimationListener(new AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + animationRunning = true; + contentPlaceHolder.setVisibility(View.VISIBLE); + Log.d(TAG, "\"Show\" Animation started"); + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + animationRunning = false; + Log.d(TAG, "\"Show\" Animation ended"); + } + }); + return animation; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPosition.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPosition.java new file mode 100644 index 000000000..59643dfc6 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DockPanel/DockPosition.java @@ -0,0 +1,5 @@ +package com.MobileAnarchy.Android.Widgets.DockPanel; + +public enum DockPosition { + TOP, BOTTOM, LEFT, RIGHT +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragAndDropManager.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragAndDropManager.java new file mode 100644 index 000000000..d7e0c5e44 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragAndDropManager.java @@ -0,0 +1,124 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +import java.util.ArrayList; + +import android.content.Context; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnTouchListener; + +public class DragAndDropManager { + + // ========================================= + // Private members + // ========================================= + + protected static final String TAG = "DragAndDropManager"; + private static DragAndDropManager instance = null; + private ArrayList dropZones; + private OnTouchListener originalTouchListener; + private DragSurface dragSurface; + private DraggableItem draggedItem; + private DropZone activeDropZone; + + // ========================================= + // Protected Constructor + // ========================================= + + protected DragAndDropManager() { + // Exists only to defeat instantiation. + dropZones = new ArrayList(); + } + + // ========================================= + // Public Properties + // ========================================= + + public static DragAndDropManager getInstance() { + if (instance == null) { + instance = new DragAndDropManager(); + } + return instance; + } + + public Context getContext() { + if (dragSurface == null) + return null; + + return dragSurface.getContext(); + } + + // ========================================= + // Public Methods + // ========================================= + + public void init(DragSurface surface) { + dragSurface = surface; + clearDropZones(); + } + + public void clearDropZones() { + dropZones.clear(); + } + + public void addDropZone(DropZone dropZone) { + dropZones.add(dropZone); + } + + + public void startDragging(OnTouchListener originalListener, DraggableItem draggedItem) { + originalTouchListener = originalListener; + this.draggedItem = draggedItem; + draggedItem.getSource().setOnTouchListener(new OnTouchListener() { + + @Override + public boolean onTouch(View v, MotionEvent event) { + int[] location = new int[2]; + v.getLocationOnScreen(location); + event.offsetLocation(location[0], location[1]); + invalidateDropZones((int)event.getX(), (int)event.getY()); + return dragSurface.onTouchEvent(event); + } + }); + + dragSurface.startDragging(draggedItem); + } + + + // ========================================= + // Protected Methods + // ========================================= + + protected void invalidateDropZones(int x, int y) { + if (activeDropZone != null) { + if (!activeDropZone.isOver(x, y)) { + activeDropZone.getListener().OnDragZoneLeft(activeDropZone, draggedItem); + activeDropZone = null; + } + else { + // we are still over the same drop zone, no need to check other drop zones + return; + } + } + + for (DropZone dropZone : dropZones) { + if (dropZone.isOver(x, y)) { + activeDropZone = dropZone; + dropZone.getListener().OnDragZoneEntered(activeDropZone, draggedItem); + break; + } + } + } + + protected void stoppedDragging() { + if (activeDropZone != null) { + activeDropZone.getListener().OnDropped(activeDropZone, draggedItem); + } + + // Registering the "old" listener to the view that initiated this drag session + draggedItem.getSource().setOnTouchListener(originalTouchListener); + draggedItem = null; + activeDropZone = null; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragSurface.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragSurface.java new file mode 100644 index 000000000..aebb9d481 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DragSurface.java @@ -0,0 +1,94 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.MotionEvent; +import android.widget.FrameLayout; + +public class DragSurface extends FrameLayout { + + private float draggedViewHalfHeight; + private float draggedViewHalfWidth; + private int framesCount; + + private Boolean isDragging; + private DraggableItem draggedItem; + + public DragSurface(Context context, AttributeSet attrs) { + super(context, attrs); + isDragging = false; + } + + // ========================================= + // Touch Events Listener + // ========================================= + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (isDragging && event.getAction() == MotionEvent.ACTION_UP) { + // Dragging ended + removeAllViews(); + isDragging = false; + + DragAndDropManager.getInstance().stoppedDragging(); + } + + if (isDragging && event.getAction() == MotionEvent.ACTION_MOVE) { + // Move the dragged view to it's new position + repositionView(event.getX(), event.getY()); + + // Mark this event as handled (so that other UI elements will not intercept it) + return true; + } + + return false; + } + + public void startDragging(DraggableItem draggableItem) { + this.draggedItem = draggableItem; + this.draggedItem.getDraggedView().setVisibility(INVISIBLE); + isDragging = true; + addView(this.draggedItem.getDraggedView()); + //repositionView(x, y); + framesCount = 0; + } + + private void repositionView(float x, float y) { + draggedViewHalfHeight = draggedItem.getDraggedView().getHeight() / 2f; + draggedViewHalfWidth = draggedItem.getDraggedView().getWidth() / 2f; + + // If the dragged view was not drawn yet, skip this phase + if (draggedViewHalfHeight == 0 || draggedViewHalfWidth == 0) + return; + + framesCount++; + + //Log.d(TAG, "Original = (x=" + x + ", y=" + y + ")"); + //Log.d(TAG, "Size (W=" + draggedViewHalfWidth + ", H=" + draggedViewHalfHeight + ")"); + + x = x - draggedViewHalfWidth; + y = y - draggedViewHalfHeight; + + x = Math.max(x, 0); + x = Math.min(x, getWidth() - draggedViewHalfWidth * 2); + + y = Math.max(y, 0); + y = Math.min(y, getHeight() - draggedViewHalfHeight * 2); + + //Log.d(TAG, "Moving view to (x=" + x + ", y=" + y + ")"); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT, Gravity.TOP + Gravity.LEFT); + + lp.setMargins((int)x, (int)y, 0, 0); + draggedItem.getDraggedView().setLayoutParams(lp); + + // hte first couple of dragged frame's positions are not calculated correctly, + // so we have a threshold before making the dragged view visible again + if (framesCount < 2) + return; + + draggedItem.getDraggedView().setVisibility(VISIBLE); + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableItem.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableItem.java new file mode 100644 index 000000000..d0c8b7e25 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableItem.java @@ -0,0 +1,44 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +import android.view.View; + +public class DraggableItem { + + // ========================================= + // Private members + // ========================================= + + private View source; + private View draggedView; + private Object tag; + + // ========================================= + // Constructor + // ========================================= + + public DraggableItem(View source, View draggedItem) { + this.source = source; + this.draggedView = draggedItem; + } + + // ========================================= + // Public properties + // ========================================= + + public Object getTag() { + return tag; + } + + public void setTag(Object tag) { + this.tag = tag; + } + + public View getSource() { + return source; + } + + public View getDraggedView() { + return draggedView; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableViewsFactory.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableViewsFactory.java new file mode 100644 index 000000000..246b2392f --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DraggableViewsFactory.java @@ -0,0 +1,19 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +import android.content.Context; +import android.view.View; +import android.widget.TextView; +import android.widget.TableLayout.LayoutParams; + +public class DraggableViewsFactory { + + public static View getLabel(String text) { + Context context = DragAndDropManager.getInstance().getContext(); + TextView textView = new TextView(context); + textView.setText(text); + textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + //textView.setGravity(Gravity.TOP + Gravity.LEFT); + return textView; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZone.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZone.java new file mode 100644 index 000000000..06a8caa17 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZone.java @@ -0,0 +1,67 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +import android.view.View; + +public class DropZone { + + // ========================================= + // Private members + // ========================================= + + private View view; + private DropZoneEventsListener listener; + private int left, top, width, height; + private Boolean dimansionsCalculated; + + // ========================================= + // Constructor + // ========================================= + + public DropZone(View view, DropZoneEventsListener listener) { + this.view = view; + this.listener = listener; + dimansionsCalculated = false; + } + + // ========================================= + // Public properties + // ========================================= + + public View getView() { + return view; + } + + // ========================================= + // Public methods + // ========================================= + + public Boolean isOver(int x, int y) { + if (!dimansionsCalculated) + calculateDimensions(); + + Boolean isOver = (x >= left && x <= (left + width)) && + (y >= top && y <= (top + height)); + + //Log.d("DragZone", "x=" +x + ", left=" + left + ", y=" + y + ", top=" + top + " width=" + width + ", height=" + height + ", isover=" + isOver); + + return isOver; + } + + // ========================================= + // Protected & Private methods + // ========================================= + + protected DropZoneEventsListener getListener() { + return listener; + } + + private void calculateDimensions() { + int[] location = new int[2]; + view.getLocationOnScreen(location); + left = location[0]; + top = location[1]; + width = view.getWidth(); + height = view.getHeight(); + dimansionsCalculated = true; + } +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZoneEventsListener.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZoneEventsListener.java new file mode 100644 index 000000000..828a1cbf2 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/DragAndDrop/DropZoneEventsListener.java @@ -0,0 +1,9 @@ +package com.MobileAnarchy.Android.Widgets.DragAndDrop; + +public interface DropZoneEventsListener { + + void OnDragZoneEntered(DropZone zone, DraggableItem item); + void OnDragZoneLeft(DropZone zone, DraggableItem item); + void OnDropped(DropZone zone, DraggableItem item); + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/DualJoystickView.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/DualJoystickView.java new file mode 100644 index 000000000..bb419d404 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/DualJoystickView.java @@ -0,0 +1,147 @@ +package com.MobileAnarchy.Android.Widgets.Joystick; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +public class DualJoystickView extends LinearLayout { + @SuppressWarnings("unused") + private static final String TAG = DualJoystickView.class.getSimpleName(); + + private final boolean D = false; + private Paint dbgPaint1; + + private JoystickView stickL; + private JoystickView stickR; + + private View pad; + + public DualJoystickView(Context context) { + super(context); + stickL = new JoystickView(context); + stickR = new JoystickView(context); + initDualJoystickView(); + } + + public DualJoystickView(Context context, AttributeSet attrs) { + super(context, attrs); + stickL = new JoystickView(context, attrs); + stickR = new JoystickView(context, attrs); + initDualJoystickView(); + } + + private void initDualJoystickView() { + setOrientation(LinearLayout.HORIZONTAL); + + if ( D ) { + dbgPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG); + dbgPaint1.setColor(Color.CYAN); + dbgPaint1.setStrokeWidth(1); + dbgPaint1.setStyle(Paint.Style.STROKE); + } + + pad = new View(getContext()); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + removeView(stickL); + removeView(stickR); + + float padW = getMeasuredWidth()-(getMeasuredHeight()*2); + int joyWidth = (int) ((getMeasuredWidth()-padW)/2); + LayoutParams joyLParams = new LayoutParams(joyWidth,getMeasuredHeight()); + + stickL.setLayoutParams(joyLParams); + stickR.setLayoutParams(joyLParams); + + stickL.TAG = "L"; + stickR.TAG = "R"; + stickL.setPointerId(JoystickView.INVALID_POINTER_ID); + stickR.setPointerId(JoystickView.INVALID_POINTER_ID); + + addView(stickL); + + ViewGroup.LayoutParams padLParams = new ViewGroup.LayoutParams((int) padW,getMeasuredHeight()); + removeView(pad); + pad.setLayoutParams(padLParams); + addView(pad); + + addView(stickR); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + stickR.setTouchOffset(stickR.getLeft(), stickR.getTop()); + } + + public void setAutoReturnToCenter(boolean left, boolean right) { + stickL.setAutoReturnToCenter(left); + stickR.setAutoReturnToCenter(right); + } + + public void setOnJostickMovedListener(JoystickMovedListener left, JoystickMovedListener right) { + stickL.setOnJostickMovedListener(left); + stickR.setOnJostickMovedListener(right); + } + + public void setOnJostickClickedListener(JoystickClickedListener left, JoystickClickedListener right) { + stickL.setOnJostickClickedListener(left); + stickR.setOnJostickClickedListener(right); + } + + public void setYAxisInverted(boolean leftYAxisInverted, boolean rightYAxisInverted) { + stickL.setYAxisInverted(leftYAxisInverted); + stickL.setYAxisInverted(rightYAxisInverted); + } + + public void setMovementConstraint(int movementConstraint) { + stickL.setMovementConstraint(movementConstraint); + stickR.setMovementConstraint(movementConstraint); + } + + public void setMovementRange(float movementRangeLeft, float movementRangeRight) { + stickL.setMovementRange(movementRangeLeft); + stickR.setMovementRange(movementRangeRight); + } + + public void setMoveResolution(float leftMoveResolution, float rightMoveResolution) { + stickL.setMoveResolution(leftMoveResolution); + stickR.setMoveResolution(rightMoveResolution); + } + + public void setUserCoordinateSystem(int leftCoordinateSystem, int rightCoordinateSystem) { + stickL.setUserCoordinateSystem(leftCoordinateSystem); + stickR.setUserCoordinateSystem(rightCoordinateSystem); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (D) { + canvas.drawRect(1, 1, getMeasuredWidth()-1, getMeasuredHeight()-1, dbgPaint1); + } + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + boolean l = stickL.dispatchTouchEvent(ev); + boolean r = stickR.dispatchTouchEvent(ev); + return l || r; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + boolean l = stickL.onTouchEvent(ev); + boolean r = stickR.onTouchEvent(ev); + return l || r; + } +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickClickedListener.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickClickedListener.java new file mode 100644 index 000000000..128828980 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickClickedListener.java @@ -0,0 +1,6 @@ +package com.MobileAnarchy.Android.Widgets.Joystick; + +public interface JoystickClickedListener { + public void OnClicked(); + public void OnReleased(); +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickMovedListener.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickMovedListener.java new file mode 100644 index 000000000..346f2efed --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickMovedListener.java @@ -0,0 +1,7 @@ +package com.MobileAnarchy.Android.Widgets.Joystick; + +public interface JoystickMovedListener { + public void OnMoved(int pan, int tilt); + public void OnReleased(); + public void OnReturnedToCenter(); +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickView.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickView.java new file mode 100644 index 000000000..bab74e5a7 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/Joystick/JoystickView.java @@ -0,0 +1,521 @@ +package com.MobileAnarchy.Android.Widgets.Joystick; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Handler; +import android.util.AttributeSet; +import android.util.Log; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.View; + +public class JoystickView extends View { + public static final int INVALID_POINTER_ID = -1; + + // ========================================= + // Private Members + // ========================================= + private final boolean D = false; + String TAG = "JoystickView"; + + private Paint dbgPaint1; + private Paint dbgPaint2; + + private Paint bgPaint; + private Paint handlePaint; + + private int innerPadding; + private int bgRadius; + private int handleRadius; + private int movementRadius; + private int handleInnerBoundaries; + + private JoystickMovedListener moveListener; + private JoystickClickedListener clickListener; + + //# of pixels movement required between reporting to the listener + private float moveResolution; + + private boolean yAxisInverted; + private boolean autoReturnToCenter; + + //Max range of movement in user coordinate system + public final static int CONSTRAIN_BOX = 0; + public final static int CONSTRAIN_CIRCLE = 1; + private int movementConstraint; + private float movementRange; + + public final static int COORDINATE_CARTESIAN = 0; //Regular cartesian coordinates + public final static int COORDINATE_DIFFERENTIAL = 1; //Uses polar rotation of 45 degrees to calc differential drive paramaters + private int userCoordinateSystem; + + //Records touch pressure for click handling + private float touchPressure; + private boolean clicked; + private float clickThreshold; + + //Last touch point in view coordinates + private int pointerId = INVALID_POINTER_ID; + private float touchX, touchY; + + //Last reported position in view coordinates (allows different reporting sensitivities) + private float reportX, reportY; + + //Handle center in view coordinates + private float handleX, handleY; + + //Center of the view in view coordinates + private int cX, cY; + + //Size of the view in view coordinates + private int dimX, dimY; + + //Cartesian coordinates of last touch point - joystick center is (0,0) + private int cartX, cartY; + + //Polar coordinates of the touch point from joystick center + private double radial; + private double angle; + + //User coordinates of last touch point + private int userX, userY; + + //Offset co-ordinates (used when touch events are received from parent's coordinate origin) + private int offsetX; + private int offsetY; + + // ========================================= + // Constructors + // ========================================= + + public JoystickView(Context context) { + super(context); + initJoystickView(); + } + + public JoystickView(Context context, AttributeSet attrs) { + super(context, attrs); + initJoystickView(); + } + + public JoystickView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initJoystickView(); + } + + // ========================================= + // Initialization + // ========================================= + + private void initJoystickView() { + setFocusable(true); + + dbgPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG); + dbgPaint1.setColor(Color.RED); + dbgPaint1.setStrokeWidth(1); + dbgPaint1.setStyle(Paint.Style.STROKE); + + dbgPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG); + dbgPaint2.setColor(Color.GREEN); + dbgPaint2.setStrokeWidth(1); + dbgPaint2.setStyle(Paint.Style.STROKE); + + bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + bgPaint.setColor(Color.GRAY); + bgPaint.setStrokeWidth(1); + bgPaint.setStyle(Paint.Style.FILL_AND_STROKE); + + handlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + handlePaint.setColor(Color.DKGRAY); + handlePaint.setStrokeWidth(1); + handlePaint.setStyle(Paint.Style.FILL_AND_STROKE); + + innerPadding = 10; + + setMovementRange(10); + setMoveResolution(1.0f); + setClickThreshold(0.4f); + setYAxisInverted(true); + setUserCoordinateSystem(COORDINATE_CARTESIAN); + setAutoReturnToCenter(true); + } + + public void setAutoReturnToCenter(boolean autoReturnToCenter) { + this.autoReturnToCenter = autoReturnToCenter; + } + + public boolean isAutoReturnToCenter() { + return autoReturnToCenter; + } + + public void setUserCoordinateSystem(int userCoordinateSystem) { + if (userCoordinateSystem < COORDINATE_CARTESIAN || movementConstraint > COORDINATE_DIFFERENTIAL) + Log.e(TAG, "invalid value for userCoordinateSystem"); + else + this.userCoordinateSystem = userCoordinateSystem; + } + + public int getUserCoordinateSystem() { + return userCoordinateSystem; + } + + public void setMovementConstraint(int movementConstraint) { + if (movementConstraint < CONSTRAIN_BOX || movementConstraint > CONSTRAIN_CIRCLE) + Log.e(TAG, "invalid value for movementConstraint"); + else + this.movementConstraint = movementConstraint; + } + + public int getMovementConstraint() { + return movementConstraint; + } + + public boolean isYAxisInverted() { + return yAxisInverted; + } + + public void setYAxisInverted(boolean yAxisInverted) { + this.yAxisInverted = yAxisInverted; + } + + /** + * Set the pressure sensitivity for registering a click + * @param clickThreshold threshold 0...1.0f inclusive. 0 will cause clicks to never be reported, 1.0 is a very hard click + */ + public void setClickThreshold(float clickThreshold) { + if (clickThreshold < 0 || clickThreshold > 1.0f) + Log.e(TAG, "clickThreshold must range from 0...1.0f inclusive"); + else + this.clickThreshold = clickThreshold; + } + + public float getClickThreshold() { + return clickThreshold; + } + + public void setMovementRange(float movementRange) { + this.movementRange = movementRange; + } + + public float getMovementRange() { + return movementRange; + } + + public void setMoveResolution(float moveResolution) { + this.moveResolution = moveResolution; + } + + public float getMoveResolution() { + return moveResolution; + } + + // ========================================= + // Public Methods + // ========================================= + + public void setOnJostickMovedListener(JoystickMovedListener listener) { + this.moveListener = listener; + } + + public void setOnJostickClickedListener(JoystickClickedListener listener) { + this.clickListener = listener; + } + + // ========================================= + // Drawing Functionality + // ========================================= + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Here we make sure that we have a perfect circle + int measuredWidth = measure(widthMeasureSpec); + int measuredHeight = measure(heightMeasureSpec); + setMeasuredDimension(measuredWidth, measuredHeight); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + int d = Math.min(getMeasuredWidth(), getMeasuredHeight()); + + dimX = d; + dimY = d; + + cX = d / 2; + cY = d / 2; + + bgRadius = dimX/2 - innerPadding; + handleRadius = (int)(d * 0.25); + handleInnerBoundaries = handleRadius; + movementRadius = Math.min(cX, cY) - handleInnerBoundaries; + } + + private int measure(int measureSpec) { + int result = 0; + // Decode the measurement specifications. + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + if (specMode == MeasureSpec.UNSPECIFIED) { + // Return a default size of 200 if no bounds are specified. + result = 200; + } else { + // As you want to fill the available space + // always return the full available bounds. + result = specSize; + } + return result; + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.save(); + // Draw the background + canvas.drawCircle(cX, cY, bgRadius, bgPaint); + + // Draw the handle + handleX = touchX + cX; + handleY = touchY + cY; + canvas.drawCircle(handleX, handleY, handleRadius, handlePaint); + + if (D) { + canvas.drawRect(1, 1, getMeasuredWidth()-1, getMeasuredHeight()-1, dbgPaint1); + + canvas.drawCircle(handleX, handleY, 3, dbgPaint1); + + if ( movementConstraint == CONSTRAIN_CIRCLE ) { + canvas.drawCircle(cX, cY, this.movementRadius, dbgPaint1); + } + else { + canvas.drawRect(cX-movementRadius, cY-movementRadius, cX+movementRadius, cY+movementRadius, dbgPaint1); + } + + //Origin to touch point + canvas.drawLine(cX, cY, handleX, handleY, dbgPaint2); + + int baseY = (int) (touchY < 0 ? cY + handleRadius : cY - handleRadius); + canvas.drawText(String.format("%s (%.0f,%.0f)", TAG, touchX, touchY), handleX-20, baseY-7, dbgPaint2); + canvas.drawText("("+ String.format("%.0f, %.1f", radial, angle * 57.2957795) + (char) 0x00B0 + ")", handleX-20, baseY+15, dbgPaint2); + } + +// Log.d(TAG, String.format("touch(%f,%f)", touchX, touchY)); +// Log.d(TAG, String.format("onDraw(%.1f,%.1f)\n\n", handleX, handleY)); + canvas.restore(); + } + + // Constrain touch within a box + private void constrainBox() { + touchX = Math.max(Math.min(touchX, movementRadius), -movementRadius); + touchY = Math.max(Math.min(touchY, movementRadius), -movementRadius); + } + + // Constrain touch within a circle + private void constrainCircle() { + float diffX = touchX; + float diffY = touchY; + double radial = Math.sqrt((diffX*diffX) + (diffY*diffY)); + if ( radial > movementRadius ) { + touchX = (int)((diffX / radial) * movementRadius); + touchY = (int)((diffY / radial) * movementRadius); + } + } + + public void setPointerId(int id) { + this.pointerId = id; + } + + public int getPointerId() { + return pointerId; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + final int action = ev.getAction(); + switch (action & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_MOVE: { + return processMoveEvent(ev); + } + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: { + if ( pointerId != INVALID_POINTER_ID ) { +// Log.d(TAG, "ACTION_UP"); + returnHandleToCenter(); + setPointerId(INVALID_POINTER_ID); + } + break; + } + case MotionEvent.ACTION_POINTER_UP: { + if ( pointerId != INVALID_POINTER_ID ) { + final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + final int pointerId = ev.getPointerId(pointerIndex); + if ( pointerId == this.pointerId ) { +// Log.d(TAG, "ACTION_POINTER_UP: " + pointerId); + returnHandleToCenter(); + setPointerId(INVALID_POINTER_ID); + return true; + } + } + break; + } + case MotionEvent.ACTION_DOWN: { + if ( pointerId == INVALID_POINTER_ID ) { + int x = (int) ev.getX(); + if ( x >= offsetX && x < offsetX + dimX ) { + setPointerId(ev.getPointerId(0)); +// Log.d(TAG, "ACTION_DOWN: " + getPointerId()); + return true; + } + } + break; + } + case MotionEvent.ACTION_POINTER_DOWN: { + if ( pointerId == INVALID_POINTER_ID ) { + final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + final int pointerId = ev.getPointerId(pointerIndex); + int x = (int) ev.getX(pointerId); + if ( x >= offsetX && x < offsetX + dimX ) { +// Log.d(TAG, "ACTION_POINTER_DOWN: " + pointerId); + setPointerId(pointerId); + return true; + } + } + break; + } + } + return false; + } + + private boolean processMoveEvent(MotionEvent ev) { + if ( pointerId != INVALID_POINTER_ID ) { + final int pointerIndex = ev.findPointerIndex(pointerId); + + // Translate touch position to center of view + float x = ev.getX(pointerIndex); + touchX = x - cX - offsetX; + float y = ev.getY(pointerIndex); + touchY = y - cY - offsetY; + +// Log.d(TAG, String.format("ACTION_MOVE: (%03.0f, %03.0f) => (%03.0f, %03.0f)", x, y, touchX, touchY)); + + reportOnMoved(); + invalidate(); + + touchPressure = ev.getPressure(pointerIndex); + reportOnPressure(); + + return true; + } + return false; + } + + private void reportOnMoved() { + if ( movementConstraint == CONSTRAIN_CIRCLE ) + constrainCircle(); + else + constrainBox(); + + calcUserCoordinates(); + + if (moveListener != null) { + boolean rx = Math.abs(touchX - reportX) >= moveResolution; + boolean ry = Math.abs(touchY - reportY) >= moveResolution; + if (rx || ry) { + this.reportX = touchX; + this.reportY = touchY; + +// Log.d(TAG, String.format("moveListener.OnMoved(%d,%d)", (int)userX, (int)userY)); + moveListener.OnMoved(userX, userY); + } + } + } + + private void calcUserCoordinates() { + //First convert to cartesian coordinates + cartX = (int)(touchX / movementRadius * movementRange); + cartY = (int)(touchY / movementRadius * movementRange); + + radial = Math.sqrt((cartX*cartX) + (cartY*cartY)); + angle = Math.atan2(cartY, cartX); + + //Invert Y axis if requested + if ( !yAxisInverted ) + cartY *= -1; + + if ( userCoordinateSystem == COORDINATE_CARTESIAN ) { + userX = cartX; + userY = cartY; + } + else if ( userCoordinateSystem == COORDINATE_DIFFERENTIAL ) { + userX = cartY + cartX / 4; + userY = cartY - cartX / 4; + + if ( userX < -movementRange ) + userX = (int)-movementRange; + if ( userX > movementRange ) + userX = (int)movementRange; + + if ( userY < -movementRange ) + userY = (int)-movementRange; + if ( userY > movementRange ) + userY = (int)movementRange; + } + + } + + //Simple pressure click + private void reportOnPressure() { +// Log.d(TAG, String.format("touchPressure=%.2f", this.touchPressure)); + if ( clickListener != null ) { + if ( clicked && touchPressure < clickThreshold ) { + clickListener.OnReleased(); + this.clicked = false; +// Log.d(TAG, "reset click"); + invalidate(); + } + else if ( !clicked && touchPressure >= clickThreshold ) { + clicked = true; + clickListener.OnClicked(); +// Log.d(TAG, "click"); + invalidate(); + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + } + } + } + + private void returnHandleToCenter() { + if ( autoReturnToCenter ) { + final int numberOfFrames = 5; + final double intervalsX = (0 - touchX) / numberOfFrames; + final double intervalsY = (0 - touchY) / numberOfFrames; + + for (int i = 0; i < numberOfFrames; i++) { + final int j = i; + postDelayed(new Runnable() { + @Override + public void run() { + touchX += intervalsX; + touchY += intervalsY; + + reportOnMoved(); + invalidate(); + + if (moveListener != null && j == numberOfFrames - 1) { + moveListener.OnReturnedToCenter(); + } + } + }, i * 40); + } + + if (moveListener != null) { + moveListener.OnReleased(); + } + } + } + + public void setTouchOffset(int x, int y) { + offsetX = x; + offsetY = y; + } +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdEditText.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdEditText.java new file mode 100644 index 000000000..5fbd76f46 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdEditText.java @@ -0,0 +1,169 @@ +package com.MobileAnarchy.Android.Widgets.ThresholdEditText; + +import android.content.Context; +import android.os.Handler; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.widget.EditText; + +public class ThresholdEditText extends EditText { + + // ========================================= + // Private members + // ========================================= + + private int threshold; + private ThresholdTextChanged thresholdTextChanged; + private Handler handler; + private Runnable invoker; + private boolean thresholdDisabledOnEmptyInput; + + + // ========================================= + // Constructors + // ========================================= + + public ThresholdEditText(Context context) { + super(context); + initAttributes(null); + init(); + } + + public ThresholdEditText(Context context, AttributeSet attrs) { + super(context, attrs); + initAttributes(attrs); + init(); + } + + + // ========================================= + // Public properties + // ========================================= + + /** + * Get the current threshold value + */ + public int getThreshold() { + return threshold; + } + + /** + * Set the threshold value (in milliseconds) + * + * @param threshold + * Threshold value + */ + public void setThreshold(int threshold) { + this.threshold = threshold; + } + + /** + * @return True = the callback will fire immediately when the content of the + * EditText is emptied False = The threshold will be used even on + * empty input + */ + public boolean getThresholdDisabledOnEmptyInput() { + return thresholdDisabledOnEmptyInput; + } + + /** + * @param thresholdDisabledOnEmptyInput + * Set to true if you want the callback to fire immediately when + * the content of the EditText is emptied + */ + public void setThresholdDisabledOnEmptyInput( + boolean thresholdDisabledOnEmptyInput) { + this.thresholdDisabledOnEmptyInput = thresholdDisabledOnEmptyInput; + } + + /** + * Set the callback to the OnThresholdTextChanged event + * + * @param listener + */ + public void setOnThresholdTextChanged(ThresholdTextChanged listener) { + this.thresholdTextChanged = listener; + } + + // ========================================= + // Private / Protected methods + // ========================================= + + /** + * Load properties values from xml layout + */ + private void initAttributes(AttributeSet attrs) { + if (attrs != null) { + String namespace = "http://com.MobileAnarchy.Android.Widgets"; + + // Load values to local members + this.threshold = attrs.getAttributeIntValue(namespace, "threshold", + 500); + this.thresholdDisabledOnEmptyInput = attrs.getAttributeBooleanValue( + namespace, "disableThresholdOnEmptyInput", true); + } else { + // Default threshold value is 0.5 seconds + threshold = 500; + + // Default behaviour on emptied text - no threshold + thresholdDisabledOnEmptyInput = true; + } + } + + /** + * Initialize the private members with default values + */ + private void init() { + + handler = new Handler(); + + invoker = new Runnable() { + + @Override + public void run() { + invokeCallback(); + } + + }; + + this.addTextChangedListener(new TextWatcher() { + + @Override + public void afterTextChanged(Editable s) { + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + // Remove any existing pending callbacks + handler.removeCallbacks(invoker); + + if (s.length() == 0 && thresholdDisabledOnEmptyInput) { + // The text is empty, so invoke the callback immediately + invoker.run(); + } else { + // Post a new delayed callback + handler.postDelayed(invoker, threshold); + } + } + + }); + } + + /** + * Invoking the callback on the listener provided (if provided) + */ + private void invokeCallback() { + if (thresholdTextChanged != null) { + thresholdTextChanged.onThersholdTextChanged(this.getText()); + } + } + +} \ No newline at end of file diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdTextChanged.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdTextChanged.java new file mode 100644 index 000000000..145f6547b --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/ThresholdEditText/ThresholdTextChanged.java @@ -0,0 +1,7 @@ +package com.MobileAnarchy.Android.Widgets.ThresholdEditText; + +import android.text.Editable; + +public interface ThresholdTextChanged { + void onThersholdTextChanged(Editable text); +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/SingleTileLayout.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/SingleTileLayout.java new file mode 100644 index 000000000..d2f3be2d3 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/SingleTileLayout.java @@ -0,0 +1,68 @@ +package com.MobileAnarchy.Android.Widgets.TilesLayout; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; + +public class SingleTileLayout extends FrameLayout { + + // ========================================= + // Private members + // ========================================= + + private TilePosition position; + private long timestamp; + + // ========================================= + // Constructors + // ========================================= + + public SingleTileLayout(Context context) { + super(context); + } + + public SingleTileLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + + // ========================================= + // Public Methods + // ========================================= + + public TilePosition getPosition() { + return position; + } + + public void setPosition(TilePosition position) { + this.position = position; + } + + public long getTimestamp() { + return this.timestamp; + } + + // ========================================= + // Overrides + // ========================================= + + @Override + public void addView(View child) { + super.addView(child); + timestamp = java.lang.System.currentTimeMillis(); + } + + @Override + public void removeAllViews() { + super.removeAllViews(); + timestamp = 0; + } + + @Override + public void removeView(View view) { + super.removeView(view); + timestamp = 0; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilePosition.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilePosition.java new file mode 100644 index 000000000..04bf0c1d4 --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilePosition.java @@ -0,0 +1,63 @@ +package com.MobileAnarchy.Android.Widgets.TilesLayout; + + +public class TilePosition { + + // ========================================= + // Private Members + // ========================================= + + private float x, y, height, width; + + // ========================================= + // Constructors + // ========================================= + + public TilePosition(float x, float y, float width, float height) { + this.x = x; + this.y = y; + this.height = height; + this.width = width; + } + + // ========================================= + // Public Properties + // ========================================= + + public float getX() { + return x; + } + + public float getY() { + return y; + } + + public float getHeight() { + return height; + } + + public float getWidth() { + return width; + } + + + // ========================================= + // Public Methods + // ========================================= + + public Boolean equals(TilePosition position) { + if (position == null) + return false; + + return this.x == position.x && + this.y == position.y && + this.height == position.height && + this.width == position.width; + } + + @Override + public String toString() { + return "TilePosition = [X: " + x + ", Y: " + y + ", Height: " + height + ", Width: " + width + "]"; + } + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayout.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayout.java new file mode 100644 index 000000000..c1728faff --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayout.java @@ -0,0 +1,299 @@ +package com.MobileAnarchy.Android.Widgets.TilesLayout; + +import java.util.ArrayList; +import java.util.List; + +import android.R; +import android.content.Context; +import android.graphics.Color; +import android.os.Handler; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.ScaleAnimation; +import android.view.animation.TranslateAnimation; +import android.view.animation.Animation.AnimationListener; +import android.widget.FrameLayout; + +public class TilesLayout extends FrameLayout { + + // ========================================= + // Private members + // ========================================= + + private static final String TAG = "TilesLayout"; + private int animatedTransitionDuration; + private List tiles; + private TilesLayoutPreset preset; + private int tileBackgroundResourceId; + + // ========================================= + // Constructors + // ========================================= + + public TilesLayout(Context context) { + super(context); + Init(null); + } + + public TilesLayout(Context context, AttributeSet attrs) { + super(context, attrs); + Init(attrs); + } + + + // ========================================= + // Public Properties + // ========================================= + + public void setPreset(TilesLayoutPreset preset) { + try { + rebuildLayout(preset); + this.preset = preset; + } + catch (Exception ex) { + Log.e(TAG, "Failed to set layout preset", ex); + } + } + + public TilesLayoutPreset getPreset() { + return this.preset; + } + + public int getAnimatedTransitionDuration() { + return animatedTransitionDuration; + } + + public void setAnimatedTransitionDuration(int animatedTransitionDuration) { + this.animatedTransitionDuration = animatedTransitionDuration; + } + + public int getTileBackgroundResourceId() { + return tileBackgroundResourceId; + } + + public void setTileBackgroundResourceId(int tileBackgroundResourceId) { + this.tileBackgroundResourceId = tileBackgroundResourceId; + } + + // ========================================= + // Public Methods + // ========================================= + + public void addContent(View view) { + for (int i = 0; i < tiles.size(); i++) { + if (tiles.get(i).getChildCount() == 0) { + tiles.get(i).addView(view); + return; + } + } + // No available space for the new view... + // TODO: Take the tile with the smallest time stamp and place the new view in it + } + + public void clearView(int tileId) { + if (tiles.size() < tileId) { + tiles.get(tileId).removeAllViews(); + } + } + + // ========================================= + // Private Methods + // ========================================= + + private void Init(AttributeSet attrs) { + animatedTransitionDuration = 750; + tileBackgroundResourceId = R.drawable.edit_text; + tiles = new ArrayList(); + } + + + private void rebuildLayout(TilesLayoutPreset preset) { + ArrayList positions = buildViewsPositions(preset); + + // We need to transform the current layout, to the new layout + int extraViews = tiles.size() - positions.size(); + if (extraViews > 0) { + // Remove the extra views + while(tiles.size() - positions.size() > 0) { + int lastViewPosition = tiles.size() - 1; + removeView(tiles.get(lastViewPosition)); + tiles.remove(lastViewPosition); + } + } else { + // Add the extra views + for (int i = tiles.size(); i< positions.size(); i++) { + TilePosition newTilePosition = positions.get(i); + SingleTileLayout tile = new SingleTileLayout(getContext()); + tile.setBackgroundResource(tileBackgroundResourceId); + + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( + (int)newTilePosition.getWidth(), + (int)newTilePosition.getHeight(), + Gravity.TOP + Gravity.LEFT); + lp.setMargins((int)newTilePosition.getX(), + (int)newTilePosition.getY(), 0, 0); + + tile.setLayoutParams(lp); + + tiles.add(tile); + addView(tile); + } + } + // There is a bug in the animation-set, so we'll not animate + animateChange(positions); + + // Regular repositioning (no animation) + //processChange(positions); + } + + + + private ArrayList buildViewsPositions(TilesLayoutPreset preset) { + int width = getWidth(); + int height = getHeight(); + + Log.d(TAG, "Container's Dimensions = Width: " + width + ", Height: " + height); + ArrayList actualPositions = new ArrayList(); + for (TilePosition position : preset.getTilePositions()) { + + int tileX = (int) Math.round(width * ((float)position.getX() / 100.0)); + int tileY = (int) Math.round(height * ((float)position.getY() / 100.0)); + int tileWidth = (int) Math.round(width * ((float)position.getWidth() / 100.0)); + int tileHeight = (int) Math.round(height * ((float)position.getHeight() / 100.0)); + + TilePosition actualPosition = new TilePosition(tileX, tileY, tileWidth, tileHeight); + actualPositions.add(actualPosition); + + Log.d(TAG, "New tile created - X: " + tileX + ", Y: " + tileY + ", Width: " + tileWidth + ", Height: " + tileHeight); + } + return actualPositions; + } + + + @SuppressWarnings("unused") + private void processChange(ArrayList positions) { + for (int i = 0; i < tiles.size(); i++) { + final SingleTileLayout currentTile = tiles.get(i); + final TilePosition targetPosition = positions.get(i); + currentTile.setPosition(targetPosition); + + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( + (int)targetPosition.getWidth(), + (int)targetPosition.getHeight(), + Gravity.TOP + Gravity.LEFT); + lp.setMargins((int)targetPosition.getX(), + (int)targetPosition.getY(), 0, 0); + + currentTile.setLayoutParams(lp); + } + } + + + private void animateChange(ArrayList positions) { + AnimationSet animationSet = new AnimationSet(true); + DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); + + for (int i = 0; i < tiles.size(); i++) { + AnimationSet scaleAndMove = new AnimationSet(true); + scaleAndMove.setFillAfter(true); + + final SingleTileLayout currentTile = tiles.get(i); + TilePosition currentPosition = currentTile.getPosition(); + final TilePosition targetPosition = positions.get(i); + + if (currentPosition == null) { + AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1); + alphaAnimation.setDuration(animatedTransitionDuration); + alphaAnimation.setStartOffset(0); + currentTile.setAnimation(alphaAnimation); + + scaleAndMove.addAnimation(alphaAnimation); + } + + currentTile.setPosition(targetPosition); + + if (!targetPosition.equals(currentPosition)) { + float toXDelta = 0, toYDelta = 0; + if (currentPosition != null) { + // Calculate new position + toXDelta = targetPosition.getX() - currentPosition.getX(); + toYDelta = targetPosition.getY() - currentPosition.getY(); + + // Factor in the scaling animation + toXDelta = toXDelta / (targetPosition.getWidth() / currentPosition.getWidth()); + toYDelta = toYDelta / (targetPosition.getHeight() / currentPosition.getHeight()); + } + + // Move + TranslateAnimation moveAnimation = new TranslateAnimation(0, toXDelta, 0, toYDelta); + moveAnimation.setDuration(animatedTransitionDuration); + moveAnimation.setStartOffset(0); + moveAnimation.setFillAfter(true); + moveAnimation.setInterpolator(decelerateInterpolator); + scaleAndMove.addAnimation(moveAnimation); + + // Physically move the tile when the animation ends + scaleAndMove.setAnimationListener(new AnimationListener() { + + @Override + public void onAnimationStart(Animation animation) { } + + @Override + public void onAnimationRepeat(Animation animation) { } + + @Override + public void onAnimationEnd(Animation animation) { + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( + (int)targetPosition.getWidth(), + (int)targetPosition.getHeight(), + Gravity.TOP + Gravity.LEFT); + lp.setMargins((int)targetPosition.getX(), + (int)targetPosition.getY(), 0, 0); + + currentTile.setLayoutParams(lp); + + // The following null animation just gets rid of screen flicker + animation = new TranslateAnimation(0.0f, 0.0f, 0.0f, 0.0f); + animation.setDuration(1); + currentTile.startAnimation(animation); + } + }); + + // Scale + if (currentPosition != null) { + ScaleAnimation scaleAnimation = + new ScaleAnimation(1, + targetPosition.getWidth() / currentPosition.getWidth(), + 1, + targetPosition.getHeight() / currentPosition.getHeight(), + Animation.ABSOLUTE, 0, + Animation.ABSOLUTE, 0); + + scaleAnimation.setDuration(animatedTransitionDuration); + scaleAnimation.setStartOffset(0); + scaleAnimation.setFillAfter(true); + scaleAndMove.addAnimation(scaleAnimation); + } + + // Set animation to the tile + currentTile.setAnimation(scaleAndMove); + } + // Add to the total animation set + animationSet.addAnimation(scaleAndMove); + } + + if (animationSet.getAnimations().size() > 0) { + Log.d(TAG, "Starting animation"); + animationSet.setFillAfter(true); + animationSet.start(); + } + } + + +} diff --git a/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayoutPreset.java b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayoutPreset.java new file mode 100644 index 000000000..76a13d73b --- /dev/null +++ b/androidgcs/src/com/MobileAnarchy/Android/Widgets/TilesLayout/TilesLayoutPreset.java @@ -0,0 +1,157 @@ +package com.MobileAnarchy.Android.Widgets.TilesLayout; + +import java.util.LinkedList; +import java.util.List; + +/** + * Describes the positioning of a tiles in a 100x100 environment + */ +public class TilesLayoutPreset { + + // ========================================= + // Private Members + // ========================================= + + private List _positions; + private String _presetName; + + // ========================================= + // Constructors + // ========================================= + + public TilesLayoutPreset(String name) { + _presetName = name; + _positions = new LinkedList(); + } + + // ========================================= + // Public Methods + // ========================================= + + public void add(float x, float y, float width, float height) { + TilePosition tilePosition = new TilePosition(x, y, height, width); + add(tilePosition); + } + + public void add(TilePosition tilePosition) { + _positions.add(tilePosition); + } + + public Iterable getTilePositions() { + return _positions; + } + + public int getCount() { + return _positions.size(); + } + + // ========================================= + // Static Presets Factories + // ========================================= + + public static TilesLayoutPreset get1x1() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 1X1"); + preset.add(0, 0, 100, 100); + return preset; + } + + + public static TilesLayoutPreset get1x2() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 1X2"); + preset.add(0, 0, 50, 100); + preset.add(0, 50, 50, 100); + return preset; + } + + + public static TilesLayoutPreset get2x1() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 2X1"); + preset.add(0, 0, 100, 50); + preset.add(50, 0, 100, 50); + return preset; + } + + + public static TilesLayoutPreset get2x2() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 2X2"); + preset.add(0, 0, 50, 50); + preset.add(50, 0, 50, 50); + preset.add(0, 50, 50, 50); + preset.add(50, 50, 50, 50); + return preset; + } + + public static TilesLayoutPreset get3x3() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 3X3"); + preset.add(0, 0, 100/3f, 100/3f); + preset.add(100/3f, 0, 100/3f, 100/3f); + preset.add(200/3f, 0, 100/3f, 100/3f); + preset.add(0, 100/3f, 100/3f, 100/3f); + preset.add(100/3f, 100/3f, 100/3f, 100/3f); + preset.add(200/3f, 100/3f, 100/3f, 100/3f); + preset.add(0, 200/3f, 100/3f, 100/3f); + preset.add(100/3f, 200/3f, 100/3f, 100/3f); + preset.add(200/3f, 200/3f, 100/3f, 100/3f); + return preset; + } + + public static TilesLayoutPreset get3x2() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 3X2"); + preset.add(0, 0, 50, 100/3f); + preset.add(100/3f, 0, 50, 100/3f); + preset.add(200/3f, 0, 50, 100/3f); + preset.add(0, 50, 50, 100/3f); + preset.add(100/3f, 50, 50, 100/3f); + preset.add(200/3f, 50, 50, 100/3f); + return preset; + } + + public static TilesLayoutPreset get2x3() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 2X3"); + preset.add(0, 0, 100/3f, 50); + preset.add(50, 0, 100/3f, 50); + preset.add(0, 100/3f, 100/3f, 50); + preset.add(50, 100/3f, 100/3f, 50); + preset.add(0, 200/3f, 100/3f, 50); + preset.add(50, 200/3f, 100/3f, 50); + return preset; + } + + + public static TilesLayoutPreset get4x4() { + TilesLayoutPreset preset = new TilesLayoutPreset("Default 2X2"); + preset.add(0, 0, 25, 25); + preset.add(25, 0, 25, 25); + preset.add(50, 0, 25, 25); + preset.add(75, 0, 25, 25); + preset.add(0, 25, 25, 25); + preset.add(25, 25, 25, 25); + preset.add(50, 25, 25, 25); + preset.add(75, 25, 25, 25); + preset.add(0, 50, 25, 25); + preset.add(25, 50, 25, 25); + preset.add(50, 50, 25, 25); + preset.add(75, 50, 25, 25); + preset.add(0, 75, 25, 25); + preset.add(25, 75, 25, 25); + preset.add(50, 75, 25, 25); + preset.add(75, 75, 25, 25); + return preset; + } + + public static TilesLayoutPreset get2x3x3() { + TilesLayoutPreset preset = new TilesLayoutPreset("Custom 2X4X4"); + preset.add(0, 0, 50, 50); + preset.add(50, 0, 50, 50); + preset.add(0, 50, 50, 50); + + preset.add(50, 50, 25, 25); + preset.add(75, 50, 25, 25); + preset.add(50, 75, 25, 25); + preset.add(75, 75, 25, 25); + + return preset; + } + + +} From b7cd02c9bfb32738ec339e3877b694801baeede2 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 21:02:05 -0500 Subject: [PATCH 180/284] AndroidGCS: Refactor the UAVO browser to use a split view - objects names on the side and content on the other side. Add a filter for settings versus data. --- androidgcs/res/layout/object_browser.xml | 54 +++++++++++- androidgcs/res/layout/pfd.xml | 34 ++++++-- .../openpilot/androidgcs/ObjectBrowser.java | 84 +++++++++++++------ .../src/org/openpilot/uavtalk/UAVObject.java | 9 +- .../org/openpilot/uavtalk/UAVObjectField.java | 6 +- 5 files changed, 151 insertions(+), 36 deletions(-) diff --git a/androidgcs/res/layout/object_browser.xml b/androidgcs/res/layout/object_browser.xml index 9c7456915..67dc0af76 100644 --- a/androidgcs/res/layout/object_browser.xml +++ b/androidgcs/res/layout/object_browser.xml @@ -2,6 +2,56 @@ - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/androidgcs/res/layout/pfd.xml b/androidgcs/res/layout/pfd.xml index 191a80eb9..5291f2724 100644 --- a/androidgcs/res/layout/pfd.xml +++ b/androidgcs/res/layout/pfd.xml @@ -1,8 +1,30 @@ - - - + + + + + + + + + + + + + diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index a6ed177a2..1a7495ada 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -16,8 +16,12 @@ import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ListView; import android.widget.Spinner; +import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; @@ -27,6 +31,7 @@ import org.openpilot.uavtalk.UAVObject; public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPreferenceChangeListener { private final String TAG = "ObjectBrower"; + int selected_index = -1; boolean connected; SharedPreferences prefs; ArrayAdapter adapter; @@ -35,10 +40,15 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref final Handler uavobjHandler = new Handler(); final Runnable updateText = new Runnable() { public void run() { - Log.d(TAG,"Update"); - update(); + updateObject(); } }; + + private final Observer updatedObserver = new Observer() { + public void update(Observable observable, Object data) { + uavobjHandler.post(updateText); + } + }; /** Called when the activity is first created. */ @Override @@ -47,20 +57,48 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref setContentView(R.layout.object_browser); prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); - - Spinner objectFilter = (Spinner) findViewById(R.id.object_list_filter); } @Override void onOPConnected() { Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT); Log.d(TAG, "onOPConnected()"); + + OnCheckedChangeListener checkListener = new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + updateList(); + } + }; + + ((CheckBox) findViewById(R.id.dataCheck)).setOnCheckedChangeListener(checkListener); + ((CheckBox) findViewById(R.id.settingsCheck)).setOnCheckedChangeListener(checkListener); + + updateList(); + } + + /** + * Populate the list of UAVO objects based on the selected filter + */ + private void updateList() { + // Disconnect any previous signals + if (selected_index > 0) + allObjects.get(selected_index).removeUpdatedObserver(updatedObserver); + selected_index = -1; + + boolean includeData = ((CheckBox) findViewById(R.id.dataCheck)).isChecked(); + boolean includeSettings = ((CheckBox) findViewById(R.id.settingsCheck)).isChecked(); List> allobjects = objMngr.getDataObjects(); allObjects = new ArrayList(); ListIterator> li = allobjects.listIterator(); while(li.hasNext()) { - allObjects.addAll(li.next()); + List objects = li.next(); + if(includeSettings && objects.get(0).isSettings()) + allObjects.addAll(objects); + else if (includeData && !objects.get(0).isSettings()) + allObjects.addAll(objects); } adapter = new ArrayAdapter(this,R.layout.object_view, allObjects); @@ -70,29 +108,25 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref objects.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View view, int position, long id) { - /*Toast.makeText(getApplicationContext(), ((TextView) view).getText(), - Toast.LENGTH_SHORT).show();*/ - Intent intent = new Intent(ObjectBrowser.this, ObjectEditor.class); - intent.putExtra("org.openpilot.androidgcs.ObjectName", allObjects.get(position).getName()); - intent.putExtra("org.openpilot.androidgcs.ObjectId", allObjects.get(position).getObjID()); - intent.putExtra("org.openpilot.androidgcs.InstId", allObjects.get(position).getInstID()); - startActivity(intent); + + if (selected_index > 0) + allObjects.get(selected_index).removeUpdatedObserver(updatedObserver); + + selected_index = position; + allObjects.get(position).addUpdatedObserver(updatedObserver); + updateObject(); } }); - - - UAVObject obj = objMngr.getObject("SystemStats"); - if(obj != null) - obj.addUpdatedObserver(new Observer() { - public void update(Observable observable, Object data) { - uavobjHandler.post(updateText); - } - }); - + } - - public void update() { - adapter.notifyDataSetChanged(); + + private void updateObject() { + //adapter.notifyDataSetChanged(); + TextView text = (TextView) findViewById(R.id.object_information); + if (selected_index >= 0 && selected_index < allObjects.size()) + text.setText(allObjects.get(selected_index).toStringData()); + else + Log.d(TAG,"Update called but invalid index: " + selected_index); } public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index 28c279040..087d2b808 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -52,6 +52,11 @@ public abstract class UAVObject { } private CallbackListener updatedListeners = new CallbackListener(this); + public void removeUpdatedObserver(Observer o) { + synchronized(updatedListeners) { + updatedListeners.deleteObserver(o); + } + } public void addUpdatedObserver(Observer o) { synchronized(updatedListeners) { updatedListeners.addObserver(o); @@ -730,14 +735,14 @@ public abstract class UAVObject { */ @Override public String toString() { - return toStringBrief() + toStringData(); + return toStringBrief(); // + toStringData(); } /** * Return a string with the object information (only the header) */ public String toStringBrief() { - return getName() + " (" + Integer.toHexString(getObjID()) + " " + Integer.toHexString(getInstID()) + " " + getNumBytes() + ")\n"; + return getName(); // + " (" + Integer.toHexString(getObjID()) + " " + Integer.toHexString(getInstID()) + " " + getNumBytes() + ")\n"; } /** diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index 3ed221079..af707d3a0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -469,7 +469,11 @@ public class UAVObjectField { public String toString() { String sout = new String(); - sout += name + ": " + data.toString() + " (" + units + ")\n"; + sout += name + ": " + getValue().toString(); + if (units.length() > 0) + sout += " (" + units + ")\n"; + else + sout += "\n"; return sout; } From 0348a8921eb3d25adf8175b566235b2c3d1e3145 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 22:20:00 -0500 Subject: [PATCH 181/284] AndroidGCS: Output all fields from the UAVObjects --- androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java index af707d3a0..988642ff0 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java @@ -469,7 +469,14 @@ public class UAVObjectField { public String toString() { String sout = new String(); - sout += name + ": " + getValue().toString(); + sout += name + ": "; + for (int i = 0; i < numElements; i++) { + sout += getValue(i).toString(); + if (i != numElements-1) + sout += ", "; + else + sout += " "; + } if (units.length() > 0) sout += " (" + units + ")\n"; else From 3a3ac552da368015b5a87e00991a4903b6a1cea5 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sat, 4 Aug 2012 23:00:25 -0500 Subject: [PATCH 182/284] AndroidGCS: Refine the graphics of the object editor --- androidgcs/AndroidManifest.xml | 4 +- androidgcs/res/layout/object_browser.xml | 71 ++++++++--- androidgcs/res/layout/object_edit.xml | 9 -- androidgcs/res/layout/object_editor.xml | 49 +++++++- .../openpilot/androidgcs/ObjectBrowser.java | 19 ++- .../openpilot/androidgcs/ObjectEditView.java | 117 ++++++++---------- .../openpilot/androidgcs/ObjectEditor.java | 18 ++- 7 files changed, 179 insertions(+), 108 deletions(-) delete mode 100644 androidgcs/res/layout/object_edit.xml diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index 40b08c328..52bf9cb30 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -2,14 +2,14 @@ - + - + diff --git a/androidgcs/res/layout/object_browser.xml b/androidgcs/res/layout/object_browser.xml index 67dc0af76..567c04f15 100644 --- a/androidgcs/res/layout/object_browser.xml +++ b/androidgcs/res/layout/object_browser.xml @@ -1,10 +1,13 @@ - + - + + + - - - + android:drawSelectorOnTop="true" + android:choiceMode="singleChoice"/> + + + + + + + + + + + - - diff --git a/androidgcs/res/layout/object_editor.xml b/androidgcs/res/layout/object_editor.xml index d93b1a097..be6e219e8 100644 --- a/androidgcs/res/layout/object_editor.xml +++ b/androidgcs/res/layout/object_editor.xml @@ -1,6 +1,45 @@ - - + + + + + + + + + + + + + + + android:layout_column="1" + android:layout_gravity="center" + android:layout_row="0" + android:layout_rowSpan="2" + android:background="@android:color/transparent" + android:drawableTop="@drawable/ic_map" + android:text="@string/location_name" /> + android:layout_column="2" + android:layout_gravity="center" + android:layout_row="0" + android:layout_rowSpan="2" + android:background="@android:color/transparent" + android:drawableTop="@drawable/ic_pfd" + android:text="@string/pfd_name" /> - \ No newline at end of file +