123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797 |
- /*
- Common GCS MAVLink functions for all vehicle types
- 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, see <http://www.gnu.org/licenses/>.
- */
- #include "GCS.h"
- #include <AP_AHRS/AP_AHRS.h>
- #include <AP_HAL/AP_HAL.h>
- #include <AP_Arming/AP_Arming.h>
- #include <AP_InternalError/AP_InternalError.h>
- #include <AP_Logger/AP_Logger.h>
- #include <AP_OpticalFlow/AP_OpticalFlow.h>
- #include <AP_Vehicle/AP_Vehicle.h>
- #include <AP_RangeFinder/RangeFinder_Backend.h>
- #include <AP_Airspeed/AP_Airspeed.h>
- #include <AP_Camera/AP_Camera.h>
- #include <AP_Gripper/AP_Gripper.h>
- #include <AP_BLHeli/AP_BLHeli.h>
- #include <AP_RSSI/AP_RSSI.h>
- #include <AP_RTC/AP_RTC.h>
- #include <AP_Scheduler/AP_Scheduler.h>
- #include <AP_SerialManager/AP_SerialManager.h>
- #include <AP_Mount/AP_Mount.h>
- #include <AP_Common/AP_FWVersion.h>
- #include <AP_VisualOdom/AP_VisualOdom.h>
- #include <AP_OpticalFlow/OpticalFlow.h>
- #include <AP_Baro/AP_Baro.h>
- #include <stdio.h>
- #if HAL_RCINPUT_WITH_AP_RADIO
- #include <AP_Radio/AP_Radio.h>
- #include <AP_BoardConfig/AP_BoardConfig.h>
- #endif
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- #include <SITL/SITL.h>
- #endif
- #if HAL_WITH_UAVCAN
- #include <AP_BoardConfig/AP_BoardConfig_CAN.h>
- #include <AP_Common/AP_Common.h>
- // To be replaced with macro saying if KDECAN library is included
- #if APM_BUILD_TYPE(APM_BUILD_ArduCopter) || APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_TYPE(APM_BUILD_ArduSub)
- #include <AP_KDECAN/AP_KDECAN.h>
- #endif
- #include <AP_ToshibaCAN/AP_ToshibaCAN.h>
- #endif
- #include <AP_BattMonitor/AP_BattMonitor.h>
- #include <AP_GPS/AP_GPS.h>
- #include <AP_UAVCAN/AP_UAVCAN.h>
- #include "../../ArduSub/Sub.h"
- extern const AP_HAL::HAL& hal;
- uint32_t GCS_MAVLINK::last_radio_status_remrssi_ms;
- uint8_t GCS_MAVLINK::mavlink_active = 0;
- uint8_t GCS_MAVLINK::chan_is_streaming = 0;
- uint32_t GCS_MAVLINK::reserve_param_space_start_ms;
- // private channels are ones used for point-to-point protocols, and
- // don't get broadcasts or fwded packets
- uint8_t GCS_MAVLINK::mavlink_private = 0;
- GCS *GCS::_singleton = nullptr;
- GCS_MAVLINK::GCS_MAVLINK(GCS_MAVLINK_Parameters ¶meters,
- AP_HAL::UARTDriver &uart)
- {
- _port = &uart;
- streamRates = parameters.streamRates;
- }
- bool GCS_MAVLINK::init(uint8_t instance)
- {
- // search for serial port
- const AP_SerialManager& serial_manager = AP::serialmanager();
- const AP_SerialManager::SerialProtocol protocol = AP_SerialManager::SerialProtocol_MAVLink;
- // get associated mavlink channel
- if (!serial_manager.get_mavlink_channel(protocol, instance, chan)) {
- // return immediately in unlikely case mavlink channel cannot be found
- return false;
- }
- // and init the gcs instance
- if (!valid_channel(chan)) {
- return false;
- }
- /*
- Now try to cope with SiK radios that may be stuck in bootloader
- mode because CTS was held while powering on. This tells the
- bootloader to wait for a firmware. It affects any SiK radio with
- CTS connected that is externally powered. To cope we send 0x30
- 0x20 at 115200 on startup, which tells the bootloader to reset
- and boot normally
- */
- _port->begin(115200);
- AP_HAL::UARTDriver::flow_control old_flow_control = _port->get_flow_control();
- _port->set_flow_control(AP_HAL::UARTDriver::FLOW_CONTROL_DISABLE);
- for (uint8_t i=0; i<3; i++) {
- hal.scheduler->delay(1);
- _port->write(0x30);
- _port->write(0x20);
- }
- // since tcdrain() and TCSADRAIN may not be implemented...
- hal.scheduler->delay(1);
-
- _port->set_flow_control(old_flow_control);
- // now change back to desired baudrate
- _port->begin(serial_manager.find_baudrate(protocol, instance));
- mavlink_comm_port[chan] = _port;
- // create performance counters
- snprintf(_perf_packet_name, sizeof(_perf_packet_name), "GCS_Packet_%u", chan);
- _perf_packet = hal.util->perf_alloc(AP_HAL::Util::PC_ELAPSED, _perf_packet_name);
- snprintf(_perf_update_name, sizeof(_perf_update_name), "GCS_Update_%u", chan);
- _perf_update = hal.util->perf_alloc(AP_HAL::Util::PC_ELAPSED, _perf_update_name);
- AP_SerialManager::SerialProtocol mavlink_protocol = serial_manager.get_mavlink_protocol(chan);
- mavlink_status_t *status = mavlink_get_channel_status(chan);
- if (status == nullptr) {
- return false;
- }
-
- if (mavlink_protocol == AP_SerialManager::SerialProtocol_MAVLink2) {
- // load signing key
- load_signing_key();
- if (status->signing == nullptr) {
- // if signing is off start by sending MAVLink1.
- status->flags |= MAVLINK_STATUS_FLAG_OUT_MAVLINK1;
- }
- } else if (status) {
- // user has asked to only send MAVLink1
- status->flags |= MAVLINK_STATUS_FLAG_OUT_MAVLINK1;
- }
- if (chan == MAVLINK_COMM_0) {
- // Always start with MAVLink1 on first port for now, to allow for recovery
- // after experiments with MAVLink2
- status->flags |= MAVLINK_STATUS_FLAG_OUT_MAVLINK1;
- }
- return true;
- }
- void GCS_MAVLINK::send_meminfo(void)
- {
- unsigned __brkval = 0;
- uint32_t memory = hal.util->available_memory();
- mavlink_msg_meminfo_send(chan, __brkval, MIN(memory, 0xFFFFU), memory);
- }
- // report power supply status
- void GCS_MAVLINK::send_power_status(void)
- {
- if (!gcs().vehicle_initialised()) {
- // avoid unnecessary errors being reported to user
- return;
- }
- mavlink_msg_power_status_send(chan,
- hal.analogin->board_voltage() * 1000,
- hal.analogin->servorail_voltage() * 1000,
- hal.analogin->power_status_flags());
- }
- void GCS_MAVLINK::send_battery_status(const uint8_t instance) const
- {
- // catch the battery backend not supporting the required number of cells
- static_assert(sizeof(AP_BattMonitor::cells) >= (sizeof(uint16_t) * MAVLINK_MSG_BATTERY_STATUS_FIELD_VOLTAGES_LEN),
- "Not enough battery cells for the MAVLink message");
- const AP_BattMonitor &battery = AP::battery();
- float temp;
- bool got_temperature = battery.get_temperature(temp, instance);
- // ensure we always send a voltage estimate to the GCS, because not all battery monitors monitor individual cells
- // as a work around for this we create a set of fake cells to be used if the backend doesn't provide direct monitoring
- // the GCS can then recover the pack voltage by summing all non ignored cell values. Because this is looped we can
- // report a pack up to 655.34 V with this method
- AP_BattMonitor::cells fake_cells;
- if (!battery.has_cell_voltages(instance)) {
- float voltage = battery.voltage(instance) * 1e3f;
- for (uint8_t i = 0; i < MAVLINK_MSG_BATTERY_STATUS_FIELD_VOLTAGES_LEN; i++) {
- if (voltage < 0.001f) {
- // too small to send to the GCS, set it to the no cell value
- fake_cells.cells[i] = UINT16_MAX;
- } else {
- fake_cells.cells[i] = MIN(voltage, 65534.0f); // Can't send more then UINT16_MAX - 1 in a cell
- voltage -= 65534.0f;
- }
- }
- }
- float current, consumed_mah, consumed_wh;
- if (battery.current_amps(current, instance)) {
- current *= 100;
- } else {
- current = -1;
- }
- if (!battery.consumed_mah(consumed_mah, instance)) {
- consumed_mah = -1;
- }
- if (battery.consumed_wh(consumed_wh, instance)) {
- consumed_wh *= 36;
- } else {
- consumed_wh = -1;
- }
- mavlink_msg_battery_status_send(chan,
- instance, // id
- MAV_BATTERY_FUNCTION_UNKNOWN, // function
- MAV_BATTERY_TYPE_UNKNOWN, // type
- got_temperature ? ((int16_t) (temp * 100)) : INT16_MAX, // temperature. INT16_MAX if unknown
- battery.has_cell_voltages(instance) ? battery.get_cell_voltages(instance).cells : fake_cells.cells, // cell voltages
- current, // current in centiampere
- consumed_mah, // total consumed current in milliampere.hour
- consumed_wh, // consumed energy in hJ (hecto-Joules)
- get_battery_remaining_percentage(instance),
- 0, // time remaining, seconds (not provided)
- MAV_BATTERY_CHARGE_STATE_UNDEFINED);
- }
- // returns true if all battery instances were reported
- bool GCS_MAVLINK::send_battery_status() const
- {
- const AP_BattMonitor &battery = AP::battery();
- for(uint8_t i = 0; i < battery.num_instances(); i++) {
- if (battery.get_type(i) != AP_BattMonitor_Params::BattMonitor_Type::BattMonitor_TYPE_NONE) {
- CHECK_PAYLOAD_SIZE(BATTERY_STATUS);
- send_battery_status(i);
- }
- }
- return true;
- }
- void GCS_MAVLINK::send_distance_sensor(const AP_RangeFinder_Backend *sensor, const uint8_t instance) const
- {
- if (!sensor->has_data()) {
- return;
- }
- mavlink_msg_distance_sensor_send(
- chan,
- AP_HAL::millis(), // time since system boot TODO: take time of measurement
- sensor->min_distance_cm(), // minimum distance the sensor can measure in centimeters
- sensor->max_distance_cm(), // maximum distance the sensor can measure in centimeters
- sensor->distance_cm(), // current distance reading
- sensor->get_mav_distance_sensor_type(), // type from MAV_DISTANCE_SENSOR enum
- instance, // onboard ID of the sensor == instance
- sensor->orientation(), // direction the sensor faces from MAV_SENSOR_ORIENTATION enum
- 0, // Measurement covariance in centimeters, 0 for unknown / invalid readings
- 0, // horizontal FOV
- 0, // vertical FOV
- (const float *)nullptr); // quaternion of sensor orientation for MAV_SENSOR_ROTATION_CUSTOM
- }
- // send any and all distance_sensor messages. This starts by sending
- // any distance sensors not used by a Proximity sensor, then sends the
- // proximity sensor ones.
- void GCS_MAVLINK::send_distance_sensor() const
- {
- RangeFinder *rangefinder = RangeFinder::get_singleton();
- if (rangefinder == nullptr) {
- return;
- }
- // if we have a proximity backend that utilizes rangefinders cull
- // sending them here, and allow the later proximity code to manage
- // them
- bool filter_possible_proximity_sensors = false;
- AP_Proximity *proximity = AP_Proximity::get_singleton();
- if (proximity != nullptr) {
- for (uint8_t i = 0; i < proximity->num_sensors(); i++) {
- if (proximity->get_type(i) == AP_Proximity::Proximity_Type_RangeFinder) {
- filter_possible_proximity_sensors = true;
- }
- }
- }
- for (uint8_t i = 0; i < RANGEFINDER_MAX_INSTANCES; i++) {
- if (!HAVE_PAYLOAD_SPACE(chan, DISTANCE_SENSOR)) {
- return;
- }
- AP_RangeFinder_Backend *sensor = rangefinder->get_backend(i);
- if (sensor == nullptr) {
- continue;
- }
- enum Rotation orient = sensor->orientation();
- if (!filter_possible_proximity_sensors ||
- (orient > ROTATION_YAW_315 && orient != ROTATION_PITCH_90)) {
- send_distance_sensor(sensor, i);
- }
- }
- send_proximity();
- }
- void GCS_MAVLINK::send_rangefinder() const
- {
- RangeFinder *rangefinder = RangeFinder::get_singleton();
- if (rangefinder == nullptr) {
- return;
- }
- AP_RangeFinder_Backend *s = rangefinder->find_instance(ROTATION_PITCH_270);
- if (s == nullptr) {
- return;
- }
- mavlink_msg_rangefinder_send(
- chan,
- s->distance_cm() * 0.01f,
- s->voltage_mv() * 0.001f);
- }
- void GCS_MAVLINK::send_proximity() const
- {
- AP_Proximity *proximity = AP_Proximity::get_singleton();
- if (proximity == nullptr || proximity->get_status() == AP_Proximity::Proximity_NotConnected) {
- return; // this is wrong, but pretend we sent data and don't requeue
- }
- const uint16_t dist_min = (uint16_t)(proximity->distance_min() * 100.0f); // minimum distance the sensor can measure in centimeters
- const uint16_t dist_max = (uint16_t)(proximity->distance_max() * 100.0f); // maximum distance the sensor can measure in centimeters
- // send horizontal distances
- AP_Proximity::Proximity_Distance_Array dist_array;
- if (proximity->get_horizontal_distances(dist_array)) {
- for (uint8_t i = 0; i < PROXIMITY_MAX_DIRECTION; i++) {
- if (!HAVE_PAYLOAD_SPACE(chan, DISTANCE_SENSOR)) {
- return;
- }
- mavlink_msg_distance_sensor_send(
- chan,
- AP_HAL::millis(), // time since system boot
- dist_min, // minimum distance the sensor can measure in centimeters
- dist_max, // maximum distance the sensor can measure in centimeters
- (uint16_t)(dist_array.distance[i] * 100.0f), // current distance reading
- MAV_DISTANCE_SENSOR_LASER, // type from MAV_DISTANCE_SENSOR enum
- PROXIMITY_SENSOR_ID_START + i, // onboard ID of the sensor
- dist_array.orientation[i], // direction the sensor faces from MAV_SENSOR_ORIENTATION enum
- 0, // Measurement covariance in centimeters, 0 for unknown / invalid readings
- 0, 0, nullptr);
- }
- }
- // send upward distance
- float dist_up;
- if (proximity->get_upward_distance(dist_up)) {
- if (!HAVE_PAYLOAD_SPACE(chan, DISTANCE_SENSOR)) {
- return;
- }
- mavlink_msg_distance_sensor_send(
- chan,
- AP_HAL::millis(), // time since system boot
- dist_min, // minimum distance the sensor can measure in centimeters
- dist_max, // maximum distance the sensor can measure in centimeters
- (uint16_t)(dist_up * 100.0f), // current distance reading
- MAV_DISTANCE_SENSOR_LASER, // type from MAV_DISTANCE_SENSOR enum
- PROXIMITY_SENSOR_ID_START + PROXIMITY_MAX_DIRECTION + 1, // onboard ID of the sensor
- MAV_SENSOR_ROTATION_PITCH_90, // direction upwards
- 0, // Measurement covariance in centimeters, 0 for unknown / invalid readings
- 0, 0, nullptr);
- }
- }
- // report AHRS2 state
- void GCS_MAVLINK::send_ahrs2()
- {
- #if AP_AHRS_NAVEKF_AVAILABLE
- const AP_AHRS &ahrs = AP::ahrs();
- Vector3f euler;
- struct Location loc {};
- if (ahrs.get_secondary_attitude(euler) ||
- ahrs.get_secondary_position(loc)) {
- mavlink_msg_ahrs2_send(chan,
- euler.x,
- euler.y,
- euler.z,
- loc.alt*1.0e-2f,
- loc.lat,
- loc.lng);
- }
- #endif
- }
- void GCS_MAVLINK::send_ahrs3()
- {
- #if AP_AHRS_NAVEKF_AVAILABLE
- const NavEKF2 &ekf2 = AP::ahrs_navekf().get_NavEKF2_const();
-
- if (ekf2.activeCores() > 0 &&
- HAVE_PAYLOAD_SPACE(chan, AHRS3)) {
- struct Location loc {};
- ekf2.getLLH(loc);
- Vector3f euler;
- ekf2.getEulerAngles(-1,euler);
- mavlink_msg_ahrs3_send(chan,
- euler.x,
- euler.y,
- euler.z,
- loc.alt*1.0e-2f,
- loc.lat,
- loc.lng,
- 0, 0, 0, 0);
- }
- #endif
- }
- MissionItemProtocol *GCS::get_prot_for_mission_type(const MAV_MISSION_TYPE mission_type) const
- {
- switch (mission_type) {
- case MAV_MISSION_TYPE_MISSION:
- return _missionitemprotocol_waypoints;
- case MAV_MISSION_TYPE_RALLY:
- return _missionitemprotocol_rally;
- default:
- return nullptr;
- }
- }
- // handle a request for the number of items we have stored for a mission type:
- void GCS_MAVLINK::handle_mission_request_list(const mavlink_message_t &msg)
- {
- // decode
- mavlink_mission_request_list_t packet;
- mavlink_msg_mission_request_list_decode(&msg, &packet);
- MissionItemProtocol *prot = gcs().get_prot_for_mission_type((MAV_MISSION_TYPE)packet.mission_type);
- if (prot == nullptr) {
- mavlink_msg_mission_ack_send(chan,
- msg.sysid,
- msg.compid,
- MAV_MISSION_UNSUPPORTED,
- packet.mission_type);
- return;
- }
- prot->handle_mission_request_list(*this, packet, msg);
- }
- /*
- handle a MISSION_REQUEST mavlink packet
- */
- void GCS_MAVLINK::handle_mission_request_int(const mavlink_message_t &msg)
- {
- // decode
- mavlink_mission_request_int_t packet;
- mavlink_msg_mission_request_int_decode(&msg, &packet);
- MissionItemProtocol *prot = gcs().get_prot_for_mission_type((MAV_MISSION_TYPE)packet.mission_type);
- if (prot == nullptr) {
- return;
- }
- prot->handle_mission_request_int(*this, packet, msg);
- }
- void GCS_MAVLINK::handle_mission_request(const mavlink_message_t &msg)
- {
- // decode
- mavlink_mission_request_t packet;
- mavlink_msg_mission_request_decode(&msg, &packet);
- MissionItemProtocol *prot = gcs().get_prot_for_mission_type((MAV_MISSION_TYPE)packet.mission_type);
- if (prot == nullptr) {
- return;
- }
- prot->handle_mission_request(*this, packet, msg);
- }
- /*
- handle a MISSION_SET_CURRENT mavlink packet
- */
- void GCS_MAVLINK::handle_mission_set_current(AP_Mission &mission, const mavlink_message_t &msg)
- {
- // decode
- mavlink_mission_set_current_t packet;
- mavlink_msg_mission_set_current_decode(&msg, &packet);
- // set current command
- if (mission.set_current_cmd(packet.seq)) {
- mavlink_msg_mission_current_send(chan, packet.seq);
- }
- }
- /*
- handle a MISSION_COUNT mavlink packet
- */
- void GCS_MAVLINK::handle_mission_count(const mavlink_message_t &msg)
- {
- // decode
- mavlink_mission_count_t packet;
- mavlink_msg_mission_count_decode(&msg, &packet);
- MissionItemProtocol *prot = gcs().get_prot_for_mission_type((MAV_MISSION_TYPE)packet.mission_type);
- if (prot == nullptr) {
- mavlink_msg_mission_ack_send(chan,
- msg.sysid,
- msg.compid,
- MAV_MISSION_UNSUPPORTED,
- packet.mission_type);
- return;
- }
- prot->handle_mission_count(*this, packet, msg);
- }
- /*
- handle a MISSION_CLEAR_ALL mavlink packet
- */
- void GCS_MAVLINK::handle_mission_clear_all(const mavlink_message_t &msg)
- {
- // decode
- mavlink_mission_clear_all_t packet;
- mavlink_msg_mission_clear_all_decode(&msg, &packet);
- const MAV_MISSION_TYPE mission_type = (MAV_MISSION_TYPE)packet.mission_type;
- MissionItemProtocol *prot = gcs().get_prot_for_mission_type(mission_type);
- if (prot == nullptr) {
- send_mission_ack(msg, mission_type, MAV_MISSION_UNSUPPORTED);
- return;
- }
- prot->handle_mission_clear_all(*this, msg);
- }
- bool GCS_MAVLINK::requesting_mission_items() const
- {
- for (uint8_t i=0; i<ARRAY_SIZE(supported_mission_types); i++) {
- MissionItemProtocol *prot = gcs().get_prot_for_mission_type(supported_mission_types[i]);
- if (prot && prot->receiving && prot->active_link_is(this)) {
- return true;
- }
- }
- return false;
- }
- void GCS_MAVLINK::handle_mission_write_partial_list(const mavlink_message_t &msg)
- {
- // decode
- mavlink_mission_write_partial_list_t packet;
- mavlink_msg_mission_write_partial_list_decode(&msg, &packet);
- MissionItemProtocol *use_prot = gcs().get_prot_for_mission_type((MAV_MISSION_TYPE)packet.mission_type);
- if (use_prot == nullptr) {
- send_mission_ack(msg, (MAV_MISSION_TYPE)packet.mission_type, MAV_MISSION_UNSUPPORTED);
- return;
- }
- use_prot->handle_mission_write_partial_list(*this, msg, packet);
- }
- /*
- pass mavlink messages to the AP_Mount singleton
- */
- void GCS_MAVLINK::handle_mount_message(const mavlink_message_t &msg)
- {
- AP_Mount *mount = AP::mount();
- if (mount == nullptr) {
- return;
- }
- mount->handle_message(chan, msg);
- }
- /*
- pass parameter value messages through to mount library
- */
- void GCS_MAVLINK::handle_param_value(const mavlink_message_t &msg)
- {
- AP_Mount *mount = AP::mount();
- if (mount == nullptr) {
- return;
- }
- mount->handle_param_value(msg);
- }
- void GCS_MAVLINK::send_text(MAV_SEVERITY severity, const char *fmt, ...) const
- {
- char text[MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN+1];
- va_list arg_list;
- va_start(arg_list, fmt);
- hal.util->vsnprintf(text, sizeof(text), fmt, arg_list);
- va_end(arg_list);
- gcs().send_statustext(severity, (1<<chan), text);
- }
- void GCS_MAVLINK::handle_radio_status(const mavlink_message_t &msg, bool log_radio)
- {
- mavlink_radio_t packet;
- mavlink_msg_radio_decode(&msg, &packet);
- // record if the GCS has been receiving radio messages from
- // the aircraft
- if (packet.remrssi != 0) {
- last_radio_status_remrssi_ms = AP_HAL::millis();
- }
- // use the state of the transmit buffer in the radio to
- // control the stream rate, giving us adaptive software
- // flow control
- if (packet.txbuf < 20 && stream_slowdown_ms < 2000) {
- // we are very low on space - slow down a lot
- stream_slowdown_ms += 60;
- } else if (packet.txbuf < 50 && stream_slowdown_ms < 2000) {
- // we are a bit low on space, slow down slightly
- stream_slowdown_ms += 20;
- } else if (packet.txbuf > 95 && stream_slowdown_ms > 200) {
- // the buffer has plenty of space, speed up a lot
- stream_slowdown_ms -= 40;
- } else if (packet.txbuf > 90 && stream_slowdown_ms != 0) {
- // the buffer has enough space, speed up a bit
- stream_slowdown_ms -= 20;
- }
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- if (stream_slowdown_ms > max_slowdown_ms) {
- max_slowdown_ms = stream_slowdown_ms;
- }
- #endif
- //log rssi, noise, etc if logging Performance monitoring data
- if (log_radio) {
- AP::logger().Write_Radio(packet);
- }
- }
- /*
- handle an incoming mission item
- return true if this is the last mission item, otherwise false
- */
- void GCS_MAVLINK::handle_mission_item(const mavlink_message_t &msg)
- {
- // TODO: rename packet to mission_item_int
- mavlink_mission_item_int_t packet;
- if (msg.msgid == MAVLINK_MSG_ID_MISSION_ITEM) {
- mavlink_mission_item_t mission_item;
- mavlink_msg_mission_item_decode(&msg, &mission_item);
- MAV_MISSION_RESULT ret = AP_Mission::convert_MISSION_ITEM_to_MISSION_ITEM_INT(mission_item, packet);
- if (ret != MAV_MISSION_ACCEPTED) {
- const MAV_MISSION_TYPE type = (MAV_MISSION_TYPE)packet.mission_type;
- send_mission_ack(msg, type, ret);
- return;
- }
- } else {
- mavlink_msg_mission_item_int_decode(&msg, &packet);
- }
- const uint8_t current = packet.current;
- const MAV_MISSION_TYPE type = (MAV_MISSION_TYPE)packet.mission_type;
- if (type == MAV_MISSION_TYPE_MISSION && (current == 2 || current == 3)) {
- struct AP_Mission::Mission_Command cmd = {};
- MAV_MISSION_RESULT result = AP_Mission::mavlink_int_to_mission_cmd(packet, cmd);
- if (result != MAV_MISSION_ACCEPTED) {
- //decode failed
- send_mission_ack(msg, MAV_MISSION_TYPE_MISSION, result);
- return;
- }
- // guided or change-alt
- if (current == 2) {
- // current = 2 is a flag to tell us this is a "guided mode"
- // waypoint and not for the mission
- result = (handle_guided_request(cmd) ? MAV_MISSION_ACCEPTED
- : MAV_MISSION_ERROR) ;
- } else if (current == 3) {
- //current = 3 is a flag to tell us this is a alt change only
- // add home alt if needed
- handle_change_alt_request(cmd);
- // verify we recevied the command
- result = MAV_MISSION_ACCEPTED;
- }
- send_mission_ack(msg, MAV_MISSION_TYPE_MISSION, result);
- return;
- }
- // not a guided-mode reqest
- MissionItemProtocol *prot = gcs().get_prot_for_mission_type(type);
- if (prot == nullptr) {
- send_mission_ack(msg, type, MAV_MISSION_UNSUPPORTED);
- return;
- }
- if (!prot->receiving) {
- send_mission_ack(msg, type, MAV_MISSION_ERROR);
- return;
- }
- prot->handle_mission_item(msg, packet);
- }
- ap_message GCS_MAVLINK::mavlink_id_to_ap_message_id(const uint32_t mavlink_id) const
- {
- // MSG_NEXT_MISSION_REQUEST doesn't correspond to a mavlink message directly.
- // It is used to request the next waypoint after receiving one.
- // MSG_NEXT_PARAM doesn't correspond to a mavlink message directly.
- // It is used to send the next parameter in a stream after sending one
- // MSG_NAMED_FLOAT messages can't really be "streamed"...
- static const struct {
- uint32_t mavlink_id;
- ap_message msg_id;
- } map[] {
- { MAVLINK_MSG_ID_HEARTBEAT, MSG_HEARTBEAT},
- { MAVLINK_MSG_ID_ATTITUDE, MSG_ATTITUDE},
- { MAVLINK_MSG_ID_GLOBAL_POSITION_INT, MSG_LOCATION},
- { MAVLINK_MSG_ID_HOME_POSITION, MSG_HOME},
- { MAVLINK_MSG_ID_GPS_GLOBAL_ORIGIN, MSG_ORIGIN},
- { MAVLINK_MSG_ID_SYS_STATUS, MSG_SYS_STATUS},
- { MAVLINK_MSG_ID_POWER_STATUS, MSG_POWER_STATUS},
- { MAVLINK_MSG_ID_MEMINFO, MSG_MEMINFO},
- { MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT, MSG_NAV_CONTROLLER_OUTPUT},
- { MAVLINK_MSG_ID_MISSION_CURRENT, MSG_CURRENT_WAYPOINT},
- { MAVLINK_MSG_ID_VFR_HUD, MSG_VFR_HUD},
- { MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, MSG_SERVO_OUTPUT_RAW},
- { MAVLINK_MSG_ID_RC_CHANNELS, MSG_RC_CHANNELS},
- { MAVLINK_MSG_ID_RC_CHANNELS_RAW, MSG_RC_CHANNELS_RAW},
- { MAVLINK_MSG_ID_RAW_IMU, MSG_RAW_IMU},
- { MAVLINK_MSG_ID_SCALED_IMU, MSG_SCALED_IMU},
- { MAVLINK_MSG_ID_SCALED_IMU2, MSG_SCALED_IMU2},
- { MAVLINK_MSG_ID_SCALED_IMU3, MSG_SCALED_IMU3},
- { MAVLINK_MSG_ID_SCALED_PRESSURE, MSG_SCALED_PRESSURE},
- { MAVLINK_MSG_ID_SCALED_PRESSURE2, MSG_SCALED_PRESSURE2},
- { MAVLINK_MSG_ID_SCALED_PRESSURE3, MSG_SCALED_PRESSURE3},
- { MAVLINK_MSG_ID_SENSOR_OFFSETS, MSG_SENSOR_OFFSETS},
- { MAVLINK_MSG_ID_GPS_RAW_INT, MSG_GPS_RAW},
- { MAVLINK_MSG_ID_GPS_RTK, MSG_GPS_RTK},
- { MAVLINK_MSG_ID_GPS2_RAW, MSG_GPS2_RAW},
- { MAVLINK_MSG_ID_GPS2_RTK, MSG_GPS2_RTK},
- { MAVLINK_MSG_ID_SYSTEM_TIME, MSG_SYSTEM_TIME},
- { MAVLINK_MSG_ID_RC_CHANNELS_SCALED, MSG_SERVO_OUT},
- { MAVLINK_MSG_ID_PARAM_VALUE, MSG_NEXT_PARAM},
- { MAVLINK_MSG_ID_FENCE_STATUS, MSG_FENCE_STATUS},
- { MAVLINK_MSG_ID_AHRS, MSG_AHRS},
- { MAVLINK_MSG_ID_SIMSTATE, MSG_SIMSTATE},
- { MAVLINK_MSG_ID_AHRS2, MSG_AHRS2},
- { MAVLINK_MSG_ID_AHRS3, MSG_AHRS3},
- { MAVLINK_MSG_ID_HWSTATUS, MSG_HWSTATUS},
- { MAVLINK_MSG_ID_WIND, MSG_WIND},
- { MAVLINK_MSG_ID_RANGEFINDER, MSG_RANGEFINDER},
- { MAVLINK_MSG_ID_DISTANCE_SENSOR, MSG_DISTANCE_SENSOR},
- // request also does report:
- { MAVLINK_MSG_ID_TERRAIN_REQUEST, MSG_TERRAIN},
- { MAVLINK_MSG_ID_BATTERY2, MSG_BATTERY2},
- { MAVLINK_MSG_ID_CAMERA_FEEDBACK, MSG_CAMERA_FEEDBACK},
- { MAVLINK_MSG_ID_MOUNT_STATUS, MSG_MOUNT_STATUS},
- { MAVLINK_MSG_ID_OPTICAL_FLOW, MSG_OPTICAL_FLOW},
- { MAVLINK_MSG_ID_GIMBAL_REPORT, MSG_GIMBAL_REPORT},
- { MAVLINK_MSG_ID_MAG_CAL_PROGRESS, MSG_MAG_CAL_PROGRESS},
- { MAVLINK_MSG_ID_MAG_CAL_REPORT, MSG_MAG_CAL_REPORT},
- { MAVLINK_MSG_ID_EKF_STATUS_REPORT, MSG_EKF_STATUS_REPORT},
- { MAVLINK_MSG_ID_LOCAL_POSITION_NED, MSG_LOCAL_POSITION},
- { MAVLINK_MSG_ID_PID_TUNING, MSG_PID_TUNING},
- { MAVLINK_MSG_ID_VIBRATION, MSG_VIBRATION},
- { MAVLINK_MSG_ID_RPM, MSG_RPM},
- { MAVLINK_MSG_ID_MISSION_ITEM_REACHED, MSG_MISSION_ITEM_REACHED},
- { MAVLINK_MSG_ID_POSITION_TARGET_GLOBAL_INT, MSG_POSITION_TARGET_GLOBAL_INT},
- { MAVLINK_MSG_ID_POSITION_TARGET_LOCAL_NED, MSG_POSITION_TARGET_LOCAL_NED},
- { MAVLINK_MSG_ID_ADSB_VEHICLE, MSG_ADSB_VEHICLE},
- { MAVLINK_MSG_ID_BATTERY_STATUS, MSG_BATTERY_STATUS},
- { MAVLINK_MSG_ID_AOA_SSA, MSG_AOA_SSA},
- { MAVLINK_MSG_ID_DEEPSTALL, MSG_LANDING},
- { MAVLINK_MSG_ID_EXTENDED_SYS_STATE, MSG_EXTENDED_SYS_STATE},
- { MAVLINK_MSG_ID_AUTOPILOT_VERSION, MSG_AUTOPILOT_VERSION},
- };
- for (uint8_t i=0; i<ARRAY_SIZE(map); i++) {
- if (map[i].mavlink_id == mavlink_id) {
- return map[i].msg_id;
- }
- }
- return MSG_LAST;
- }
- bool GCS_MAVLINK::set_mavlink_message_id_interval(const uint32_t mavlink_id,
- const uint16_t interval_ms)
- {
- const ap_message id = mavlink_id_to_ap_message_id(mavlink_id);
- if (id == MSG_LAST) {
- gcs().send_text(MAV_SEVERITY_INFO, "No ap_message for mavlink id (%u)", (unsigned int)mavlink_id);
- return false;
- }
- return set_ap_message_interval(id, interval_ms);
- }
- bool GCS_MAVLINK::should_send_message_in_delay_callback(const ap_message id) const
- {
- // No ID we return true for may take more than a few hundred
- // microseconds to return!
- if (id == MSG_HEARTBEAT || id == MSG_NEXT_PARAM) {
- return true;
- }
- if (in_hil_mode()) {
- // in HIL we need to keep sending servo values to ensure
- // the simulator doesn't pause, otherwise our sensor
- // calibration could stall
- if (id == MSG_SERVO_OUT ||
- id == MSG_SERVO_OUTPUT_RAW) {
- return true;
- }
- }
- return false;
- }
- uint16_t GCS_MAVLINK::get_reschedule_interval_ms(const deferred_message_bucket_t &deferred) const
- {
- uint32_t interval_ms = deferred.interval_ms;
- interval_ms += stream_slowdown_ms;
- // slow most messages down if we're transfering parameters or
- // waypoints:
- if (_queued_parameter) {
- // we are sending parameters, penalize streams:
- interval_ms *= 4;
- }
- if (requesting_mission_items()) {
- // we are sending requests for waypoints, penalize streams:
- interval_ms *= 4;
- }
- if (interval_ms > 60000) {
- return 60000;
- }
- return interval_ms;
- }
- // typical runtime on fmuv3: 5 microseconds for 3 buckets
- void GCS_MAVLINK::find_next_bucket_to_send()
- {
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- void *data = hal.scheduler->disable_interrupts_save();
- uint32_t start_us = AP_HAL::micros();
- #endif
- const uint16_t now16_ms{AP_HAL::millis16()};
- // all done sending this bucket... find another bucket...
- sending_bucket_id = no_bucket_to_send;
- uint16_t ms_before_send_next_bucket_to_send = UINT16_MAX;
- for (uint8_t i=0; i<ARRAY_SIZE(deferred_message_bucket); i++) {
- if (deferred_message_bucket[i].ap_message_ids.count() == 0) {
- // no entries
- continue;
- }
- const uint16_t interval = get_reschedule_interval_ms(deferred_message_bucket[i]);
- const uint16_t ms_since_last_sent = now16_ms - deferred_message_bucket[i].last_sent_ms;
- uint16_t ms_before_send_this_bucket;
- if (ms_since_last_sent > interval) {
- // should already have sent this bucket!
- ms_before_send_this_bucket = 0;
- } else {
- ms_before_send_this_bucket = interval - ms_since_last_sent;
- }
- if (ms_before_send_this_bucket < ms_before_send_next_bucket_to_send) {
- sending_bucket_id = i;
- ms_before_send_next_bucket_to_send = ms_before_send_this_bucket;
- }
- }
- if (sending_bucket_id != no_bucket_to_send) {
- bucket_message_ids_to_send = deferred_message_bucket[sending_bucket_id].ap_message_ids;
- } else {
- bucket_message_ids_to_send.clearall();
- }
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- uint32_t delta_us = AP_HAL::micros() - start_us;
- hal.scheduler->restore_interrupts(data);
- if (delta_us > try_send_message_stats.fnbts_maxtime) {
- try_send_message_stats.fnbts_maxtime = delta_us;
- }
- #endif
- }
- ap_message GCS_MAVLINK::next_deferred_bucket_message_to_send()
- {
- if (sending_bucket_id == no_bucket_to_send) {
- // could happen if all streamrates are zero?
- return no_message_to_send;
- }
- const uint16_t now16_ms = AP_HAL::millis16();
- const uint16_t ms_since_last_sent = now16_ms - deferred_message_bucket[sending_bucket_id].last_sent_ms;
- if (ms_since_last_sent < get_reschedule_interval_ms(deferred_message_bucket[sending_bucket_id])) {
- // not time to send this bucket
- return no_message_to_send;
- }
- const int16_t next = bucket_message_ids_to_send.first_set();
- if (next == -1) {
- // should not happen
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- AP_HAL::panic("next_deferred_bucket_message_to_send called on empty bucket");
- #endif
- find_next_bucket_to_send();
- return no_message_to_send;
- }
- return (ap_message)next;
- }
- // call try_send_message if appropriate. Incorporates debug code to
- // record how long it takes to send a message. try_send_message is
- // expected to be overridden, not this function.
- bool GCS_MAVLINK::do_try_send_message(const ap_message id)
- {
- const bool in_delay_callback = hal.scheduler->in_delay_callback();
- if (in_delay_callback && !should_send_message_in_delay_callback(id)) {
- return true;
- }
- if (telemetry_delayed()) {
- return false;
- }
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- void *data = hal.scheduler->disable_interrupts_save();
- uint32_t start_send_message_us = AP_HAL::micros();
- #endif
- if (!try_send_message(id)) {
- // didn't fit in buffer...
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- try_send_message_stats.no_space_for_message++;
- hal.scheduler->restore_interrupts(data);
- #endif
- return false;
- }
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- const uint32_t delta_us = AP_HAL::micros() - start_send_message_us;
- hal.scheduler->restore_interrupts(data);
- if (delta_us > try_send_message_stats.longest_time_us) {
- try_send_message_stats.longest_time_us = delta_us;
- try_send_message_stats.longest_id = id;
- }
- #endif
- return true;
- }
- int8_t GCS_MAVLINK::get_deferred_message_index(const ap_message id) const
- {
- for (uint8_t i=0; i<ARRAY_SIZE(deferred_message); i++) {
- if (deferred_message[i].id == id) {
- return i;
- }
- }
- return -1;
- }
- int8_t GCS_MAVLINK::deferred_message_to_send_index()
- {
- const uint16_t now16_ms = AP_HAL::millis16();
- if (next_deferred_message_to_send_cache == -1) {
- uint16_t ms_before_next_message_to_send = UINT16_MAX;
- for (uint8_t i=0; i<ARRAY_SIZE(deferred_message); i++) {
- const uint16_t interval_ms = deferred_message[i].interval_ms;
- if (interval_ms == 0) {
- continue;
- }
- const uint16_t ms_since_last_sent = now16_ms - deferred_message[i].last_sent_ms;
- uint16_t ms_before_send_this_message;
- if (ms_since_last_sent > interval_ms) {
- // should already have sent this one!
- ms_before_send_this_message = 0;
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- try_send_message_stats.behind++;
- #endif
- } else {
- ms_before_send_this_message = interval_ms - ms_since_last_sent;
- }
- if (ms_before_send_this_message < ms_before_next_message_to_send) {
- next_deferred_message_to_send_cache = i;
- ms_before_next_message_to_send = ms_before_send_this_message;
- }
- }
- }
- if (next_deferred_message_to_send_cache == -1) {
- // this really shouldn't happen; we force parameter rates, for example.
- return -1;
- }
- const uint16_t ms_since_last_sent = now16_ms - deferred_message[next_deferred_message_to_send_cache].last_sent_ms;
- if (ms_since_last_sent < deferred_message[next_deferred_message_to_send_cache].interval_ms) {
- return -1;
- }
- return next_deferred_message_to_send_cache;
- }
- extern mavlink_rov_state_monitoring_t rov_message;
- //extern mavlink_motor_speed_t mav_motor_speed;
- extern mavlink_motor_speed_t mav_motor_speed_back;
- mavlink_data64_t rov_message3;
- extern mavlink_set_slave_parameter_t get_stm32_param;
- extern mavlink_hv_reg_get_t hv_reg_get;
- extern uint8_t get_stm32_param_buf[7];
- int countper = 0;
- void GCS_MAVLINK::update_send()
- {
- // const AP_UAVCAN &uavcan = AP::uavcan();//6自由度电机计算出来的PWM
-
- mav_motor_speed_back.motorTest = 0;
-
- mav_motor_speed_back.Ltrack = 0;
- mav_motor_speed_back.Rtrack =0;
- mav_motor_speed_back.motor1 =(float)sub._telemetry[0].rpm/7;//uint32 rpm
- mav_motor_speed_back.motor2 =(float)sub._telemetry[1].rpm/7;
- mav_motor_speed_back.motor3 =(float)sub._telemetry[2].rpm/7;
- mav_motor_speed_back.motor4 =(float)sub._telemetry[3].rpm/7;
- mav_motor_speed_back.motor5 =(float)sub._telemetry[4].rpm/7;
- mav_motor_speed_back.motor6 =(float)sub._telemetry[5].rpm/7;
- mav_motor_speed_back.motor7 =0;
- mav_motor_speed_back.motor8 =0;
- rov_message.floodlight = sub.lights;
- //pressure_level 在各个模式中已经赋值
- rov_message.low_voltage = (float)sub._telemetry[0].voltage/10;
- rov_message.high_voltage = (float)sub._telemetry[1].voltage/10;//sub._telemetry[0].voltage;//电压
- rov_message.deep =fabsf(sub.barometer.get_altitude());//深度
- //rov_message.temp = 0;
- rov_message.motor_block_flag = 0;
- rov_message.motor_twine_flag[0] = 0;//(uint16_t)uavcan.thruster[0].error_count;//故障码?
- rov_message.motor_twine_flag[1] = 0;//(uint16_t)uavcan.thruster[1].error_count;
- rov_message.motor_twine_flag[2] = 0;//(uint16_t)uavcan.thruster[2].error_count;
- rov_message.motor_twine_flag[3] = 0;//(uint16_t)uavcan.thruster[3].error_count;
- rov_message.motor_twine_flag[4] = 0;//(uint16_t)uavcan.thruster[4].error_count;
- rov_message.motor_twine_flag[5] = 0;//(uint16_t)uavcan.thruster[5].error_count;
- rov_message.motor_twine_flag[6] = 0;
- rov_message.motor_twine_flag[7] = 0;
- rov_message.motor_power[0] = (int16_t)sub._telemetry[0].totalcurrent;//float current
- rov_message.motor_power[1] = (int16_t)sub._telemetry[1].totalcurrent;
- rov_message.motor_power[2] = (int16_t)sub._telemetry[2].totalcurrent;
- rov_message.motor_power[3] = (int16_t)sub._telemetry[3].totalcurrent;
- rov_message.motor_power[4] = (int16_t)sub._telemetry[4].totalcurrent;
- rov_message.motor_power[5] = (int16_t)sub._telemetry[5].totalcurrent;
-
- get_stm32_param.number = 0;
- get_stm32_param.flag = 0;
- get_stm32_param.XX1 = 0;
- get_stm32_param.XX2 =0;
- get_stm32_param.XX3 = 0;
- get_stm32_param.XX4 = 0;
- get_stm32_param.YY = 0;
-
- const NavEKF2 &ekf2 = AP::ahrs_navekf().get_NavEKF2_const();
- Matrix3f mat;
- ekf2.getRotationBodyToNED(mat);
- countper++;
- if (countper>30)
- {
- countper = 0;
-
- mavlink_msg_rotation_matrix_array_send(chan,
- mat.c.x,mat.c.z,mat.c.y,
- mat.b.x,mat.b.z,mat.b.y,
- mat.a.x,mat.a.z,mat.a.y);
-
- }
-
- /*const NavEKF2 &ekf2 = AP::ahrs_navekf().get_NavEKF2_const();
- Matrix3f mat;
- ekf2.getRotationBodyToNED(mat);
- countper++;
- if (countper>50)
- {
- countper = 0;
-
- mavlink_msg_rotation_matrix_array_send(chan,
- mat.c.x,mat.c.z,mat.c.y,
- mat.b.x,mat.b.z,mat.b.y,
- mat.a.x,mat.a.z,mat.a.y);
- mavlink_msg_rov_state_monitoring_send_struct(chan,&rov_message);
-
- mavlink_msg_set_slave_parameter_send_struct(chan,&get_stm32_param);
-
- //mavlink_msg_motor_speed_send_struct(chan,&mav_motor_speed_back);
- //mavlink_msg_hv_reg_get_send_struct(chan,&hv_reg_get);
- }*/
-
-
-
-
- if (!hal.scheduler->in_delay_callback()) {
- // AP_Logger will not send log data if we are armed.
- AP::logger().handle_log_send();
- }
- if (!deferred_messages_initialised) {
- initialise_message_intervals_from_streamrates();
- deferred_messages_initialised = true;
- }
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- uint32_t retry_deferred_body_start = AP_HAL::micros();
- #endif
- const uint32_t start = AP_HAL::millis();
- while (AP_HAL::millis() - start < 5) { // spend a max of 5ms sending messages. This should never trigger - out_of_time() should become true
- if (gcs().out_of_time()) {
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- try_send_message_stats.out_of_time++;
- #endif
- break;
- }
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- retry_deferred_body_start = AP_HAL::micros();
- #endif
- // check if any "specially handled" messages should be sent out
- {
- const int8_t next = deferred_message_to_send_index();
- if (next != -1) {
- if (!do_try_send_message(deferred_message[next].id)) {
- break;
- }
- deferred_message[next].last_sent_ms += deferred_message[next].interval_ms;
- next_deferred_message_to_send_cache = -1; // deferred_message_to_send will recalculate
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- const uint32_t stop = AP_HAL::micros();
- const uint32_t delta = stop - retry_deferred_body_start;
- if (delta > try_send_message_stats.max_retry_deferred_body_us) {
- try_send_message_stats.max_retry_deferred_body_us = delta;
- try_send_message_stats.max_retry_deferred_body_type = 1;
- }
- #endif
- continue;
- }
- }
- // check for any messages that the code has explicitly sent
- const int16_t fs = pushed_ap_message_ids.first_set();
- if (fs != -1) {
- ap_message next = (ap_message)fs;
- if (!do_try_send_message(next)) {
- break;
- }
- pushed_ap_message_ids.clear(next);
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- const uint32_t stop = AP_HAL::micros();
- const uint32_t delta = stop - retry_deferred_body_start;
- if (delta > try_send_message_stats.max_retry_deferred_body_us) {
- try_send_message_stats.max_retry_deferred_body_us = delta;
- try_send_message_stats.max_retry_deferred_body_type = 2;
- }
- #endif
- continue;
- }
- ap_message next = next_deferred_bucket_message_to_send();
- if (next != no_message_to_send) {
- if (!do_try_send_message(next)) {
- break;
- }
- bucket_message_ids_to_send.clear(next);
- if (bucket_message_ids_to_send.count() == 0) {
- // we sent everything in the bucket. Reschedule it.
- deferred_message_bucket[sending_bucket_id].last_sent_ms +=
- get_reschedule_interval_ms(deferred_message_bucket[sending_bucket_id]);
- find_next_bucket_to_send();
- }
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- const uint32_t stop = AP_HAL::micros();
- const uint32_t delta = stop - retry_deferred_body_start;
- if (delta > try_send_message_stats.max_retry_deferred_body_us) {
- try_send_message_stats.max_retry_deferred_body_us = delta;
- try_send_message_stats.max_retry_deferred_body_type = 3;
- }
- #endif
- continue;
- }
- break;
- }
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- const uint32_t stop = AP_HAL::micros();
- const uint32_t delta = stop - retry_deferred_body_start;
- if (delta > try_send_message_stats.max_retry_deferred_body_us) {
- try_send_message_stats.max_retry_deferred_body_us = delta;
- try_send_message_stats.max_retry_deferred_body_type = 4;
- }
- #endif
- // update the number of packets transmitted base on seqno, making
- // the assumption that we don't send more than 256 messages
- // between the last pass through here
- mavlink_status_t *status = mavlink_get_channel_status(chan);
- if (status != nullptr) {
- send_packet_count += uint8_t(status->current_tx_seq - last_tx_seq);
- last_tx_seq = status->current_tx_seq;
- }
- }
- void GCS_MAVLINK::remove_message_from_bucket(int8_t bucket, ap_message id)
- {
- deferred_message_bucket[bucket].ap_message_ids.clear(id);
- if (bucket == sending_bucket_id) {
- bucket_message_ids_to_send.clear(id);
- }
- if (deferred_message_bucket[bucket].ap_message_ids.count() == 0) {
- // bucket empty. Free it:
- deferred_message_bucket[bucket].interval_ms = 0;
- deferred_message_bucket[bucket].last_sent_ms = 0;
- if (sending_bucket_id == bucket) {
- find_next_bucket_to_send();
- }
- }
- }
- bool GCS_MAVLINK::set_ap_message_interval(enum ap_message id, uint16_t interval_ms)
- {
- if (id == MSG_NEXT_PARAM) {
- // force parameters to *always* get streamed so a vehicle is
- // recoverable from bad configuration:
- if (interval_ms == 0) {
- interval_ms = 100;
- } else if (interval_ms > 1000) {
- interval_ms = 1000;
- }
- }
- // send messages out at most 80% of main loop rate
- if (interval_ms != 0 &&
- interval_ms*800 < AP::scheduler().get_loop_period_us()) {
- interval_ms = AP::scheduler().get_loop_period_us()/800.0f;
- }
- // check if it's a specially-handled message:
- const int8_t deferred_offset = get_deferred_message_index(id);
- if (deferred_offset != -1) {
- deferred_message[deferred_offset].interval_ms = interval_ms;
- deferred_message[deferred_offset].last_sent_ms = AP_HAL::millis16();
- return true;
- }
- // see which bucket has the closest interval:
- int8_t closest_bucket = -1;
- uint16_t closest_bucket_interval_delta = UINT16_MAX;
- int8_t in_bucket = -1;
- int8_t empty_bucket_id = -1;
- for (uint8_t i=0; i<ARRAY_SIZE(deferred_message_bucket); i++) {
- const deferred_message_bucket_t &bucket = deferred_message_bucket[i];
- if (bucket.interval_ms == 0) {
- // unused bucket
- if (empty_bucket_id == -1) {
- empty_bucket_id = i;
- }
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- if (bucket.ap_message_ids.count() != 0) {
- AP_HAL::panic("Bucket %u has zero interval but with ids set", i);
- }
- #endif
- continue;
- }
- if (bucket.ap_message_ids.get(id)) {
- in_bucket = i;
- }
- const uint16_t interval_delta = abs(bucket.interval_ms - interval_ms);
- if (interval_delta < closest_bucket_interval_delta) {
- closest_bucket = i;
- closest_bucket_interval_delta = interval_delta;
- }
- }
- if (in_bucket == -1 && interval_ms == 0) {
- // not in a bucket and told to remove from scheduling
- return true;
- }
- if (in_bucket != -1) {
- if (interval_ms == 0) {
- // remove it
- remove_message_from_bucket(in_bucket, id);
- return true;
- }
- if (closest_bucket_interval_delta == 0 &&
- in_bucket == closest_bucket) {
- // don't need to move it
- return true;
- }
- // remove from existing bucket
- remove_message_from_bucket(in_bucket, id);
- if (empty_bucket_id == -1 &&
- deferred_message_bucket[in_bucket].ap_message_ids.count() == 0) {
- empty_bucket_id = in_bucket;
- }
- }
- if (closest_bucket == -1 && empty_bucket_id == -1) {
- // gah?!
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- ::fprintf(stderr, "no buckets?!\n");
- abort();
- #endif
- return false;
- }
- if (closest_bucket_interval_delta != 0 &&
- empty_bucket_id != -1) {
- // allocate a bucket for this interval
- deferred_message_bucket[empty_bucket_id].interval_ms = interval_ms;
- deferred_message_bucket[empty_bucket_id].last_sent_ms = AP_HAL::millis16();
- closest_bucket = empty_bucket_id;
- closest_bucket_interval_delta = 0;
- }
- deferred_message_bucket[closest_bucket].ap_message_ids.set(id);
- if (sending_bucket_id == no_bucket_to_send) {
- sending_bucket_id = closest_bucket;
- bucket_message_ids_to_send = deferred_message_bucket[closest_bucket].ap_message_ids;
- }
- return true;
- }
- // queue a message to be sent (try_send_message does the *actual*
- // mavlink work!)
- void GCS_MAVLINK::send_message(enum ap_message id)
- {
- if (id == MSG_HEARTBEAT) {
- save_signing_timestamp(false);
- // update the mask of all streaming channels
- if (is_streaming()) {
- GCS_MAVLINK::chan_is_streaming |= (1U<<(chan-MAVLINK_COMM_0));
- } else {
- GCS_MAVLINK::chan_is_streaming &= ~(1U<<(chan-MAVLINK_COMM_0));
- }
- }
- pushed_ap_message_ids.set(id);
- }
- void GCS_MAVLINK::packetReceived(const mavlink_status_t &status,
- const mavlink_message_t &msg)
- {
- // we exclude radio packets because we historically used this to
- // make it possible to use the CLI over the radio
- if (msg.msgid != MAVLINK_MSG_ID_RADIO && msg.msgid != MAVLINK_MSG_ID_RADIO_STATUS) {
- const uint8_t mask = (1U<<(chan-MAVLINK_COMM_0));
- if (!(mask & mavlink_private)) {
- mavlink_active |= mask;
- }
- }
- if (!(status.flags & MAVLINK_STATUS_FLAG_IN_MAVLINK1) &&
- (status.flags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1) &&
- AP::serialmanager().get_mavlink_protocol(chan) == AP_SerialManager::SerialProtocol_MAVLink2) {
- // if we receive any MAVLink2 packets on a connection
- // currently sending MAVLink1 then switch to sending
- // MAVLink2
- mavlink_status_t *cstatus = mavlink_get_channel_status(chan);
- if (cstatus != nullptr) {
- cstatus->flags &= ~MAVLINK_STATUS_FLAG_OUT_MAVLINK1;
- }
- }
- if (!routing.check_and_forward(chan, msg)) {
- // the routing code has indicated we should not handle this packet locally
- return;
- }
- if (!accept_packet(status, msg)) {
- // e.g. enforce-sysid says we shouldn't look at this packet
- return;
- }
- handleMessage(msg);
- }
- void
- GCS_MAVLINK::update_receive(uint32_t max_time_us)
- {
- // do absolutely nothing if we are locked
- if (locked()) {
- return;
- }
- // receive new packets
- mavlink_message_t msg;
- mavlink_status_t status;
- uint32_t tstart_us = AP_HAL::micros();
- uint32_t now_ms = AP_HAL::millis();
- hal.util->perf_begin(_perf_update);
- status.packet_rx_drop_count = 0;
- const uint16_t nbytes = _port->available();
- for (uint16_t i=0; i<nbytes; i++)
- {
- const uint8_t c = (uint8_t)_port->read();
- const uint32_t protocol_timeout = 4000;
-
- if (alternative.handler &&
- now_ms - alternative.last_mavlink_ms > protocol_timeout) {
- /*
- we have an alternative protocol handler installed and we
- haven't parsed a MAVLink packet for 4 seconds. Try
- parsing using alternative handler
- */
- if (alternative.handler(c, mavlink_comm_port[chan])) {
- alternative.last_alternate_ms = now_ms;
- gcs_alternative_active[chan] = true;
- }
-
- /*
- we may also try parsing as MAVLink if we haven't had a
- successful parse on the alternative protocol for 4s
- */
- if (now_ms - alternative.last_alternate_ms <= protocol_timeout) {
- continue;
- }
- }
- bool parsed_packet = false;
- // Try to get a new message
- if (mavlink_parse_char(chan, c, &msg, &status)) {
- hal.util->persistent_data.last_mavlink_msgid = msg.msgid;
- hal.util->perf_begin(_perf_packet);
- packetReceived(status, msg);
- hal.util->perf_end(_perf_packet);
- parsed_packet = true;
- gcs_alternative_active[chan] = false;
- alternative.last_mavlink_ms = now_ms;
- hal.util->persistent_data.last_mavlink_msgid = 0;
- }
- if (parsed_packet || i % 100 == 0) {
- // make sure we don't spend too much time parsing mavlink messages
- if (AP_HAL::micros() - tstart_us > max_time_us) {
- break;
- }
- }
- }
- const uint32_t tnow = AP_HAL::millis();
- // send a timesync message every 10 seconds; this is for data
- // collection purposes
- if (tnow - _timesync_request.last_sent_ms > _timesync_request.interval_ms && !is_private()) {
- if (HAVE_PAYLOAD_SPACE(chan, TIMESYNC)) {
- send_timesync();
- _timesync_request.last_sent_ms = tnow;
- }
- }
- // consider logging mavlink stats:
- if (is_active() || is_streaming()) {
- if (tnow - last_mavlink_stats_logged > 1000) {
- log_mavlink_stats();
- last_mavlink_stats_logged = tnow;
- }
- }
- #if GCS_DEBUG_SEND_MESSAGE_TIMINGS
- const uint16_t now16_ms{AP_HAL::millis16()};
- if (uint16_t(now16_ms - try_send_message_stats.statustext_last_sent_ms) > 10000U) {
- if (try_send_message_stats.longest_time_us) {
- gcs().send_text(MAV_SEVERITY_INFO,
- "GCS.chan(%u): ap_msg=%u took %uus to send",
- chan,
- try_send_message_stats.longest_id,
- try_send_message_stats.longest_time_us);
- try_send_message_stats.longest_time_us = 0;
- }
- if (try_send_message_stats.no_space_for_message &&
- (is_active() || is_streaming())) {
- gcs().send_text(MAV_SEVERITY_INFO,
- "GCS.chan(%u): out-of-space: %u",
- chan,
- try_send_message_stats.no_space_for_message);
- try_send_message_stats.no_space_for_message = 0;
- }
- if (try_send_message_stats.out_of_time) {
- gcs().send_text(MAV_SEVERITY_INFO,
- "GCS.chan(%u): out-of-time=%u",
- chan,
- try_send_message_stats.out_of_time);
- try_send_message_stats.out_of_time = 0;
- }
- if (max_slowdown_ms) {
- gcs().send_text(MAV_SEVERITY_INFO,
- "GCS.chan(%u): max slowdown=%u",
- chan,
- max_slowdown_ms);
- max_slowdown_ms = 0;
- }
- if (try_send_message_stats.behind) {
- gcs().send_text(MAV_SEVERITY_INFO,
- "GCS.chan(%u): behind=%u",
- chan,
- try_send_message_stats.behind);
- try_send_message_stats.behind = 0;
- }
- if (try_send_message_stats.fnbts_maxtime) {
- gcs().send_text(MAV_SEVERITY_INFO,
- "GCS.chan(%u): fnbts_maxtime=%uus",
- chan,
- try_send_message_stats.fnbts_maxtime);
- try_send_message_stats.fnbts_maxtime = 0;
- }
- if (try_send_message_stats.max_retry_deferred_body_us) {
- gcs().send_text(MAV_SEVERITY_INFO,
- "GCS.chan(%u): retry_body_maxtime=%uus (%u)",
- chan,
- try_send_message_stats.max_retry_deferred_body_us,
- try_send_message_stats.max_retry_deferred_body_type
- );
- try_send_message_stats.max_retry_deferred_body_us = 0;
- }
- for (uint8_t i=0; i<ARRAY_SIZE(deferred_message_bucket); i++) {
- gcs().send_text(MAV_SEVERITY_INFO,
- "B. intvl. (%u): %u %u %u %u %u",
- chan,
- deferred_message_bucket[0].interval_ms,
- deferred_message_bucket[1].interval_ms,
- deferred_message_bucket[2].interval_ms,
- deferred_message_bucket[3].interval_ms,
- deferred_message_bucket[4].interval_ms);
- }
- try_send_message_stats.statustext_last_sent_ms = now16_ms;
- }
- #endif
- hal.util->perf_end(_perf_update);
- }
- /*
- record stats about this link to logger
- */
- void GCS_MAVLINK::log_mavlink_stats()
- {
- mavlink_status_t *status = mavlink_get_channel_status(chan);
- if (status == nullptr) {
- return;
- }
- const struct log_MAV pkt = {
- LOG_PACKET_HEADER_INIT(LOG_MAV_MSG),
- time_us : AP_HAL::micros64(),
- chan : (uint8_t)chan,
- packet_tx_count : send_packet_count,
- packet_rx_success_count: status->packet_rx_success_count,
- packet_rx_drop_count : status->packet_rx_drop_count
- };
- AP::logger().WriteBlock(&pkt, sizeof(pkt));
- }
- /*
- send the SYSTEM_TIME message
- */
- void GCS_MAVLINK::send_system_time()
- {
- uint64_t time_unix = 0;
- AP::rtc().get_utc_usec(time_unix); // may fail, leaving time_unix at 0
- mavlink_msg_system_time_send(
- chan,
- time_unix,
- AP_HAL::millis());
- }
- /*
- send RC_CHANNELS messages
- */
- void GCS_MAVLINK::send_rc_channels() const
- {
- AP_RSSI *rssi = AP::rssi();
- uint8_t receiver_rssi = 0;
- if (rssi != nullptr) {
- receiver_rssi = rssi->read_receiver_rssi_uint8();
- }
- uint16_t values[18] = {};
- rc().get_radio_in(values, ARRAY_SIZE(values));
- mavlink_msg_rc_channels_send(
- chan,
- AP_HAL::millis(),
- RC_Channels::get_valid_channel_count(),
- values[0],
- values[1],
- values[2],
- values[3],
- values[4],
- values[5],
- values[6],
- values[7],
- values[8],
- values[9],
- values[10],
- values[11],
- values[12],
- values[13],
- values[14],
- values[15],
- values[16],
- values[17],
- receiver_rssi);
- }
- bool GCS_MAVLINK::sending_mavlink1() const
- {
- const mavlink_status_t *status = mavlink_get_channel_status(chan);
- if (status == nullptr) {
- // should not happen
- return true;
- }
- return ((status->flags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1) != 0);
- }
- void GCS_MAVLINK::send_rc_channels_raw() const
- {
- // for mavlink1 send RC_CHANNELS_RAW, for compatibility with OSD
- // implementations
- if (!sending_mavlink1()) {
- return;
- }
- AP_RSSI *rssi = AP::rssi();
- uint8_t receiver_rssi = 0;
- if (rssi != nullptr) {
- receiver_rssi = rssi->read_receiver_rssi_uint8();
- }
- uint16_t values[8] = {};
- rc().get_radio_in(values, ARRAY_SIZE(values));
- mavlink_msg_rc_channels_raw_send(
- chan,
- AP_HAL::millis(),
- 0,
- values[0],
- values[1],
- values[2],
- values[3],
- values[4],
- values[5],
- values[6],
- values[7],
- receiver_rssi);
- }
- void GCS_MAVLINK::send_raw_imu()
- {
- const AP_InertialSensor &ins = AP::ins();
- const Compass &compass = AP::compass();
- const Vector3f &accel = ins.get_accel(0);
- const Vector3f &gyro = ins.get_gyro(0);
- Vector3f mag;
- if (compass.get_count() >= 1) {
- mag = compass.get_field(0);
- } else {
- mag.zero();
- }
- mavlink_msg_raw_imu_send(
- chan,
- AP_HAL::micros(),
- accel.x * 1000.0f / GRAVITY_MSS,
- accel.y * 1000.0f / GRAVITY_MSS,
- accel.z * 1000.0f / GRAVITY_MSS,
- gyro.x * 1000.0f,
- gyro.y * 1000.0f,
- gyro.z * 1000.0f,
- mag.x,
- mag.y,
- mag.z);
- }
- void GCS_MAVLINK::send_scaled_imu(uint8_t instance, void (*send_fn)(mavlink_channel_t chan, uint32_t time_ms, int16_t xacc, int16_t yacc, int16_t zacc, int16_t xgyro, int16_t ygyro, int16_t zgyro, int16_t xmag, int16_t ymag, int16_t zmag))
- {
- const AP_InertialSensor &ins = AP::ins();
- const Compass &compass = AP::compass();
- bool have_data = false;
- Vector3f accel{};
- if (ins.get_accel_count() > instance) {
- accel = ins.get_accel(instance);
- have_data = true;
- }
- Vector3f gyro{};
- if (ins.get_accel_count() > instance) {
- gyro = ins.get_gyro(instance);
- have_data = true;
- }
- Vector3f mag{};
- if (compass.get_count() > instance) {
- mag = compass.get_field(instance);
- have_data = true;
- }
- if (!have_data) {
- return;
- }
- send_fn(
- chan,
- AP_HAL::millis(),
- accel.x * 1000.0f / GRAVITY_MSS,
- accel.y * 1000.0f / GRAVITY_MSS,
- accel.z * 1000.0f / GRAVITY_MSS,
- gyro.x * 1000.0f,
- gyro.y * 1000.0f,
- gyro.z * 1000.0f,
- mag.x,
- mag.y,
- mag.z);
- }
- // send data for barometer and airspeed sensors instances. In the
- // case that we run out of instances of one before the other we send
- // the relevant fields as 0.
- void GCS_MAVLINK::send_scaled_pressure_instance(uint8_t instance, void (*send_fn)(mavlink_channel_t chan, uint32_t time_boot_ms, float press_abs, float press_diff, int16_t temperature))
- {
- const AP_Baro &barometer = AP::baro();
- bool have_data = false;
- float press_abs = 0.0f;
- float temperature = 0.0f;
- if (instance < barometer.num_instances()) {
- press_abs = barometer.get_pressure(instance) * 0.01f;
- temperature = barometer.get_temperature(instance)*100;
- have_data = true;
- }
- float press_diff = 0; // pascal
- AP_Airspeed *airspeed = AP_Airspeed::get_singleton();
- if (airspeed != nullptr &&
- airspeed->enabled(instance)) {
- press_diff = airspeed->get_differential_pressure(instance) * 0.01f;
- have_data = true;
- }
- if (!have_data) {
- return;
- }
- send_fn(
- chan,
- AP_HAL::millis(),
- press_abs, // hectopascal
- press_diff, // hectopascal
- temperature); // 0.01 degrees C
- }
- void GCS_MAVLINK::send_scaled_pressure()
- {
- send_scaled_pressure_instance(0, mavlink_msg_scaled_pressure_send);
- }
- void GCS_MAVLINK::send_scaled_pressure2()
- {
- send_scaled_pressure_instance(1, mavlink_msg_scaled_pressure2_send);
- }
- void GCS_MAVLINK::send_scaled_pressure3()
- {
- send_scaled_pressure_instance(2, mavlink_msg_scaled_pressure3_send);
- }
- void GCS_MAVLINK::send_sensor_offsets()
- {
- const AP_InertialSensor &ins = AP::ins();
- const Compass &compass = AP::compass();
- // run this message at a much lower rate - otherwise it
- // pointlessly wastes quite a lot of bandwidth
- static uint8_t counter;
- if (counter++ < 10) {
- return;
- }
- counter = 0;
- const Vector3f &mag_offsets = compass.get_offsets(0);
- const Vector3f &accel_offsets = ins.get_accel_offsets(0);
- const Vector3f &gyro_offsets = ins.get_gyro_offsets(0);
- const AP_Baro &barometer = AP::baro();
- mavlink_msg_sensor_offsets_send(chan,
- mag_offsets.x,
- mag_offsets.y,
- mag_offsets.z,
- compass.get_declination(),
- barometer.get_pressure(),
- barometer.get_temperature()*100,
- gyro_offsets.x,
- gyro_offsets.y,
- gyro_offsets.z,
- accel_offsets.x,
- accel_offsets.y,
- accel_offsets.z);
- }
- void GCS_MAVLINK::send_ahrs()
- {
- const AP_AHRS &ahrs = AP::ahrs();
- const Vector3f &omega_I = ahrs.get_gyro_drift();
- mavlink_msg_ahrs_send(
- chan,
- omega_I.x,
- omega_I.y,
- omega_I.z,
- 0,
- 0,
- ahrs.get_error_rp(),
- ahrs.get_error_yaw());
- }
- /*
- send a statustext text string to specific MAVLink bitmask
- */
- void GCS::send_statustext(MAV_SEVERITY severity, uint8_t dest_bitmask, const char *text)
- {
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- if (strlen(text) > MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN) {
- AP_HAL::panic("Statustext (%s) too long", text);
- }
- #endif
- AP_Logger *logger = AP_Logger::get_singleton();
- if (logger != nullptr) {
- logger->Write_Message(text);
- }
- if (frsky != nullptr) {
- frsky->queue_message(severity, text);
- }
- AP_Notify *notify = AP_Notify::get_singleton();
- if (notify) {
- notify->send_text(text);
- }
- // filter destination ports to only allow active ports.
- statustext_t statustext{};
- statustext.bitmask = (GCS_MAVLINK::active_channel_mask() | GCS_MAVLINK::streaming_channel_mask() ) & dest_bitmask;
- if (!statustext.bitmask) {
- // nowhere to send
- return;
- }
- statustext.msg.severity = severity;
- strncpy(statustext.msg.text, text, sizeof(statustext.msg.text));
- WITH_SEMAPHORE(_statustext_sem);
-
- // The force push will ensure comm links do not block other comm links forever if they fail.
- // If we push to a full buffer then we overwrite the oldest entry, effectively removing the
- // block but not until the buffer fills up.
- _statustext_queue.push_force(statustext);
- // try and send immediately if possible
- service_statustext();
- }
- /*
- send a statustext message to specific MAVLink connections in a bitmask
- */
- void GCS::service_statustext(void)
- {
- // create bitmask of what mavlink ports we should send this text to.
- // note, if sending to all ports, we only need to store the bitmask for each and the string only once.
- // once we send over a link, clear the port but other busy ports bit may stay allowing for faster links
- // to clear the bit and send quickly but slower links to still store the string. Regardless of mixed
- // bitrates of ports, a maximum of _status_capacity strings can be buffered. Downside
- // is if you have a super slow link mixed with a faster port, if there are _status_capacity
- // strings in the slow queue then the next item can not be queued for the faster link
- if (_statustext_queue.empty()) {
- // nothing to do
- return;
- }
- for (uint8_t idx=0; idx<_status_capacity; ) {
- statustext_t *statustext = _statustext_queue[idx];
- if (statustext == nullptr) {
- break;
- }
- // try and send to all active mavlink ports listed in the statustext.bitmask
- for (uint8_t i=0; i<MAVLINK_COMM_NUM_BUFFERS; i++) {
- uint8_t chan_bit = (1U<<i);
- // logical AND (&) to mask them together
- if (statustext->bitmask & chan_bit) {
- // something is queued on a port and that's the port index we're looped at
- mavlink_channel_t chan_index = (mavlink_channel_t)(MAVLINK_COMM_0+i);
- if (HAVE_PAYLOAD_SPACE(chan_index, STATUSTEXT)) {
- // we have space so send then clear that channel bit on the mask
- mavlink_msg_statustext_send(chan_index, statustext->msg.severity, statustext->msg.text);
- statustext->bitmask &= ~chan_bit;
- }
- }
- }
- if (statustext->bitmask == 0) {
- _statustext_queue.remove(idx);
- } else {
- // move to next index
- idx++;
- }
- }
- }
- void GCS::send_message(enum ap_message id)
- {
- for (uint8_t i=0; i<num_gcs(); i++) {
- chan(i)->send_message(id);
- }
- }
- void GCS::update_send()
- {
- if (!initialised_missionitemprotocol_objects) {
- initialised_missionitemprotocol_objects = true;
- // once-only initialisation of MissionItemProtocol objects:
- AP_Mission *mission = AP::mission();
- if (mission != nullptr) {
- _missionitemprotocol_waypoints = new MissionItemProtocol_Waypoints(*mission);
- }
- AP_Rally *rally = AP::rally();
- if (rally != nullptr) {
- _missionitemprotocol_rally = new MissionItemProtocol_Rally(*rally);
- }
- }
- if (_missionitemprotocol_waypoints != nullptr) {
- _missionitemprotocol_waypoints->update();
- }
- if (_missionitemprotocol_rally != nullptr) {
- _missionitemprotocol_rally->update();
- }
- for (uint8_t i=0; i<num_gcs(); i++) {
- chan(i)->update_send();
- }
- WITH_SEMAPHORE(_statustext_sem);
- service_statustext();
- }
- void GCS::update_receive(void)
- {
- for (uint8_t i=0; i<num_gcs(); i++) {
- chan(i)->update_receive();
- }
- // also update UART pass-thru, if enabled
- update_passthru();
- }
- void GCS::send_mission_item_reached_message(uint16_t mission_index)
- {
- for (uint8_t i=0; i<num_gcs(); i++) {
- chan(i)->mission_item_reached_index = mission_index;
- chan(i)->send_message(MSG_MISSION_ITEM_REACHED);
- }
- }
- void GCS::setup_console()
- {
- AP_HAL::UARTDriver *uart = AP::serialmanager().find_serial(AP_SerialManager::SerialProtocol_MAVLink, 0);
- if (uart == nullptr) {
- // this is probably not going to end well.
- return;
- }
- if (ARRAY_SIZE(chan_parameters) == 0) {
- return;
- }
- create_gcs_mavlink_backend(chan_parameters[0], *uart);
- }
- GCS_MAVLINK_Parameters::GCS_MAVLINK_Parameters()
- {
- AP_Param::setup_object_defaults(this, var_info);
- }
- void GCS::create_gcs_mavlink_backend(GCS_MAVLINK_Parameters ¶ms, AP_HAL::UARTDriver &uart)
- {
- if (_num_gcs >= ARRAY_SIZE(chan_parameters)) {
- return;
- }
- _chan[_num_gcs] = new_gcs_mavlink_backend(params, uart);
- if (_chan[_num_gcs] == nullptr) {
- return;
- }
- if (!_chan[_num_gcs]->init(_num_gcs)) {
- delete _chan[_num_gcs];
- _chan[_num_gcs] = nullptr;
- return;
- }
- _num_gcs++;
- }
- void GCS::setup_uarts()
- {
- for (uint8_t i = 1; i < MAVLINK_COMM_NUM_BUFFERS; i++) {
- if (i >= ARRAY_SIZE(chan_parameters)) {
- // should not happen
- break;
- }
- AP_HAL::UARTDriver *uart = AP::serialmanager().find_serial(AP_SerialManager::SerialProtocol_MAVLink, i);
- if (uart == nullptr) {
- // no more mavlink uarts
- break;
- }
- create_gcs_mavlink_backend(chan_parameters[i], *uart);
- }
- if (frsky == nullptr) {
- frsky = new AP_Frsky_Telem();
- if (frsky == nullptr || !frsky->init()) {
- delete frsky;
- frsky = nullptr;
- }
- }
- #if !HAL_MINIMIZE_FEATURES
- devo_telemetry.init();
- #endif
- }
- // report battery2 state
- void GCS_MAVLINK::send_battery2()
- {
- const AP_BattMonitor &battery = AP::battery();
- if (battery.num_instances() > 1) {
- float current;
- if (battery.current_amps(current, 1)) {
- current *= 100; // 10*mA
- } else {
- current = -1;
- }
- mavlink_msg_battery2_send(chan, battery.voltage(1)*1000, current);
- }
- }
- /*
- handle a SET_MODE MAVLink message
- */
- void GCS_MAVLINK::handle_set_mode(const mavlink_message_t &msg)
- {
- mavlink_set_mode_t packet;
- mavlink_msg_set_mode_decode(&msg, &packet);
- const MAV_MODE _base_mode = (MAV_MODE)packet.base_mode;
- const uint32_t _custom_mode = packet.custom_mode;
- const MAV_RESULT result = _set_mode_common(_base_mode, _custom_mode);
- // send ACK or NAK. Note that this is extraodinarily improper -
- // we are sending a command-ack for a message which is not a
- // command. The command we are acking (ID=11) doesn't actually
- // exist, but if it did we'd probably be acking something
- // completely unrelated to setting modes.
- if (HAVE_PAYLOAD_SPACE(chan, MAVLINK_MSG_ID_COMMAND_ACK)) {
- mavlink_msg_command_ack_send(chan, MAVLINK_MSG_ID_SET_MODE, result);
- }
- }
- /*
- code common to both SET_MODE mavlink message and command long set_mode msg
- */
- MAV_RESULT GCS_MAVLINK::_set_mode_common(const MAV_MODE _base_mode, const uint32_t _custom_mode)
- {
- MAV_RESULT result = MAV_RESULT_UNSUPPORTED;
- // only accept custom modes because there is no easy mapping from Mavlink flight modes to AC flight modes
- if (_base_mode & MAV_MODE_FLAG_CUSTOM_MODE_ENABLED) {
- if (set_mode(_custom_mode)) {
- result = MAV_RESULT_ACCEPTED;
- }
- } else if (_base_mode == (MAV_MODE)MAV_MODE_FLAG_DECODE_POSITION_SAFETY) {
- // set the safety switch position. Must be in a command by itself
- if (_custom_mode == 0) {
- // turn safety off (pwm outputs flow to the motors)
- hal.rcout->force_safety_off();
- result = MAV_RESULT_ACCEPTED;
- } else if (_custom_mode == 1) {
- // turn safety on (no pwm outputs to the motors)
- if (hal.rcout->force_safety_on()) {
- result = MAV_RESULT_ACCEPTED;
- }
- }
- }
- return result;
- }
- /*
- send OPTICAL_FLOW message
- */
- void GCS_MAVLINK::send_opticalflow()
- {
- #if AP_AHRS_NAVEKF_AVAILABLE
- const OpticalFlow *optflow = AP::opticalflow();
- // exit immediately if no optical flow sensor or not healthy
- if (optflow == nullptr ||
- !optflow->healthy()) {
- return;
- }
- // get rates from sensor
- const Vector2f &flowRate = optflow->flowRate();
- const Vector2f &bodyRate = optflow->bodyRate();
- const AP_AHRS &ahrs = AP::ahrs();
- float hagl = 0;
- if (ahrs.have_inertial_nav()) {
- if (!ahrs.get_hagl(hagl)) {
- return;
- }
- }
- // populate and send message
- mavlink_msg_optical_flow_send(
- chan,
- AP_HAL::millis(),
- 0, // sensor id is zero
- flowRate.x,
- flowRate.y,
- flowRate.x - bodyRate.x,
- flowRate.y - bodyRate.y,
- optflow->quality(),
- hagl, // ground distance (in meters) set to zero
- flowRate.x,
- flowRate.y);
- #endif
- }
- /*
- send AUTOPILOT_VERSION packet
- */
- void GCS_MAVLINK::send_autopilot_version() const
- {
- uint32_t flight_sw_version;
- uint32_t middleware_sw_version = 0;
- uint32_t board_version = 0;
- char flight_custom_version[MAVLINK_MSG_AUTOPILOT_VERSION_FIELD_FLIGHT_CUSTOM_VERSION_LEN]{};
- char middleware_custom_version[MAVLINK_MSG_AUTOPILOT_VERSION_FIELD_MIDDLEWARE_CUSTOM_VERSION_LEN]{};
- char os_custom_version[MAVLINK_MSG_AUTOPILOT_VERSION_FIELD_OS_CUSTOM_VERSION_LEN]{};
- uint16_t vendor_id = 0;
- uint16_t product_id = 0;
- uint64_t uid = 0;
- uint8_t uid2[MAVLINK_MSG_AUTOPILOT_VERSION_FIELD_UID2_LEN] = {0};
- const AP_FWVersion &version = AP::fwversion();
- flight_sw_version = version.major << (8 * 3) | \
- version.minor << (8 * 2) | \
- version.patch << (8 * 1) | \
- (uint32_t)(version.fw_type) << (8 * 0);
- if (version.fw_hash_str) {
- strncpy(flight_custom_version, version.fw_hash_str, sizeof(flight_custom_version) - 1);
- flight_custom_version[sizeof(flight_custom_version) - 1] = '\0';
- }
- if (version.middleware_hash_str) {
- strncpy(middleware_custom_version, version.middleware_hash_str, sizeof(middleware_custom_version) - 1);
- middleware_custom_version[sizeof(middleware_custom_version) - 1] = '\0';
- }
- if (version.os_hash_str) {
- strncpy(os_custom_version, version.os_hash_str, sizeof(os_custom_version) - 1);
- os_custom_version[sizeof(os_custom_version) - 1] = '\0';
- }
- mavlink_msg_autopilot_version_send(
- chan,
- capabilities(),
- flight_sw_version,
- middleware_sw_version,
- version.os_sw_version,
- board_version,
- (uint8_t *)flight_custom_version,
- (uint8_t *)middleware_custom_version,
- (uint8_t *)os_custom_version,
- vendor_id,
- product_id,
- uid,
- uid2
- );
- }
- /*
- send LOCAL_POSITION_NED message
- */
- void GCS_MAVLINK::send_local_position() const
- {
- const AP_AHRS &ahrs = AP::ahrs();
- Vector3f local_position, velocity;
- if (!ahrs.get_relative_position_NED_home(local_position) ||
- !ahrs.get_velocity_NED(velocity)) {
- // we don't know the position and velocity
- return;
- }
- mavlink_msg_local_position_ned_send(
- chan,
- AP_HAL::millis(),
- local_position.x,
- local_position.y,
- local_position.z,
- velocity.x,
- velocity.y,
- velocity.z);
- }
- /*
- send VIBRATION message
- */
- void GCS_MAVLINK::send_vibration() const
- {
- const AP_InertialSensor &ins = AP::ins();
- Vector3f vibration = ins.get_vibration_levels();
- mavlink_msg_vibration_send(
- chan,
- AP_HAL::micros64(),
- vibration.x,
- vibration.y,
- vibration.z,
- ins.get_accel_clip_count(0),
- ins.get_accel_clip_count(1),
- ins.get_accel_clip_count(2));
- }
- void GCS_MAVLINK::send_named_float(const char *name, float value) const
- {
- char float_name[MAVLINK_MSG_NAMED_VALUE_FLOAT_FIELD_NAME_LEN+1] {};
- strncpy(float_name, name, MAVLINK_MSG_NAMED_VALUE_FLOAT_FIELD_NAME_LEN);
- mavlink_msg_named_value_float_send(chan, AP_HAL::millis(), float_name, value);
- }
- void GCS_MAVLINK::send_home_position() const
- {
- if (!AP::ahrs().home_is_set()) {
- return;
- }
- const Location &home = AP::ahrs().get_home();
- const float q[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- mavlink_msg_home_position_send(
- chan,
- home.lat,
- home.lng,
- home.alt * 10,
- 0.0f, 0.0f, 0.0f,
- q,
- 0.0f, 0.0f, 0.0f,
- AP_HAL::micros64());
- }
- void GCS_MAVLINK::send_gps_global_origin() const
- {
- Location ekf_origin;
- if (!AP::ahrs().get_origin(ekf_origin)) {
- return;
- }
- mavlink_msg_gps_global_origin_send(
- chan,
- ekf_origin.lat,
- ekf_origin.lng,
- ekf_origin.alt * 10,
- AP_HAL::micros64());
- }
- /*
- Send MAVLink heartbeat
- */
- void GCS_MAVLINK::send_heartbeat() const
- {
- mavlink_msg_heartbeat_send(
- chan,
- gcs().frame_type(),
- MAV_AUTOPILOT_ARDUPILOTMEGA,
- base_mode(),
- gcs().custom_mode(),
- system_status());
- }
- MAV_RESULT GCS_MAVLINK::handle_command_set_message_interval(const mavlink_command_long_t &packet)
- {
- const uint32_t msg_id = (uint32_t)packet.param1;
- const int32_t interval_us = (int32_t)packet.param2;
- uint16_t interval_ms;
- if (interval_us == 0) {
- // zero is "reset to default rate"
- if (!get_default_interval_for_mavlink_message_id(msg_id, interval_ms)) {
- return MAV_RESULT_FAILED;
- }
- } else if (interval_us == -1) {
- // minus-one is "stop sending"
- interval_ms = 0;
- } else if (interval_us < 1000) {
- // don't squash sub-ms times to zero
- interval_ms = 1;
- } else if (interval_us > 60000000) {
- interval_ms = 60000;
- } else {
- interval_ms = interval_us / 1000;
- }
- if (set_mavlink_message_id_interval(msg_id, interval_ms)) {
- return MAV_RESULT_ACCEPTED;
- }
- return MAV_RESULT_FAILED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_request_message(const mavlink_command_long_t &packet)
- {
- const uint32_t mavlink_id = (uint32_t)packet.param1;
- const ap_message id = mavlink_id_to_ap_message_id(mavlink_id);
- if (id == MSG_LAST) {
- return MAV_RESULT_FAILED;
- }
- send_message(id);
- return MAV_RESULT_ACCEPTED;
- }
- bool GCS_MAVLINK::get_ap_message_interval(ap_message id, uint16_t &interval_ms) const
- {
- // check if it's a specially-handled message:
- const int8_t deferred_offset = get_deferred_message_index(id);
- if (deferred_offset != -1) {
- interval_ms = deferred_message[deferred_offset].interval_ms;
- return true;
- }
- // check the deferred message buckets:
- for (uint8_t i=0; i<ARRAY_SIZE(deferred_message_bucket); i++) {
- const deferred_message_bucket_t &bucket = deferred_message_bucket[i];
- if (bucket.ap_message_ids.get(id)) {
- interval_ms = bucket.interval_ms;
- return true;
- }
- }
- return false;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_get_message_interval(const mavlink_command_long_t &packet)
- {
- if (comm_get_txspace(chan) < PAYLOAD_SIZE(chan, MESSAGE_INTERVAL) + PAYLOAD_SIZE(chan, COMMAND_ACK)) {
- return MAV_RESULT_TEMPORARILY_REJECTED;
- }
- const uint32_t mavlink_id = (uint32_t)packet.param1;
- if (mavlink_id >= 2 << 15) {
- // response packet limits range this works against!
- mavlink_msg_message_interval_send(chan, mavlink_id, 0); // not available
- return MAV_RESULT_FAILED;
- }
- const ap_message id = mavlink_id_to_ap_message_id(mavlink_id);
- if (id == MSG_LAST) {
- mavlink_msg_message_interval_send(chan, mavlink_id, 0); // not available
- return MAV_RESULT_FAILED;
- }
- uint16_t interval_ms = 0;
- if (!get_ap_message_interval(id, interval_ms)) {
- // not streaming this message at the moment...
- mavlink_msg_message_interval_send(chan, mavlink_id, -1); // disabled
- return MAV_RESULT_ACCEPTED;
- }
- if (interval_ms == 0) {
- mavlink_msg_message_interval_send(chan, mavlink_id, -1); // disabled
- return MAV_RESULT_ACCEPTED;
- }
- mavlink_msg_message_interval_send(chan, mavlink_id, interval_ms * 1000);
- return MAV_RESULT_ACCEPTED;
- }
- // are we still delaying telemetry to try to avoid Xbee bricking?
- bool GCS_MAVLINK::telemetry_delayed() const
- {
- uint32_t tnow = AP_HAL::millis() >> 10;
- if (tnow > telem_delay()) {
- return false;
- }
- if (chan == MAVLINK_COMM_0 && hal.gpio->usb_connected()) {
- // this is USB telemetry, so won't be an Xbee
- return false;
- }
- // we're either on the 2nd UART, or no USB cable is connected
- // we need to delay telemetry by the TELEM_DELAY time
- return true;
- }
- /*
- send SERVO_OUTPUT_RAW
- */
- void GCS_MAVLINK::send_servo_output_raw()
- {
- uint16_t values[16] {};
- if (in_hil_mode()) {
- for (uint8_t i=0; i<16; i++) {
- values[i] = SRV_Channels::srv_channel(i)->get_output_pwm();
- }
- } else {
- hal.rcout->read(values, 16);
- }
- for (uint8_t i=0; i<16; i++) {
- if (values[i] == 65535) {
- values[i] = 0;
- }
- }
- mavlink_msg_servo_output_raw_send(
- chan,
- AP_HAL::micros(),
- 0, // port
- values[0], values[1], values[2], values[3],
- values[4], values[5], values[6], values[7],
- values[8], values[9], values[10], values[11],
- values[12], values[13], values[14], values[15]);
- }
- void GCS_MAVLINK::send_accelcal_vehicle_position(uint32_t position)
- {
- if (HAVE_PAYLOAD_SPACE(chan, COMMAND_LONG)) {
- mavlink_msg_command_long_send(
- chan,
- 0,
- 0,
- MAV_CMD_ACCELCAL_VEHICLE_POS,
- 0,
- (float) position,
- 0, 0, 0, 0, 0, 0);
- }
- }
- float GCS_MAVLINK::vfr_hud_airspeed() const
- {
- AP_Airspeed *airspeed = AP_Airspeed::get_singleton();
- if (airspeed != nullptr && airspeed->healthy()) {
- return airspeed->get_airspeed();
- }
- // because most vehicles don't have airspeed sensors, we return a
- // different sort of speed estimate in the relevant field for
- // comparison's sake.
- return AP::gps().ground_speed();
- }
- float GCS_MAVLINK::vfr_hud_climbrate() const
- {
- Vector3f velned;
- if (!AP::ahrs().get_velocity_NED(velned)) {
- velned.zero();
- }
- return -velned.z;
- }
- float GCS_MAVLINK::vfr_hud_alt() const
- {
- return global_position_current_loc.alt * 0.01f; // cm -> m
- }
- void GCS_MAVLINK::send_vfr_hud()
- {
- AP_AHRS &ahrs = AP::ahrs();
- // return values ignored; we send stale data
- ahrs.get_position(global_position_current_loc);
- mavlink_msg_vfr_hud_send(
- chan,
- vfr_hud_airspeed(),
- ahrs.groundspeed(),
- (ahrs.yaw_sensor / 100) % 360,
- vfr_hud_throttle(),
- vfr_hud_alt(),
- vfr_hud_climbrate());
- }
- void GCS_MAVLINK::zero_rc_outputs()
- {
- // Send an invalid signal to the motors to prevent spinning due to neutral (1500) pwm pulse being cut short
- // For that matter, send an invalid signal to all channels to prevent undesired/unexpected behavior
- SRV_Channels::cork();
- for (int i=0; i<NUM_RC_CHANNELS; i++) {
- hal.rcout->write(i, 0);
- }
- SRV_Channels::push();
- }
- /*
- handle a MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN command
- Optionally disable PX4IO overrides. This is done for quadplanes to
- prevent the mixer running while rebooting which can start the VTOL
- motors. That can be dangerous when a preflight reboot is done with
- the pilot close to the aircraft and can also damage the aircraft
- */
- MAV_RESULT GCS_MAVLINK::handle_preflight_reboot(const mavlink_command_long_t &packet)
- {
- if (is_equal(packet.param1, 42.0f) &&
- is_equal(packet.param2, 24.0f) &&
- is_equal(packet.param3, 71.0f) &&
- is_equal(packet.param4, 93.0f)) {
- // this is a magic sequence to force the main loop to
- // lockup. This is for testing the stm32 watchdog
- // functionality
- while (true) {
- send_text(MAV_SEVERITY_WARNING,"entering lockup");
- hal.scheduler->delay(250);
- }
- }
- if (hal.util->get_soft_armed()) {
- // refuse reboot when armed
- return MAV_RESULT_FAILED;
- }
- if (!(is_equal(packet.param1, 1.0f) || is_equal(packet.param1, 3.0f))) {
- // param1 must be 1 or 3 - 1 being reboot, 3 being reboot-to-bootloader
- return MAV_RESULT_UNSUPPORTED;
- }
- if (should_zero_rc_outputs_on_reboot()) {
- zero_rc_outputs();
- }
- // send ack before we reboot
- mavlink_msg_command_ack_send(chan, packet.command, MAV_RESULT_ACCEPTED);
- // Notify might want to blink some LEDs:
- AP_Notify *notify = AP_Notify::get_singleton();
- if (notify) {
- AP_Notify::flags.firmware_update = 1;
- notify->update();
- }
- // force safety on
- hal.rcout->force_safety_on();
- // flush pending parameter writes
- AP_Param::flush();
- hal.scheduler->delay(200);
-
- // when packet.param1 == 3 we reboot to hold in bootloader
- const bool hold_in_bootloader = is_equal(packet.param1, 3.0f);
- hal.scheduler->reboot(hold_in_bootloader);
- return MAV_RESULT_FAILED;
- }
- /*
- handle a flight termination request
- */
- MAV_RESULT GCS_MAVLINK::handle_flight_termination(const mavlink_command_long_t &packet)
- {
- AP_AdvancedFailsafe *failsafe = get_advanced_failsafe();
- if (failsafe == nullptr) {
- return MAV_RESULT_UNSUPPORTED;
- }
- bool should_terminate = packet.param1 > 0.5f;
- if (failsafe->gcs_terminate(should_terminate, "GCS request")) {
- return MAV_RESULT_ACCEPTED;
- }
- return MAV_RESULT_FAILED;
- }
- /*
- handle a R/C bind request (for spektrum)
- */
- MAV_RESULT GCS_MAVLINK::handle_rc_bind(const mavlink_command_long_t &packet)
- {
- // initiate bind procedure. We accept the DSM type from either
- // param1 or param2 due to a past mixup with what parameter is the
- // right one
- if (!RC_Channels::receiver_bind(packet.param2>0?packet.param2:packet.param1)) {
- return MAV_RESULT_FAILED;
- }
- return MAV_RESULT_ACCEPTED;
- }
- uint64_t GCS_MAVLINK::timesync_receive_timestamp_ns() const
- {
- uint64_t ret = _port->receive_time_constraint_us(PAYLOAD_SIZE(chan, TIMESYNC));
- if (ret == 0) {
- ret = AP_HAL::micros64();
- }
- return ret*1000LL;
- }
- uint64_t GCS_MAVLINK::timesync_timestamp_ns() const
- {
- // we add in our own system id try to ensure we only consider
- // responses to our own timesync request messages
- return AP_HAL::micros64()*1000LL + mavlink_system.sysid;
- }
- /*
- return a timesync request
- Sends back ts1 as received, and tc1 is the local timestamp in usec
- */
- void GCS_MAVLINK::handle_timesync(const mavlink_message_t &msg)
- {
- // decode incoming timesync message
- mavlink_timesync_t tsync;
- mavlink_msg_timesync_decode(&msg, &tsync);
- if (tsync.tc1 != 0) {
- // this is a response to a timesync request
- if (tsync.ts1 != _timesync_request.sent_ts1) {
- // we didn't actually send the request.... or it's a
- // response to an ancient request...
- return;
- }
- const uint64_t round_trip_time_us = (timesync_receive_timestamp_ns() - _timesync_request.sent_ts1)*0.001f;
- #if 0
- gcs().send_text(MAV_SEVERITY_INFO,
- "timesync response sysid=%u (latency=%fms)",
- msg.sysid,
- round_trip_time_us*0.001f);
- #endif
- AP_Logger *logger = AP_Logger::get_singleton();
- if (logger != nullptr) {
- AP::logger().Write(
- "TSYN",
- "TimeUS,SysID,RTT",
- "s-s",
- "F-F",
- "QBQ",
- AP_HAL::micros64(),
- msg.sysid,
- round_trip_time_us
- );
- }
- return;
- }
- if (!HAVE_PAYLOAD_SPACE(chan, TIMESYNC)) {
- // drop this timesync request entirely
- return;
- }
- // create new timesync struct with tc1 field as system time in
- // nanoseconds. The client timestamp is as close as possible to
- // the time we received the TIMESYNC message.
- mavlink_timesync_t rsync;
- rsync.tc1 = timesync_receive_timestamp_ns();
- rsync.ts1 = tsync.ts1;
- // respond with a timesync message
- mavlink_msg_timesync_send(
- chan,
- rsync.tc1,
- rsync.ts1
- );
- }
- /*
- * broadcast a timesync message. We may get multiple responses to this request.
- */
- void GCS_MAVLINK::send_timesync()
- {
- _timesync_request.sent_ts1 = timesync_timestamp_ns();
- mavlink_msg_timesync_send(
- chan,
- 0,
- _timesync_request.sent_ts1
- );
- }
- void GCS_MAVLINK::handle_statustext(const mavlink_message_t &msg)
- {
- AP_Logger *logger = AP_Logger::get_singleton();
- if (logger == nullptr) {
- return;
- }
- mavlink_statustext_t packet;
- mavlink_msg_statustext_decode(&msg, &packet);
- const uint8_t max_prefix_len = 20;
- const uint8_t text_len = MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN+1+max_prefix_len;
- char text[text_len] = { 'G','C','S',':'};
- uint8_t offset = strlen(text);
- if (msg.sysid != sysid_my_gcs()) {
- offset = hal.util->snprintf(text,
- max_prefix_len,
- "SRC=%u/%u:",
- msg.sysid,
- msg.compid);
- offset = MIN(offset, max_prefix_len);
- }
- memcpy(&text[offset], packet.text, MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN);
- logger->Write_Message(text);
- }
- void GCS_MAVLINK::handle_system_time_message(const mavlink_message_t &msg)
- {
- mavlink_system_time_t packet;
- mavlink_msg_system_time_decode(&msg, &packet);
- AP::rtc().set_utc_usec(packet.time_unix_usec, AP_RTC::SOURCE_MAVLINK_SYSTEM_TIME);
- }
- MAV_RESULT GCS_MAVLINK::handle_command_camera(const mavlink_command_long_t &packet)
- {
- AP_Camera *camera = AP::camera();
- if (camera == nullptr) {
- return MAV_RESULT_UNSUPPORTED;
- }
- MAV_RESULT result = MAV_RESULT_FAILED;
- switch (packet.command) {
- case MAV_CMD_DO_DIGICAM_CONFIGURE:
- camera->configure(packet.param1,
- packet.param2,
- packet.param3,
- packet.param4,
- packet.param5,
- packet.param6,
- packet.param7);
- result = MAV_RESULT_ACCEPTED;
- break;
- case MAV_CMD_DO_DIGICAM_CONTROL:
- camera->control(packet.param1,
- packet.param2,
- packet.param3,
- packet.param4,
- packet.param5,
- packet.param6);
- result = MAV_RESULT_ACCEPTED;
- break;
- case MAV_CMD_DO_SET_CAM_TRIGG_DIST:
- camera->set_trigger_distance(packet.param1);
- result = MAV_RESULT_ACCEPTED;
- break;
- default:
- result = MAV_RESULT_UNSUPPORTED;
- break;
- }
- return result;
- }
- // sets ekf_origin if it has not been set.
- // should only be used when there is no GPS to provide an absolute position
- void GCS_MAVLINK::set_ekf_origin(const Location& loc)
- {
- // check location is valid
- if (!loc.check_latlng()) {
- return;
- }
- AP_AHRS &ahrs = AP::ahrs();
- // check if EKF origin has already been set
- Location ekf_origin;
- if (ahrs.get_origin(ekf_origin)) {
- return;
- }
- if (!ahrs.set_origin(loc)) {
- return;
- }
- ahrs.Log_Write_Home_And_Origin();
- // send ekf origin to GCS
- if (!try_send_message(MSG_ORIGIN)) {
- // try again later
- send_message(MSG_ORIGIN);
- }
- }
- void GCS_MAVLINK::handle_set_gps_global_origin(const mavlink_message_t &msg)
- {
- mavlink_set_gps_global_origin_t packet;
- mavlink_msg_set_gps_global_origin_decode(&msg, &packet);
- // sanity check location
- if (!check_latlng(packet.latitude, packet.longitude)) {
- // silently drop the request
- return;
- }
- Location ekf_origin {};
- ekf_origin.lat = packet.latitude;
- ekf_origin.lng = packet.longitude;
- ekf_origin.alt = packet.altitude / 10;
- set_ekf_origin(ekf_origin);
- }
- /*
- handle a DATA96 message
- */
- void GCS_MAVLINK::handle_data_packet(const mavlink_message_t &msg)
- {
- #if HAL_RCINPUT_WITH_AP_RADIO
- mavlink_data96_t m;
- mavlink_msg_data96_decode(&msg, &m);
- switch (m.type) {
- case 42:
- case 43: {
- // pass to AP_Radio (for firmware upload and playing test tunes)
- AP_Radio *radio = AP_Radio::get_singleton();
- if (radio != nullptr) {
- radio->handle_data_packet(chan, m);
- }
- break;
- }
- default:
- // unknown
- break;
- }
- #endif
- }
- void GCS_MAVLINK::handle_vision_position_delta(const mavlink_message_t &msg)
- {
- AP_VisualOdom *visual_odom = AP::visualodom();
- if (visual_odom == nullptr) {
- return;
- }
- visual_odom->handle_msg(msg);
- }
- void GCS_MAVLINK::handle_vision_position_estimate(const mavlink_message_t &msg)
- {
- mavlink_vision_position_estimate_t m;
- mavlink_msg_vision_position_estimate_decode(&msg, &m);
- handle_common_vision_position_estimate_data(m.usec, m.x, m.y, m.z, m.roll, m.pitch, m.yaw,
- PAYLOAD_SIZE(chan, VISION_POSITION_ESTIMATE));
- }
- void GCS_MAVLINK::handle_global_vision_position_estimate(const mavlink_message_t &msg)
- {
- mavlink_global_vision_position_estimate_t m;
- mavlink_msg_global_vision_position_estimate_decode(&msg, &m);
- handle_common_vision_position_estimate_data(m.usec, m.x, m.y, m.z, m.roll, m.pitch, m.yaw,
- PAYLOAD_SIZE(chan, GLOBAL_VISION_POSITION_ESTIMATE));
- }
- void GCS_MAVLINK::handle_vicon_position_estimate(const mavlink_message_t &msg)
- {
- mavlink_vicon_position_estimate_t m;
- mavlink_msg_vicon_position_estimate_decode(&msg, &m);
- handle_common_vision_position_estimate_data(m.usec, m.x, m.y, m.z, m.roll, m.pitch, m.yaw,
- PAYLOAD_SIZE(chan, VICON_POSITION_ESTIMATE));
- }
- // there are several messages which all have identical fields in them.
- // This function provides common handling for the data contained in
- // these packets
- void GCS_MAVLINK::handle_common_vision_position_estimate_data(const uint64_t usec,
- const float x,
- const float y,
- const float z,
- const float roll,
- const float pitch,
- const float yaw,
- const uint16_t payload_size)
- {
- // correct offboard timestamp to be in local ms since boot
- uint32_t timestamp_ms = correct_offboard_timestamp_usec_to_ms(usec, payload_size);
-
- // sensor assumed to be at 0,0,0 body-frame; need parameters for this?
- // or a new message
- const Vector3f sensor_offset = {};
- const Vector3f pos = {
- x,
- y,
- z
- };
- Quaternion attitude;
- attitude.from_euler(roll, pitch, yaw); // from_vector312?
- const float posErr = 0; // parameter required?
- const float angErr = 0; // parameter required?
- const uint32_t reset_timestamp_ms = 0; // no data available
- AP::ahrs().writeExtNavData(sensor_offset,
- pos,
- attitude,
- posErr,
- angErr,
- timestamp_ms,
- reset_timestamp_ms);
- log_vision_position_estimate_data(usec, timestamp_ms, x, y, z, roll, pitch, yaw);
- }
- void GCS_MAVLINK::log_vision_position_estimate_data(const uint64_t usec,
- const uint32_t corrected_msec,
- const float x,
- const float y,
- const float z,
- const float roll,
- const float pitch,
- const float yaw)
- {
- AP::logger().Write("VISP", "TimeUS,RemTimeUS,CTimeMS,PX,PY,PZ,Roll,Pitch,Yaw",
- "sssmmmddh", "FFC000000", "QQIffffff",
- (uint64_t)AP_HAL::micros64(),
- (uint64_t)usec,
- corrected_msec,
- (double)x,
- (double)y,
- (double)z,
- (double)(roll * RAD_TO_DEG),
- (double)(pitch * RAD_TO_DEG),
- (double)(yaw * RAD_TO_DEG));
- }
- void GCS_MAVLINK::handle_att_pos_mocap(const mavlink_message_t &msg)
- {
- mavlink_att_pos_mocap_t m;
- mavlink_msg_att_pos_mocap_decode(&msg, &m);
- // sensor assumed to be at 0,0,0 body-frame; need parameters for this?
- const Vector3f sensor_offset = {};
- const Vector3f pos = {
- m.x,
- m.y,
- m.z
- };
- Quaternion attitude = Quaternion(m.q);
- const float posErr = 0; // parameter required?
- const float angErr = 0; // parameter required?
- // correct offboard timestamp to be in local ms since boot
- uint32_t timestamp_ms = correct_offboard_timestamp_usec_to_ms(m.time_usec, PAYLOAD_SIZE(chan, ATT_POS_MOCAP));
- const uint32_t reset_timestamp_ms = 0; // no data available
- AP::ahrs().writeExtNavData(sensor_offset,
- pos,
- attitude,
- posErr,
- angErr,
- timestamp_ms,
- reset_timestamp_ms);
-
- // calculate euler orientation for logging
- float roll;
- float pitch;
- float yaw;
- attitude.to_euler(roll, pitch, yaw);
- log_vision_position_estimate_data(m.time_usec, timestamp_ms, m.x, m.y, m.z, roll, pitch, yaw);
- }
- void GCS_MAVLINK::handle_command_ack(const mavlink_message_t &msg)
- {
- AP_AccelCal *accelcal = AP::ins().get_acal();
- if (accelcal != nullptr) {
- accelcal->handleMessage(msg);
- }
- }
- // allow override of RC channel values for HIL or for complete GCS
- // control of switch position and RC PWM values.
- void GCS_MAVLINK::handle_rc_channels_override(const mavlink_message_t &msg)
- {
- if(msg.sysid != sysid_my_gcs()) {
- return; // Only accept control from our gcs
- }
- const uint32_t tnow = AP_HAL::millis();
- mavlink_rc_channels_override_t packet;
- mavlink_msg_rc_channels_override_decode(&msg, &packet);
- const uint16_t override_data[] = {
- packet.chan1_raw,
- packet.chan2_raw,
- packet.chan3_raw,
- packet.chan4_raw,
- packet.chan5_raw,
- packet.chan6_raw,
- packet.chan7_raw,
- packet.chan8_raw,
- packet.chan9_raw,
- packet.chan10_raw,
- packet.chan11_raw,
- packet.chan12_raw,
- packet.chan13_raw,
- packet.chan14_raw,
- packet.chan15_raw,
- packet.chan16_raw
- };
- for (uint8_t i=0; i<ARRAY_SIZE(override_data); i++) {
- // Per MAVLink spec a value of UINT16_MAX means to ignore this field.
- if (override_data[i] != UINT16_MAX) {
- RC_Channels::set_override(i, override_data[i], tnow);
- }
- }
- }
- // allow override of RC channel values for HIL or for complete GCS
- // control of switch position and RC PWM values.
- void GCS_MAVLINK::handle_optical_flow(const mavlink_message_t &msg)
- {
- OpticalFlow *optflow = AP::opticalflow();
- if (optflow == nullptr) {
- return;
- }
- optflow->handle_msg(msg);
- }
- /*
- handle messages which don't require vehicle specific data
- */
- void GCS_MAVLINK::handle_common_message(const mavlink_message_t &msg)
- {
- switch (msg.msgid) {
- case MAVLINK_MSG_ID_COMMAND_ACK: {
- handle_command_ack(msg);
- break;
- }
- case MAVLINK_MSG_ID_SETUP_SIGNING:
- handle_setup_signing(msg);
- break;
- case MAVLINK_MSG_ID_PARAM_REQUEST_LIST:
- case MAVLINK_MSG_ID_PARAM_SET:
- case MAVLINK_MSG_ID_PARAM_REQUEST_READ:
- handle_common_param_message(msg);
- break;
- case MAVLINK_MSG_ID_SET_GPS_GLOBAL_ORIGIN:
- handle_set_gps_global_origin(msg);
- break;
- case MAVLINK_MSG_ID_DEVICE_OP_READ:
- handle_device_op_read(msg);
- break;
- case MAVLINK_MSG_ID_DEVICE_OP_WRITE:
- handle_device_op_write(msg);
- break;
- case MAVLINK_MSG_ID_TIMESYNC:
- handle_timesync(msg);
- break;
- case MAVLINK_MSG_ID_LOG_REQUEST_LIST:
- case MAVLINK_MSG_ID_LOG_REQUEST_DATA:
- case MAVLINK_MSG_ID_LOG_ERASE:
- case MAVLINK_MSG_ID_LOG_REQUEST_END:
- case MAVLINK_MSG_ID_REMOTE_LOG_BLOCK_STATUS:
- AP::logger().handle_mavlink_msg(*this, msg);
- break;
- case MAVLINK_MSG_ID_DIGICAM_CONTROL:
- {
- AP_Camera *camera = AP::camera();
- if (camera == nullptr) {
- return;
- }
- camera->control_msg(msg);
- }
- break;
- case MAVLINK_MSG_ID_SET_MODE:
- handle_set_mode(msg);
- break;
- case MAVLINK_MSG_ID_AUTOPILOT_VERSION_REQUEST:
- handle_send_autopilot_version(msg);
- break;
- case MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST:
- case MAVLINK_MSG_ID_MISSION_REQUEST_LIST:
- case MAVLINK_MSG_ID_MISSION_COUNT:
- case MAVLINK_MSG_ID_MISSION_CLEAR_ALL:
- case MAVLINK_MSG_ID_MISSION_ITEM:
- case MAVLINK_MSG_ID_MISSION_ITEM_INT:
- case MAVLINK_MSG_ID_MISSION_REQUEST_INT:
- case MAVLINK_MSG_ID_MISSION_REQUEST:
- case MAVLINK_MSG_ID_MISSION_ACK:
- case MAVLINK_MSG_ID_MISSION_SET_CURRENT:
- handle_common_mission_message(msg);
- break;
- case MAVLINK_MSG_ID_COMMAND_LONG:
- handle_command_long(msg);
- break;
- case MAVLINK_MSG_ID_COMMAND_INT:
- handle_command_int(msg);
- break;
- case MAVLINK_MSG_ID_FENCE_POINT:
- case MAVLINK_MSG_ID_FENCE_FETCH_POINT:
- handle_fence_message(msg);
- break;
- case MAVLINK_MSG_ID_GIMBAL_REPORT:
- handle_mount_message(msg);
- break;
- case MAVLINK_MSG_ID_PARAM_VALUE:
- handle_param_value(msg);
- break;
- case MAVLINK_MSG_ID_SERIAL_CONTROL:
- handle_serial_control(msg);
- break;
- case MAVLINK_MSG_ID_GPS_RTCM_DATA:
- case MAVLINK_MSG_ID_GPS_INPUT:
- case MAVLINK_MSG_ID_HIL_GPS:
- case MAVLINK_MSG_ID_GPS_INJECT_DATA:
- AP::gps().handle_msg(msg);
- break;
- case MAVLINK_MSG_ID_STATUSTEXT:
- handle_statustext(msg);
- break;
- case MAVLINK_MSG_ID_LED_CONTROL:
- // send message to Notify
- AP_Notify::handle_led_control(msg);
- break;
- case MAVLINK_MSG_ID_MOUNT_CONFIGURE: // deprecated. Use MAV_CMD_DO_MOUNT_CONFIGURE
- case MAVLINK_MSG_ID_MOUNT_CONTROL: // deprecated. Use MAV_CMD_DO_MOUNT_CONTROL
- handle_mount_message(msg);
- break;
- case MAVLINK_MSG_ID_PLAY_TUNE:
- // send message to Notify
- AP_Notify::handle_play_tune(msg);
- break;
- case MAVLINK_MSG_ID_RALLY_POINT:
- case MAVLINK_MSG_ID_RALLY_FETCH_POINT:
- handle_common_rally_message(msg);
- break;
- case MAVLINK_MSG_ID_REQUEST_DATA_STREAM:
- handle_request_data_stream(msg);
- break;
- case MAVLINK_MSG_ID_DATA96:
- handle_data_packet(msg);
- break;
- case MAVLINK_MSG_ID_VISION_POSITION_DELTA:
- handle_vision_position_delta(msg);
- break;
- case MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE:
- handle_vision_position_estimate(msg);
- break;
- case MAVLINK_MSG_ID_GLOBAL_VISION_POSITION_ESTIMATE:
- handle_global_vision_position_estimate(msg);
- break;
- case MAVLINK_MSG_ID_VICON_POSITION_ESTIMATE:
- handle_vicon_position_estimate(msg);
- break;
- case MAVLINK_MSG_ID_ATT_POS_MOCAP:
- handle_att_pos_mocap(msg);
- break;
- case MAVLINK_MSG_ID_SYSTEM_TIME:
- handle_system_time_message(msg);
- break;
- case MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE:
- handle_rc_channels_override(msg);
- break;
- case MAVLINK_MSG_ID_OPTICAL_FLOW:
- handle_optical_flow(msg);
- break;
- }
- }
- void GCS_MAVLINK::handle_common_mission_message(const mavlink_message_t &msg)
- {
- AP_Mission *_mission = AP::mission();
- if (_mission == nullptr) {
- return;
- }
- switch (msg.msgid) {
- case MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST: // MAV ID: 38
- {
- handle_mission_write_partial_list(msg);
- break;
- }
- // GCS has sent us a mission item, store to EEPROM
- case MAVLINK_MSG_ID_MISSION_ITEM: // MAV ID: 39
- case MAVLINK_MSG_ID_MISSION_ITEM_INT:
- handle_mission_item(msg);
- break;
- // read an individual command from EEPROM and send it to the GCS
- case MAVLINK_MSG_ID_MISSION_REQUEST_INT:
- handle_mission_request_int(msg);
- break;
- case MAVLINK_MSG_ID_MISSION_REQUEST:
- handle_mission_request(msg);
- break;
- case MAVLINK_MSG_ID_MISSION_SET_CURRENT: // MAV ID: 41
- {
- handle_mission_set_current(*_mission, msg);
- break;
- }
- // GCS request the full list of commands, we return just the number and leave the GCS to then request each command individually
- case MAVLINK_MSG_ID_MISSION_REQUEST_LIST: // MAV ID: 43
- {
- handle_mission_request_list(msg);
- break;
- }
- // GCS provides the full number of commands it wishes to upload
- // individual commands will then be sent from the GCS using the MAVLINK_MSG_ID_MISSION_ITEM message
- case MAVLINK_MSG_ID_MISSION_COUNT: // MAV ID: 44
- {
- handle_mission_count(msg);
- break;
- }
- case MAVLINK_MSG_ID_MISSION_CLEAR_ALL: // MAV ID: 45
- {
- handle_mission_clear_all(msg);
- break;
- }
- case MAVLINK_MSG_ID_MISSION_ACK:
- /* not used */
- break;
- }
- }
- void GCS_MAVLINK::handle_send_autopilot_version(const mavlink_message_t &msg)
- {
- send_message(MSG_AUTOPILOT_VERSION);
- }
- void GCS_MAVLINK::send_banner()
- {
- // mark the firmware version in the tlog
- const AP_FWVersion &fwver = AP::fwversion();
- send_text(MAV_SEVERITY_INFO, "%s", fwver.fw_string);
- if (fwver.middleware_name && fwver.os_name) {
- send_text(MAV_SEVERITY_INFO, "%s: %s %s: %s",
- fwver.middleware_name, fwver.middleware_hash_str,
- fwver.os_name, fwver.os_hash_str);
- } else if (fwver.os_name) {
- send_text(MAV_SEVERITY_INFO, "%s: %s",
- fwver.os_name, fwver.os_hash_str);
- }
- // send system ID if we can
- char sysid[40];
- if (hal.util->get_system_id(sysid)) {
- send_text(MAV_SEVERITY_INFO, "%s", sysid);
- }
- }
- void GCS_MAVLINK::send_simstate() const
- {
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- SITL::SITL *sitl = AP::sitl();
- if (sitl == nullptr) {
- return;
- }
- sitl->simstate_send(get_chan());
- #endif
- }
- MAV_RESULT GCS_MAVLINK::handle_command_flash_bootloader(const mavlink_command_long_t &packet)
- {
- if (uint32_t(packet.param5) != 290876) {
- gcs().send_text(MAV_SEVERITY_INFO, "Magic not set");
- return MAV_RESULT_FAILED;
- }
- if (!hal.util->flash_bootloader()) {
- return MAV_RESULT_FAILED;
- }
- return MAV_RESULT_ACCEPTED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_preflight_set_sensor_offsets(const mavlink_command_long_t &packet)
- {
- Compass &compass = AP::compass();
- uint8_t compassNumber = -1;
- if (is_equal(packet.param1, 2.0f)) {
- compassNumber = 0;
- } else if (is_equal(packet.param1, 5.0f)) {
- compassNumber = 1;
- } else if (is_equal(packet.param1, 6.0f)) {
- compassNumber = 2;
- }
- if (compassNumber == (uint8_t) -1) {
- return MAV_RESULT_FAILED;
- }
- compass.set_and_save_offsets(compassNumber, Vector3f(packet.param2, packet.param3, packet.param4));
- return MAV_RESULT_ACCEPTED;
- }
- bool GCS_MAVLINK::calibrate_gyros()
- {
- AP::ins().init_gyro();
- if (!AP::ins().gyro_calibrated_ok_all()) {
- return false;
- }
- AP::ahrs().reset_gyro_drift();
- return true;
- }
- MAV_RESULT GCS_MAVLINK::_handle_command_preflight_calibration_baro()
- {
- // fast barometer calibration
- gcs().send_text(MAV_SEVERITY_INFO, "Updating barometer calibration");
- AP::baro().update_calibration();
- gcs().send_text(MAV_SEVERITY_INFO, "Barometer calibration complete");
- AP_Airspeed *airspeed = AP_Airspeed::get_singleton();
- if (airspeed != nullptr) {
- airspeed->calibrate(false);
- }
- return MAV_RESULT_ACCEPTED;
- }
- MAV_RESULT GCS_MAVLINK::_handle_command_preflight_calibration(const mavlink_command_long_t &packet)
- {
- EXPECT_DELAY_MS(30000);
- if (is_equal(packet.param1,1.0f)) {
- if (!calibrate_gyros()) {
- return MAV_RESULT_FAILED;
- }
- return MAV_RESULT_ACCEPTED;
- }
- if (is_equal(packet.param3,1.0f)) {
- return _handle_command_preflight_calibration_baro();
- }
- if (is_equal(packet.param5,1.0f)) {
- // start with gyro calibration
- if (!calibrate_gyros()) {
- return MAV_RESULT_FAILED;
- }
- // start accel cal
- AP::ins().acal_init();
- AP::ins().get_acal()->start(this);
- return MAV_RESULT_ACCEPTED;
- }
- if (is_equal(packet.param5,2.0f)) {
- if (!calibrate_gyros()) {
- return MAV_RESULT_FAILED;
- }
- float trim_roll, trim_pitch;
- if (!AP::ins().calibrate_trim(trim_roll, trim_pitch)) {
- return MAV_RESULT_FAILED;
- }
- // reset ahrs's trim to suggested values from calibration routine
- AP::ahrs().set_trim(Vector3f(trim_roll, trim_pitch, 0));
- return MAV_RESULT_ACCEPTED;
- }
- if (is_equal(packet.param5,4.0f)) {
- // simple accel calibration
- return AP::ins().simple_accel_cal();
- }
- return MAV_RESULT_UNSUPPORTED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_preflight_calibration(const mavlink_command_long_t &packet)
- {
- if (hal.util->get_soft_armed()) {
- // *preflight*, remember?
- return MAV_RESULT_FAILED;
- }
- // now call subclass methods:
- return _handle_command_preflight_calibration(packet);
- }
- MAV_RESULT GCS_MAVLINK::handle_command_preflight_can(const mavlink_command_long_t &packet)
- {
- #if HAL_WITH_UAVCAN
- if (hal.util->get_soft_armed()) {
- // *preflight*, remember?
- return MAV_RESULT_TEMPORARILY_REJECTED;
- }
- bool start_stop = is_equal(packet.param1,1.0f) ? true : false;
- bool result = true;
- bool can_exists = false;
- uint8_t num_drivers = AP::can().get_num_drivers();
- for (uint8_t i = 0; i < num_drivers; i++) {
- switch (AP::can().get_protocol_type(i)) {
- case AP_BoardConfig_CAN::Protocol_Type_KDECAN: {
- // To be replaced with macro saying if KDECAN library is included
- #if APM_BUILD_TYPE(APM_BUILD_ArduCopter) || APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_TYPE(APM_BUILD_ArduSub)
- AP_KDECAN *ap_kdecan = AP_KDECAN::get_kdecan(i);
- if (ap_kdecan != nullptr) {
- can_exists = true;
- result = ap_kdecan->run_enumeration(start_stop) && result;
- }
- break;
- #else
- UNUSED_RESULT(start_stop); // prevent unused variable error
- #endif
- }
- case AP_BoardConfig_CAN::Protocol_Type_UAVCAN:
- case AP_BoardConfig_CAN::Protocol_Type_None:
- default:
- break;
- }
- }
- MAV_RESULT ack = MAV_RESULT_DENIED;
- if (can_exists) {
- ack = result ? MAV_RESULT_ACCEPTED : MAV_RESULT_FAILED;
- }
- return ack;
- #else
- return MAV_RESULT_UNSUPPORTED;
- #endif
- }
- MAV_RESULT GCS_MAVLINK::handle_command_battery_reset(const mavlink_command_long_t &packet)
- {
- const uint16_t battery_mask = packet.param1;
- const float percentage = packet.param2;
- if (AP::battery().reset_remaining(battery_mask, percentage)) {
- return MAV_RESULT_ACCEPTED;
- }
- return MAV_RESULT_FAILED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_mag_cal(const mavlink_command_long_t &packet)
- {
- return AP::compass().handle_mag_cal_command(packet);
- }
- MAV_RESULT GCS_MAVLINK::handle_command_request_autopilot_capabilities(const mavlink_command_long_t &packet)
- {
- if (!is_equal(packet.param1,1.0f)) {
- return MAV_RESULT_FAILED;
- }
- send_message(MSG_AUTOPILOT_VERSION);
- return MAV_RESULT_ACCEPTED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_do_send_banner(const mavlink_command_long_t &packet)
- {
- send_banner();
- return MAV_RESULT_ACCEPTED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_do_set_mode(const mavlink_command_long_t &packet)
- {
- const MAV_MODE _base_mode = (MAV_MODE)packet.param1;
- const uint32_t _custom_mode = (uint32_t)packet.param2;
- return _set_mode_common(_base_mode, _custom_mode);
- }
- MAV_RESULT GCS_MAVLINK::handle_command_get_home_position(const mavlink_command_long_t &packet)
- {
- if (!AP::ahrs().home_is_set()) {
- return MAV_RESULT_FAILED;
- }
- if (!try_send_message(MSG_HOME)) {
- // try again later
- send_message(MSG_HOME);
- }
- if (!try_send_message(MSG_ORIGIN)) {
- // try again later
- send_message(MSG_ORIGIN);
- }
- return MAV_RESULT_ACCEPTED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_do_gripper(const mavlink_command_long_t &packet)
- {
- AP_Gripper *gripper = AP::gripper();
- if (gripper == nullptr) {
- return MAV_RESULT_FAILED;
- }
- // param1 : gripper number (ignored)
- // param2 : action (0=release, 1=grab). See GRIPPER_ACTIONS enum.
- if(!gripper->enabled()) {
- return MAV_RESULT_FAILED;
- }
- MAV_RESULT result = MAV_RESULT_ACCEPTED;
- switch ((uint8_t)packet.param2) {
- case GRIPPER_ACTION_RELEASE:
- gripper->release();
- break;
- case GRIPPER_ACTION_GRAB:
- gripper->grab();
- break;
- default:
- result = MAV_RESULT_FAILED;
- break;
- }
- return result;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_accelcal_vehicle_pos(const mavlink_command_long_t &packet)
- {
- if (!AP::ins().get_acal()->gcs_vehicle_position(packet.param1)) {
- return MAV_RESULT_FAILED;
- }
- return MAV_RESULT_ACCEPTED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_mount(const mavlink_command_long_t &packet)
- {
- AP_Mount *mount = AP::mount();
- if (mount == nullptr) {
- return MAV_RESULT_UNSUPPORTED;
- }
- return mount->handle_command_long(packet);
- }
- MAV_RESULT GCS_MAVLINK::handle_command_do_set_home(const mavlink_command_long_t &packet)
- {
- if (is_equal(packet.param1, 1.0f) || (is_zero(packet.param5) && is_zero(packet.param6))) {
- // param1 is 1 (or both lat and lon are zero); use current location
- if (!set_home_to_current_location(true)) {
- return MAV_RESULT_FAILED;
- }
- return MAV_RESULT_ACCEPTED;
- }
- // ensure param1 is zero
- if (!is_zero(packet.param1)) {
- return MAV_RESULT_FAILED;
- }
- Location new_home_loc;
- new_home_loc.lat = (int32_t)(packet.param5 * 1.0e7f);
- new_home_loc.lng = (int32_t)(packet.param6 * 1.0e7f);
- new_home_loc.alt = (int32_t)(packet.param7 * 100.0f);
- if (!set_home(new_home_loc, true)) {
- return MAV_RESULT_FAILED;
- }
- return MAV_RESULT_ACCEPTED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_long_packet(const mavlink_command_long_t &packet)
- {
- MAV_RESULT result = MAV_RESULT_FAILED;
- switch (packet.command) {
- case MAV_CMD_ACCELCAL_VEHICLE_POS:
- result = handle_command_accelcal_vehicle_pos(packet);
- break;
- case MAV_CMD_DO_SET_MODE:
- result = handle_command_do_set_mode(packet);
- break;
- case MAV_CMD_DO_SEND_BANNER:
- result = handle_command_do_send_banner(packet);
- break;
- case MAV_CMD_DO_SET_HOME:
- result = handle_command_do_set_home(packet);
- break;
- case MAV_CMD_DO_FENCE_ENABLE:
- result = handle_command_do_fence_enable(packet);
- break;
- case MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN:
- result = handle_preflight_reboot(packet);
- break;
- case MAV_CMD_DO_START_MAG_CAL:
- case MAV_CMD_DO_ACCEPT_MAG_CAL:
- case MAV_CMD_DO_CANCEL_MAG_CAL: {
- result = handle_command_mag_cal(packet);
- break;
- }
- case MAV_CMD_START_RX_PAIR:
- result = handle_rc_bind(packet);
- break;
- case MAV_CMD_DO_DIGICAM_CONFIGURE:
- case MAV_CMD_DO_DIGICAM_CONTROL:
- case MAV_CMD_DO_SET_CAM_TRIGG_DIST:
- result = handle_command_camera(packet);
- break;
- case MAV_CMD_DO_GRIPPER:
- result = handle_command_do_gripper(packet);
- break;
- case MAV_CMD_DO_MOUNT_CONFIGURE:
- case MAV_CMD_DO_MOUNT_CONTROL:
- result = handle_command_mount(packet);
- break;
- case MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES: {
- result = handle_command_request_autopilot_capabilities(packet);
- break;
- }
- case MAV_CMD_DO_SET_ROI_LOCATION:
- case MAV_CMD_DO_SET_ROI:
- result = handle_command_do_set_roi(packet);
- break;
- case MAV_CMD_PREFLIGHT_CALIBRATION:
- result = handle_command_preflight_calibration(packet);
- break;
- case MAV_CMD_BATTERY_RESET:
- result = handle_command_battery_reset(packet);
- break;
-
- case MAV_CMD_PREFLIGHT_UAVCAN:
- result = handle_command_preflight_can(packet);
- break;
- case MAV_CMD_FLASH_BOOTLOADER:
- result = handle_command_flash_bootloader(packet);
- break;
- case MAV_CMD_PREFLIGHT_SET_SENSOR_OFFSETS: {
- result = handle_command_preflight_set_sensor_offsets(packet);
- break;
- }
- case MAV_CMD_GET_HOME_POSITION:
- result = handle_command_get_home_position(packet);
- break;
- case MAV_CMD_PREFLIGHT_STORAGE:
- if (is_equal(packet.param1, 2.0f)) {
- AP_Param::erase_all();
- send_text(MAV_SEVERITY_WARNING, "All parameters reset, reboot board");
- result= MAV_RESULT_ACCEPTED;
- }
- break;
- case MAV_CMD_SET_MESSAGE_INTERVAL:
- result = handle_command_set_message_interval(packet);
- break;
- case MAV_CMD_GET_MESSAGE_INTERVAL:
- result = handle_command_get_message_interval(packet);
- break;
- case MAV_CMD_REQUEST_MESSAGE:
- result = handle_command_request_message(packet);
- break;
- case MAV_CMD_DO_SET_SERVO:
- case MAV_CMD_DO_REPEAT_SERVO:
- case MAV_CMD_DO_SET_RELAY:
- case MAV_CMD_DO_REPEAT_RELAY:
- result = handle_servorelay_message(packet);
- break;
- case MAV_CMD_DO_FLIGHTTERMINATION:
- result = handle_flight_termination(packet);
- break;
- case MAV_CMD_COMPONENT_ARM_DISARM:
- if (is_equal(packet.param1,1.0f)) {
- // run pre_arm_checks and arm_checks and display failures
- const bool do_arming_checks = !is_equal(packet.param2,magic_force_arm_value);
- if (AP::arming().is_armed() ||
- AP::arming().arm(AP_Arming::Method::MAVLINK, do_arming_checks)) {
- return MAV_RESULT_ACCEPTED;
- }
- return MAV_RESULT_FAILED;
- }
- if (is_zero(packet.param1)) {
- if (!AP::arming().is_armed()) {
- return MAV_RESULT_ACCEPTED;
- }
- // allow vehicle to disallow disarm. Copter does this if
- // the vehicle isn't considered landed.
- if (!allow_disarm() &&
- !is_equal(packet.param2, magic_force_disarm_value)) {
- return MAV_RESULT_FAILED;
- }
- if (AP::arming().disarm()) {
- return MAV_RESULT_ACCEPTED;
- }
- return MAV_RESULT_FAILED;
- }
- return MAV_RESULT_UNSUPPORTED;
- default:
- result = MAV_RESULT_UNSUPPORTED;
- break;
- }
- return result;
- }
- bool GCS_MAVLINK::command_long_stores_location(const MAV_CMD command)
- {
- switch(command) {
- case MAV_CMD_DO_SET_HOME:
- case MAV_CMD_DO_SET_ROI:
- case MAV_CMD_NAV_TAKEOFF:
- return true;
- default:
- return false;
- }
- return false;
- }
- void GCS_MAVLINK::convert_COMMAND_LONG_to_COMMAND_INT(const mavlink_command_long_t &in, mavlink_command_int_t &out)
- {
- out.target_system = in.target_system;
- out.target_component = in.target_component;
- out.frame = MAV_FRAME_GLOBAL_RELATIVE_ALT; // FIXME?
- out.command = in.command;
- out.current = 0;
- out.autocontinue = 0;
- out.param1 = in.param1;
- out.param2 = in.param2;
- out.param3 = in.param3;
- out.param4 = in.param4;
- if (command_long_stores_location((MAV_CMD)in.command)) {
- out.x = in.param5 *1e7;
- out.y = in.param6 *1e7;
- } else {
- out.x = in.param5;
- out.y = in.param6;
- }
- out.z = in.param7;
- }
- void GCS_MAVLINK::handle_command_long(const mavlink_message_t &msg)
- {
- // decode packet
- mavlink_command_long_t packet;
- mavlink_msg_command_long_decode(&msg, &packet);
- hal.util->persistent_data.last_mavlink_cmd = packet.command;
- const MAV_RESULT result = handle_command_long_packet(packet);
- // send ACK or NAK
- mavlink_msg_command_ack_send(chan, packet.command, result);
- // log the packet:
- mavlink_command_int_t packet_int;
- convert_COMMAND_LONG_to_COMMAND_INT(packet, packet_int);
- AP::logger().Write_Command(packet_int, result, true);
- hal.util->persistent_data.last_mavlink_cmd = 0;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_do_set_roi(const Location &roi_loc)
- {
- AP_Mount *mount = AP::mount();
- if (mount == nullptr) {
- return MAV_RESULT_UNSUPPORTED;
- }
- // sanity check location
- if (!roi_loc.check_latlng()) {
- return MAV_RESULT_FAILED;
- }
- if (roi_loc.lat == 0 && roi_loc.lng == 0 && roi_loc.alt == 0) {
- // switch off the camera tracking if enabled
- if (mount->get_mode() == MAV_MOUNT_MODE_GPS_POINT) {
- mount->set_mode_to_default();
- }
- } else {
- // send the command to the camera mount
- mount->set_roi_target(roi_loc);
- }
- return MAV_RESULT_ACCEPTED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_int_do_set_home(const mavlink_command_int_t &packet)
- {
- if (is_equal(packet.param1, 1.0f) || (packet.x == 0 && packet.y == 0)) {
- // param1 is 1 (or both lat and lon are zero); use current location
- if (!set_home_to_current_location(true)) {
- return MAV_RESULT_FAILED;
- }
- return MAV_RESULT_ACCEPTED;
- }
- // ensure param1 is zero
- if (!is_zero(packet.param1)) {
- return MAV_RESULT_FAILED;
- }
- Location::AltFrame frame;
- if (!mavlink_coordinate_frame_to_location_alt_frame((MAV_FRAME)packet.frame, frame)) {
- // unknown coordinate frame
- return MAV_RESULT_UNSUPPORTED;
- }
- const Location new_home_loc{
- packet.x,
- packet.y,
- int32_t(packet.z * 100),
- frame,
- };
- if (!set_home(new_home_loc, true)) {
- return MAV_RESULT_FAILED;
- }
- return MAV_RESULT_ACCEPTED;
- }
- MAV_RESULT GCS_MAVLINK::handle_command_do_set_roi(const mavlink_command_int_t &packet)
- {
- // be aware that this method is called for both MAV_CMD_DO_SET_ROI
- // and MAV_CMD_DO_SET_ROI_LOCATION. If you intend to support any
- // of the extra fields in the former then you will need to split
- // off support for MAV_CMD_DO_SET_ROI_LOCATION (which doesn't
- // support the extra fields).
- // param1 : /* Region of interest mode (not used)*/
- // param2 : /* MISSION index/ target ID (not used)*/
- // param3 : /* ROI index (not used)*/
- // param4 : /* empty */
- // x : lat
- // y : lon
- // z : alt
- Location roi_loc;
- roi_loc.lat = packet.x;
- roi_loc.lng = packet.y;
- roi_loc.alt = (int32_t)(packet.z * 100.0f);
- return handle_command_do_set_roi(roi_loc);
- }
- MAV_RESULT GCS_MAVLINK::handle_command_do_set_roi(const mavlink_command_long_t &packet)
- {
- // be aware that this method is called for both MAV_CMD_DO_SET_ROI
- // and MAV_CMD_DO_SET_ROI_LOCATION. If you intend to support any
- // of the extra fields in the former then you will need to split
- // off support for MAV_CMD_DO_SET_ROI_LOCATION (which doesn't
- // support the extra fields).
- Location roi_loc;
- roi_loc.lat = (int32_t)(packet.param5 * 1.0e7f);
- roi_loc.lng = (int32_t)(packet.param6 * 1.0e7f);
- roi_loc.alt = (int32_t)(packet.param7 * 100.0f);
- return handle_command_do_set_roi(roi_loc);
- }
- MAV_RESULT GCS_MAVLINK::handle_command_int_packet(const mavlink_command_int_t &packet)
- {
- switch (packet.command) {
- case MAV_CMD_DO_SET_ROI:
- case MAV_CMD_DO_SET_ROI_LOCATION:
- return handle_command_do_set_roi(packet);
- case MAV_CMD_DO_SET_HOME:
- return handle_command_int_do_set_home(packet);
- default:
- break;
- }
- return MAV_RESULT_UNSUPPORTED;
- }
- void GCS_MAVLINK::handle_command_int(const mavlink_message_t &msg)
- {
- // decode packet
- mavlink_command_int_t packet;
- mavlink_msg_command_int_decode(&msg, &packet);
- hal.util->persistent_data.last_mavlink_cmd = packet.command;
- const MAV_RESULT result = handle_command_int_packet(packet);
- // send ACK or NAK
- mavlink_msg_command_ack_send(chan, packet.command, result);
- AP::logger().Write_Command(packet, result);
- hal.util->persistent_data.last_mavlink_cmd = 0;
- }
- void GCS::try_send_queued_message_for_type(MAV_MISSION_TYPE type) {
- MissionItemProtocol *prot = get_prot_for_mission_type(type);
- if (prot == nullptr) {
- return;
- }
- prot->queued_request_send();
- }
- bool GCS_MAVLINK::try_send_mission_message(const enum ap_message id)
- {
- AP_Mission *mission = AP::mission();
- if (mission == nullptr) {
- return true;
- }
- bool ret = true;
- switch (id) {
- case MSG_CURRENT_WAYPOINT:
- CHECK_PAYLOAD_SIZE(MISSION_CURRENT);
- mavlink_msg_mission_current_send(chan, mission->get_current_nav_index());
- ret = true;
- break;
- case MSG_MISSION_ITEM_REACHED:
- CHECK_PAYLOAD_SIZE(MISSION_ITEM_REACHED);
- mavlink_msg_mission_item_reached_send(chan, mission_item_reached_index);
- ret = true;
- break;
- case MSG_NEXT_MISSION_REQUEST_WAYPOINTS:
- CHECK_PAYLOAD_SIZE(MISSION_REQUEST);
- gcs().try_send_queued_message_for_type(MAV_MISSION_TYPE_MISSION);
- ret = true;
- break;
- case MSG_NEXT_MISSION_REQUEST_RALLY:
- CHECK_PAYLOAD_SIZE(MISSION_REQUEST);
- gcs().try_send_queued_message_for_type(MAV_MISSION_TYPE_RALLY);
- ret = true;
- break;
- default:
- ret = true;
- break;
- }
- return ret;
- }
- void GCS_MAVLINK::send_hwstatus()
- {
- mavlink_msg_hwstatus_send(
- chan,
- hal.analogin->board_voltage()*1000,
- 0);
- }
- void GCS_MAVLINK::send_rpm() const
- {
- AP_RPM *rpm = AP::rpm();
- if (rpm == nullptr) {
- return;
- }
- if (!rpm->enabled(0) && !rpm->enabled(1)) {
- return;
- }
- mavlink_msg_rpm_send(
- chan,
- rpm->get_rpm(0),
- rpm->get_rpm(1));
- }
- void GCS_MAVLINK::send_sys_status()
- {
- // send extended status only once vehicle has been initialised
- // to avoid unnecessary errors being reported to user
- if (!gcs().vehicle_initialised()) {
- return;
- }
- const AP_BattMonitor &battery = AP::battery();
- float battery_current;
- int8_t battery_remaining;
- if (battery.healthy() && battery.current_amps(battery_current)) {
- battery_remaining = get_battery_remaining_percentage();
- battery_current *= 100;
- } else {
- battery_current = -1;
- battery_remaining = -1;
- }
- uint32_t control_sensors_present;
- uint32_t control_sensors_enabled;
- uint32_t control_sensors_health;
- gcs().get_sensor_status_flags(control_sensors_present, control_sensors_enabled, control_sensors_health);
- const uint32_t errors = AP::internalerror().errors();
- const uint16_t errors1 = errors & 0xffff;
- const uint16_t errors2 = (errors>>16) & 0xffff;
- const uint16_t errors4 = AP::internalerror().count() & 0xffff;
- mavlink_msg_sys_status_send(
- chan,
- control_sensors_present,
- control_sensors_enabled,
- control_sensors_health,
- static_cast<uint16_t>(AP::scheduler().load_average() * 1000),
- battery.voltage() * 1000, // mV
- battery_current, // in 10mA units
- battery_remaining, // in %
- 0, // comm drops %,
- 0, // comm drops in pkts,
- errors1,
- errors2,
- 0, // errors3
- errors4); // errors4
- }
- void GCS_MAVLINK::send_extended_sys_state() const
- {
- mavlink_msg_extended_sys_state_send(chan, vtol_state(), landed_state());
- }
- void GCS_MAVLINK::send_attitude() const
- {
- const AP_AHRS &ahrs = AP::ahrs();
- const Vector3f omega = ahrs.get_gyro();
- mavlink_msg_attitude_send(
- chan,
- AP_HAL::millis(),
- ahrs.roll,
- ahrs.pitch,
- ahrs.yaw,
- omega.x,
- omega.y,
- omega.z);
- }
- int32_t GCS_MAVLINK::global_position_int_alt() const {
- return global_position_current_loc.alt * 10UL;
- }
- int32_t GCS_MAVLINK::global_position_int_relative_alt() const {
- float posD;
- AP::ahrs().get_relative_position_D_home(posD);
- posD *= -1000.0f; // change from down to up and metres to millimeters
- return posD;
- }
- void GCS_MAVLINK::send_global_position_int()
- {
- AP_AHRS &ahrs = AP::ahrs();
- ahrs.get_position(global_position_current_loc); // return value ignored; we send stale data
- Vector3f vel;
- if (!ahrs.get_velocity_NED(vel)) {
- vel.zero();
- }
- mavlink_msg_global_position_int_send(
- chan,
- AP_HAL::millis(),
- global_position_current_loc.lat, // in 1E7 degrees
- global_position_current_loc.lng, // in 1E7 degrees
- global_position_int_alt(), // millimeters above ground/sea level
- global_position_int_relative_alt(), // millimeters above home
- vel.x * 100, // X speed cm/s (+ve North)
- vel.y * 100, // Y speed cm/s (+ve East)
- vel.z * 100, // Z speed cm/s (+ve Down)
- ahrs.yaw_sensor); // compass heading in 1/100 degree
- }
- void GCS_MAVLINK::send_gimbal_report() const
- {
- AP_Mount *mount = AP::mount();
- if (mount == nullptr) {
- return;
- }
- mount->send_gimbal_report(chan);
- }
- void GCS_MAVLINK::send_mount_status() const
- {
- AP_Mount *mount = AP::mount();
- if (mount == nullptr) {
- return;
- }
- mount->send_mount_status(chan);
- }
- void GCS_MAVLINK::send_set_position_target_global_int(uint8_t target_system, uint8_t target_component, const Location& loc)
- {
- const uint16_t type_mask = POSITION_TARGET_TYPEMASK_VX_IGNORE | POSITION_TARGET_TYPEMASK_VY_IGNORE | POSITION_TARGET_TYPEMASK_VZ_IGNORE | \
- POSITION_TARGET_TYPEMASK_AX_IGNORE | POSITION_TARGET_TYPEMASK_AY_IGNORE | POSITION_TARGET_TYPEMASK_AZ_IGNORE | \
- POSITION_TARGET_TYPEMASK_YAW_IGNORE | POSITION_TARGET_TYPEMASK_YAW_RATE_IGNORE;
- // convert altitude to relative to home
- int32_t rel_alt;
- if (!loc.get_alt_cm(Location::AltFrame::ABOVE_HOME, rel_alt)) {
- return;
- }
- mavlink_msg_set_position_target_global_int_send(
- chan,
- AP_HAL::millis(),
- target_system,
- target_component,
- MAV_FRAME_GLOBAL_RELATIVE_ALT_INT,
- type_mask,
- loc.lat,
- loc.lng,
- rel_alt,
- 0,0,0, // vx, vy, vz
- 0,0,0, // ax, ay, az
- 0,0); // yaw, yaw_rate
- }
- bool GCS_MAVLINK::try_send_message(const enum ap_message id)
- {
- bool ret = true;
- switch(id) {
- case MSG_ROV_STATE_MONITORING:
- mavlink_msg_rov_state_monitoring_send_struct(chan,&rov_message);
- break;
- case MSG_SET_SLAVE_PARAMETER:
- mavlink_msg_set_slave_parameter_send_struct(chan,&get_stm32_param);
- break;
- case MSG_MOTOR_SPEED:
- mavlink_msg_motor_speed_send_struct(chan,&mav_motor_speed_back);
- break;
- case MSG_HV_REG_GET:
-
- mavlink_msg_hv_reg_get_send_struct(chan,&hv_reg_get);
- break;
- case MSG_ATTITUDE:
- CHECK_PAYLOAD_SIZE(ATTITUDE);
- send_attitude();
- break;
- case MSG_NEXT_PARAM:
- CHECK_PAYLOAD_SIZE(PARAM_VALUE);
- queued_param_send();
- break;
- case MSG_GIMBAL_REPORT:
- CHECK_PAYLOAD_SIZE(GIMBAL_REPORT);
- send_gimbal_report();
- break;
- case MSG_HEARTBEAT:
- CHECK_PAYLOAD_SIZE(HEARTBEAT);
- last_heartbeat_time = AP_HAL::millis();
- send_heartbeat();
- break;
- case MSG_HWSTATUS:
- CHECK_PAYLOAD_SIZE(HWSTATUS);
- send_hwstatus();
- break;
- case MSG_LOCATION:
- CHECK_PAYLOAD_SIZE(GLOBAL_POSITION_INT);
- send_global_position_int();
- break;
- case MSG_HOME:
- CHECK_PAYLOAD_SIZE(HOME_POSITION);
- send_home_position();
- break;
- case MSG_ORIGIN:
- CHECK_PAYLOAD_SIZE(GPS_GLOBAL_ORIGIN);
- send_gps_global_origin();
- break;
- case MSG_RPM:
- CHECK_PAYLOAD_SIZE(RPM);
- send_rpm();
- break;
- case MSG_CURRENT_WAYPOINT:
- case MSG_MISSION_ITEM_REACHED:
- case MSG_NEXT_MISSION_REQUEST_WAYPOINTS:
- case MSG_NEXT_MISSION_REQUEST_RALLY:
- ret = try_send_mission_message(id);
- break;
- case MSG_MAG_CAL_PROGRESS:
- ret = AP::compass().send_mag_cal_progress(*this);
- break;
- case MSG_MAG_CAL_REPORT:
- ret = AP::compass().send_mag_cal_report(*this);
- break;
- case MSG_BATTERY_STATUS:
- send_battery_status();
- break;
- case MSG_BATTERY2:
- CHECK_PAYLOAD_SIZE(BATTERY2);
- send_battery2();
- break;
- case MSG_EKF_STATUS_REPORT:
- #if AP_AHRS_NAVEKF_AVAILABLE
- CHECK_PAYLOAD_SIZE(EKF_STATUS_REPORT);
- AP::ahrs_navekf().send_ekf_status_report(chan);
- #endif
- break;
- case MSG_MEMINFO:
- CHECK_PAYLOAD_SIZE(MEMINFO);
- send_meminfo();
- break;
- case MSG_FENCE_STATUS:
- CHECK_PAYLOAD_SIZE(FENCE_STATUS);
- send_fence_status();
- break;
- case MSG_RANGEFINDER:
- CHECK_PAYLOAD_SIZE(RANGEFINDER);
- send_rangefinder();
- break;
- case MSG_DISTANCE_SENSOR:
- send_distance_sensor();
- break;
- case MSG_CAMERA_FEEDBACK:
- {
- AP_Camera *camera = AP::camera();
- if (camera == nullptr) {
- break;
- }
- CHECK_PAYLOAD_SIZE(CAMERA_FEEDBACK);
- camera->send_feedback(chan);
- }
- break;
- case MSG_SYSTEM_TIME:
- CHECK_PAYLOAD_SIZE(SYSTEM_TIME);
- send_system_time();
- break;
- case MSG_GPS_RAW:
- CHECK_PAYLOAD_SIZE(GPS_RAW_INT);
- AP::gps().send_mavlink_gps_raw(chan);
- break;
- case MSG_GPS_RTK:
- CHECK_PAYLOAD_SIZE(GPS_RTK);
- AP::gps().send_mavlink_gps_rtk(chan, 0);
- break;
- case MSG_GPS2_RAW:
- CHECK_PAYLOAD_SIZE(GPS2_RAW);
- AP::gps().send_mavlink_gps2_raw(chan);
- break;
- case MSG_GPS2_RTK:
- CHECK_PAYLOAD_SIZE(GPS2_RTK);
- AP::gps().send_mavlink_gps_rtk(chan, 1);
- break;
- case MSG_LOCAL_POSITION:
- CHECK_PAYLOAD_SIZE(LOCAL_POSITION_NED);
- send_local_position();
- break;
- case MSG_MOUNT_STATUS:
- CHECK_PAYLOAD_SIZE(MOUNT_STATUS);
- send_mount_status();
- break;
- case MSG_OPTICAL_FLOW:
- CHECK_PAYLOAD_SIZE(OPTICAL_FLOW);
- send_opticalflow();
- break;
- case MSG_POSITION_TARGET_GLOBAL_INT:
- CHECK_PAYLOAD_SIZE(POSITION_TARGET_GLOBAL_INT);
- send_position_target_global_int();
- break;
- case MSG_POSITION_TARGET_LOCAL_NED:
- CHECK_PAYLOAD_SIZE(POSITION_TARGET_LOCAL_NED);
- send_position_target_local_ned();
- break;
- case MSG_POWER_STATUS:
- CHECK_PAYLOAD_SIZE(POWER_STATUS);
- send_power_status();
- break;
- case MSG_RC_CHANNELS:
- CHECK_PAYLOAD_SIZE(RC_CHANNELS);
- send_rc_channels();
- break;
- case MSG_RC_CHANNELS_RAW:
- CHECK_PAYLOAD_SIZE(RC_CHANNELS_RAW);
- send_rc_channels_raw();
- break;
- case MSG_RAW_IMU:
- CHECK_PAYLOAD_SIZE(RAW_IMU);
- send_raw_imu();
- break;
- case MSG_SCALED_IMU:
- CHECK_PAYLOAD_SIZE(SCALED_IMU);
- send_scaled_imu(0, mavlink_msg_scaled_imu_send);
- break;
- case MSG_SCALED_IMU2:
- CHECK_PAYLOAD_SIZE(SCALED_IMU2);
- send_scaled_imu(1, mavlink_msg_scaled_imu2_send);
- break;
- case MSG_SCALED_IMU3:
- CHECK_PAYLOAD_SIZE(SCALED_IMU3);
- send_scaled_imu(2, mavlink_msg_scaled_imu3_send);
- break;
- case MSG_SCALED_PRESSURE:
- CHECK_PAYLOAD_SIZE(SCALED_PRESSURE);
- send_scaled_pressure();
- break;
- case MSG_SCALED_PRESSURE2:
- CHECK_PAYLOAD_SIZE(SCALED_PRESSURE2);
- send_scaled_pressure2();
- break;
- case MSG_SCALED_PRESSURE3:
- CHECK_PAYLOAD_SIZE(SCALED_PRESSURE3);
- send_scaled_pressure3();
- break;
- case MSG_SENSOR_OFFSETS:
- CHECK_PAYLOAD_SIZE(SENSOR_OFFSETS);
- send_sensor_offsets();
- break;
- case MSG_SERVO_OUTPUT_RAW:
- CHECK_PAYLOAD_SIZE(SERVO_OUTPUT_RAW);
- send_servo_output_raw();
- break;
- case MSG_SIMSTATE:
- CHECK_PAYLOAD_SIZE(SIMSTATE);
- send_simstate();
- break;
- case MSG_SYS_STATUS:
- CHECK_PAYLOAD_SIZE(SYS_STATUS);
- send_sys_status();
- break;
- case MSG_AHRS2:
- CHECK_PAYLOAD_SIZE(AHRS2);
- send_ahrs2();
- break;
- case MSG_AHRS3:
- CHECK_PAYLOAD_SIZE(AHRS3);
- send_ahrs3();
- break;
- case MSG_PID_TUNING:
- CHECK_PAYLOAD_SIZE(PID_TUNING);
- send_pid_tuning();
- break;
- case MSG_NAV_CONTROLLER_OUTPUT:
- CHECK_PAYLOAD_SIZE(NAV_CONTROLLER_OUTPUT);
- send_nav_controller_output();
- break;
- case MSG_AHRS:
- CHECK_PAYLOAD_SIZE(AHRS);
- send_ahrs();
- break;
- case MSG_EXTENDED_SYS_STATE:
- CHECK_PAYLOAD_SIZE(EXTENDED_SYS_STATE);
- send_extended_sys_state();
- break;
- case MSG_VFR_HUD:
- CHECK_PAYLOAD_SIZE(VFR_HUD);
- send_vfr_hud();
- break;
- case MSG_VIBRATION:
- CHECK_PAYLOAD_SIZE(VIBRATION);
- send_vibration();
- break;
- case MSG_AUTOPILOT_VERSION:
- CHECK_PAYLOAD_SIZE(AUTOPILOT_VERSION);
- send_autopilot_version();
- break;
- case MSG_ESC_TELEMETRY: {
- #ifdef HAVE_AP_BLHELI_SUPPORT
- CHECK_PAYLOAD_SIZE(ESC_TELEMETRY_1_TO_4);
- AP_BLHeli *blheli = AP_BLHeli::get_singleton();
- if (blheli) {
- blheli->send_esc_telemetry_mavlink(uint8_t(chan));
- }
- #endif
- #if HAL_WITH_UAVCAN
- uint8_t num_drivers = AP::can().get_num_drivers();
- for (uint8_t i = 0; i < num_drivers; i++) {
- switch (AP::can().get_protocol_type(i)) {
- case AP_BoardConfig_CAN::Protocol_Type_KDECAN: {
- // To be replaced with macro saying if KDECAN library is included
- #if APM_BUILD_TYPE(APM_BUILD_ArduCopter) || APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_TYPE(APM_BUILD_ArduSub)
- AP_KDECAN *ap_kdecan = AP_KDECAN::get_kdecan(i);
- if (ap_kdecan != nullptr) {
- ap_kdecan->send_mavlink(uint8_t(chan));
- }
- #endif
- break;
- }
- case AP_BoardConfig_CAN::Protocol_Type_ToshibaCAN: {
- AP_ToshibaCAN *ap_tcan = AP_ToshibaCAN::get_tcan(i);
- if (ap_tcan != nullptr) {
- ap_tcan->send_esc_telemetry_mavlink(uint8_t(chan));
- }
- break;
- }
- case AP_BoardConfig_CAN::Protocol_Type_UAVCAN:
- case AP_BoardConfig_CAN::Protocol_Type_None:
- default:
- break;
- }
- }
- #endif
- break;
- }
- default:
- // try_send_message must always at some stage return true for
- // a message, or we will attempt to infinitely retry the
- // message as part of send_message.
- // This message will be sent out at the same rate as the
- // unknown message, so should be safe.
- gcs().send_text(MAV_SEVERITY_DEBUG, "Sending unknown message (%u)", id);
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- AP_HAL::panic("Sending unknown ap_message %u", id);
- #endif
- break;
- }
- return ret;
- }
- uint16_t GCS_MAVLINK::get_interval_for_stream(GCS_MAVLINK::streams id) const
- {
- const int16_t frate = streamRates[id].get();
- if (frate == 0) {
- return 0;
- }
- const uint32_t ret = 1000/frate;
- if (ret > 60000) {
- return 60000;
- }
- return ret;
- }
- void GCS_MAVLINK::initialise_message_intervals_for_stream(GCS_MAVLINK::streams id)
- {
- for (uint8_t i=0; all_stream_entries[i].ap_message_ids != nullptr; i++) {
- const GCS_MAVLINK::stream_entries &entries = all_stream_entries[i];
- if (entries.stream_id != id) {
- continue;
- }
- // found it!
- const uint16_t interval_ms = get_interval_for_stream(id);
- for (uint8_t j=0; j<entries.num_ap_message_ids; j++) {
- set_ap_message_interval(entries.ap_message_ids[j], interval_ms);
- }
- break;
- }
- }
- void GCS_MAVLINK::initialise_message_intervals_from_streamrates()
- {
- // this is O(n^2), but it's once at boot and across a 10-entry list...
- for (uint8_t i=0; all_stream_entries[i].ap_message_ids != nullptr; i++) {
- initialise_message_intervals_for_stream(all_stream_entries[i].stream_id);
- }
- set_mavlink_message_id_interval(MAVLINK_MSG_ID_HEARTBEAT, 1000);
- }
- bool GCS_MAVLINK::get_default_interval_for_ap_message(const ap_message id, uint16_t &interval) const
- {
- if (id == MSG_HEARTBEAT) {
- // handle heartbeat requests as a special case because heartbeat is not "streamed"
- interval = 1000;
- return true;
- }
- // find which stream this ap_message is in
- for (uint8_t i=0; all_stream_entries[i].ap_message_ids != nullptr; i++) {
- const GCS_MAVLINK::stream_entries &entries = all_stream_entries[i];
- for (uint8_t j=0; j<entries.num_ap_message_ids; j++) {
- if (entries.ap_message_ids[j] == id) {
- interval = get_interval_for_stream(all_stream_entries[i].stream_id);
- return true;
- }
- }
- }
- return false;
- }
- bool GCS_MAVLINK::get_default_interval_for_mavlink_message_id(const uint32_t mavlink_message_id, uint16_t &interval) const
- {
- const ap_message id = mavlink_id_to_ap_message_id(mavlink_message_id);
- if (id == MSG_LAST) {
- return false;
- }
- return get_default_interval_for_ap_message(id, interval);
- }
- /*
- correct an offboard timestamp in microseconds into a local timestamp
- since boot in milliseconds. See the JitterCorrection code for details
- Return a value in milliseconds since boot (for use by the EKF)
- */
- uint32_t GCS_MAVLINK::correct_offboard_timestamp_usec_to_ms(uint64_t offboard_usec, uint16_t payload_size)
- {
- uint64_t local_us;
- // if the HAL supports it then constrain the latest possible time
- // the packet could have been sent by the uart receive time and
- // the baudrate and packet size.
- uint64_t uart_receive_time = _port->receive_time_constraint_us(payload_size);
- if (uart_receive_time != 0) {
- local_us = uart_receive_time;
- } else {
- local_us = AP_HAL::micros64();
- }
- uint64_t corrected_us = lag_correction.correct_offboard_timestamp_usec(offboard_usec, local_us);
- return corrected_us / 1000U;
- }
- /*
- return true if we will accept this packet. Used to implement SYSID_ENFORCE
- */
- bool GCS_MAVLINK::accept_packet(const mavlink_status_t &status,
- const mavlink_message_t &msg)
- {
- if (msg.sysid == mavlink_system.sysid) {
- // accept packets from our own components
- // (e.g. mavlink-connected companion computers)
- return true;
- }
- if (msg.sysid == sysid_my_gcs()) {
- return true;
- }
- if (msg.msgid == MAVLINK_MSG_ID_RADIO ||
- msg.msgid == MAVLINK_MSG_ID_RADIO_STATUS) {
- return true;
- }
- if (!sysid_enforce()) {
- return true;
- }
- return false;
- }
- /*
- update UART pass-thru, if enabled
- */
- void GCS::update_passthru(void)
- {
- WITH_SEMAPHORE(_passthru.sem);
- uint32_t now = AP_HAL::millis();
- bool enabled = AP::serialmanager().get_passthru(_passthru.port1, _passthru.port2, _passthru.timeout_s);
- if (enabled && !_passthru.enabled) {
- _passthru.start_ms = now;
- _passthru.last_ms = 0;
- _passthru.enabled = true;
- _passthru.last_port1_data_ms = now;
- gcs().send_text(MAV_SEVERITY_INFO, "Passthru enabled");
- if (!_passthru.timer_installed) {
- _passthru.timer_installed = true;
- hal.scheduler->register_timer_process(FUNCTOR_BIND_MEMBER(&GCS::passthru_timer, void));
- }
- } else if (!enabled && _passthru.enabled) {
- _passthru.enabled = false;
- _passthru.port1->lock_port(0, 0);
- _passthru.port2->lock_port(0, 0);
- gcs().send_text(MAV_SEVERITY_INFO, "Passthru disabled");
- } else if (enabled &&
- _passthru.timeout_s &&
- now - _passthru.last_port1_data_ms > uint32_t(_passthru.timeout_s)*1000U) {
- // timed out, disable
- _passthru.enabled = false;
- _passthru.port1->lock_port(0, 0);
- _passthru.port2->lock_port(0, 0);
- AP::serialmanager().disable_passthru();
- gcs().send_text(MAV_SEVERITY_INFO, "Passthru timed out");
- }
- }
- /*
- called at 1kHz to handle pass-thru between SERIA0_PASSTHRU port and hal.console
- */
- void GCS::passthru_timer(void)
- {
- WITH_SEMAPHORE(_passthru.sem);
- if (!_passthru.enabled) {
- // it has been disabled after starting
- return;
- }
- if (_passthru.start_ms != 0) {
- uint32_t now = AP_HAL::millis();
- if (now - _passthru.start_ms < 1000) {
- // delay for 1s so the reply for the SERIAL0_PASSTHRU param set can be seen by GCS
- return;
- }
- _passthru.start_ms = 0;
- }
- // while pass-thru is enabled lock both ports. They remain
- // locked until disabled again, or reboot
- const uint32_t lock_key = 0x3256AB9F;
- _passthru.port1->lock_port(lock_key, lock_key);
- _passthru.port2->lock_port(lock_key, lock_key);
- int16_t b;
- uint8_t buf[64];
- uint8_t nbytes = 0;
- // read from port1, and write to port2
- while (nbytes < sizeof(buf) && (b = _passthru.port1->read_locked(lock_key)) >= 0) {
- buf[nbytes++] = b;
- }
- if (nbytes > 0) {
- _passthru.last_port1_data_ms = AP_HAL::millis();
- _passthru.port2->write_locked(buf, nbytes, lock_key);
- }
- // read from port2, and write to port1
- nbytes = 0;
- while (nbytes < sizeof(buf) && (b = _passthru.port2->read_locked(lock_key)) >= 0) {
- buf[nbytes++] = b;
- }
- if (nbytes > 0) {
- _passthru.port1->write_locked(buf, nbytes, lock_key);
- }
- }
- bool GCS_MAVLINK::mavlink_coordinate_frame_to_location_alt_frame(const MAV_FRAME coordinate_frame, Location::AltFrame &frame)
- {
- switch (coordinate_frame) {
- case MAV_FRAME_GLOBAL_RELATIVE_ALT: // solo shot manager incorrectly sends RELATIVE_ALT instead of RELATIVE_ALT_INT
- case MAV_FRAME_GLOBAL_RELATIVE_ALT_INT:
- frame = Location::AltFrame::ABOVE_HOME;
- return true;
- case MAV_FRAME_GLOBAL_TERRAIN_ALT:
- case MAV_FRAME_GLOBAL_TERRAIN_ALT_INT:
- frame = Location::AltFrame::ABOVE_TERRAIN;
- return true;
- case MAV_FRAME_GLOBAL:
- case MAV_FRAME_GLOBAL_INT:
- frame = Location::AltFrame::ABSOLUTE;
- return true;
- default:
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- gcs().send_text(MAV_SEVERITY_INFO, "Unknown mavlink coordinate frame %u", coordinate_frame);
- #endif
- return false;
- }
- }
- uint64_t GCS_MAVLINK::capabilities() const
- {
- uint64_t ret = 0;
- AP_SerialManager::SerialProtocol mavlink_protocol = AP::serialmanager().get_mavlink_protocol(chan);
- if (mavlink_protocol == AP_SerialManager::SerialProtocol_MAVLink2) {
- ret |= MAV_PROTOCOL_CAPABILITY_MAVLINK2;
- }
- AP_AdvancedFailsafe *failsafe = get_advanced_failsafe();
- if (failsafe != nullptr && failsafe->enabled()) {
- // Copter and Sub may also set this bit as they can always terminate
- ret |= MAV_PROTOCOL_CAPABILITY_FLIGHT_TERMINATION;
- }
- if (AP::rally()) {
- ret |= MAV_PROTOCOL_CAPABILITY_MISSION_RALLY;
- }
- return ret;
- }
- void GCS_MAVLINK::manual_override(RC_Channel *c, int16_t value_in, const uint16_t offset, const float scaler, const uint32_t tnow, const bool reversed)
- {
- if (c == nullptr) {
- return;
- }
- int16_t override_value = 0;
- if (value_in != INT16_MAX) {
- const int16_t radio_min = c->get_radio_min();
- const int16_t radio_max = c->get_radio_max();
- if (reversed) {
- value_in *= -1;
- }
- override_value = radio_min + (radio_max - radio_min) * (value_in + offset) / scaler;
- }
- c->set_override(override_value, tnow);
- }
- uint8_t GCS_MAVLINK::get_battery_remaining_percentage(uint8_t instance) const {
- const AP_BattMonitor &battery = AP::battery();
- return battery.capacity_remaining_pct(instance);
- }
- GCS &gcs()
- {
- return *GCS::get_singleton();
- }
|