SDK

SDK Parrot

__Inleiding__
In ons project gaan we gebruik maken van de SDK die Parrot heeft geschreven om de AR Drone te laten vliegen met een computer, door middel van het toetsenbord. Bij deze code gaan wij onze eigen code voor beeldverwerking bijvoegen, zodat deze parallel loopt met de code van Parrot. Hierdoor zal de AR Drone kunnen vliegen aan de hand van de beelden die worden ontvangen. Deze wikipagina wordt geschreven tijdens het doornemen van de code van Parrot om een aantal zaken te verduidelijken zoals het doel van de belangrijkste C-files en hoe de globale structuur van het programma in elkaar zit.

__Threads__
In de code is gebruik gemaakt van THREADS. Een thread is een proces dat parallel kan lopen met andere processen. Zo worden er in de SDK 4 threads gebruikt die parallel draaien. (Vergelijk het met 4 main functies die parallel draaien)
 * navdata_update
 * ardrone_control
 * video_stage
 * directx_renderer_thread

navdata_update
in ardrone_navdata_client.c: Deze thread ontvangt navigatiedata van de AR Drone, zoals: hoogte,batterijlevel,jaw,... Wordt opgestart door 'ardrone_tool_init'in ardrone_tool.c, die wordt opgeroepen door de main in dezelfde file. De prioriteit = 0 en dus de hoogste

ardrone_control
Deze thread verstuurd data naar de AR Drone, zoals: omhoog,omlaag,landen,vooruit,... Wordt opgestart door 'ardrone_tool_init'in ardrone_tool.c, die wordt opgeroepen door de main in dezelfde file. De prioriteit = 0 en dus de hoogste

video_stage
in video_stage.c: Wordt opgestart door 'ardrone_tool_init_custom' in custom_code.c, die wordt opgeroepen door de main in ardrone_tool.c. Deze thread decodeert de ontvangen videostream. De thread initialiseert en runt een pipeline in een lus die in stages verschillende stappen uitvoert. De thread roept elke keer als het een frame ontvangen heeft van de drone, de functie 'output_rendering_device_stage_transform' op (deze is opgenomen in de pipeline) waarbij een van de argumenten de framebuffer is. In deze functie kunnen we later een beelverwerkingsalgoritme toevoegen. In het SDK example worden de beelden in deze functie eenvoudigweg aan de video rendering module (directx) doorgegeven die ze afbeeld op het scherm.

directx_renderer_thread
in directx_rendering.cpp Wordt opgestart door 'ardrone_tool_init_custom' in custom_code.c, die wordt opgeroepen door de main in ardrone_tool.c. Deze thread rendert de video scene met als input RGB video afbeeldingen afkomstig van de video_stage thread.

__Ontvangen navdata verwerken__
- navdata handler functies in navdata.c

Deze functies zijn callback functies die worden opgeroepen door de ardronetool library telkens als er nieuwe navdata ontvangen wordt. De functies staan gedeclareerd in een navdata handler table (deze is onderaan navdata.c opgenomen). Er zijn 3 fucnties: demo_navdata_client_init, (voor de initialisatie van de handler) demo_navdata_client_process, (voor de verwerking tijdens het programma) demo_navdata_client_release (voor het opruimen van de handler bij het afsluiten) De process functie krijgt de uitgepakte navdata als argument mee.

__Drone control functions__
In gamepad.cpp worden de control functies opgeroepen in het example, afhankelijk van de bediende controller hardware. De functies zijn gedefinieerd in ardrone_at.c. Deze functies plaatsen een AT commando in de AT message queue die vervolgens naar de drone verzonden wordt.

- ardrone_tool_set_ui_pad_start(takeoff flag) laat de drone opstijgen (takeoff flag = 1) of landen (takeoff flag = 0) - ardrone_tool_set_ui_pad_select(emergency flag) verzend een emergency signaal (emergency flag = 1) verzend een herstel van emergency signaal (emergency flag = 0) NOTA: deze functie wordt in de code meestal vooragegaan door een: ardrone_tool_set_ui_pad_start(0) call - ardrone_at_set_progress_cmd(int flags, float phi : Left/right angle float theta : Front/back angle float gaz : Vertical speed float yaw : Angular speed ) laat de drone een bepaalde beweging uitvoeren (zie p18 van de developers guide voor meer info) met deze functie kan men ook de hoovering mode instellen

NOTA: Er zijn nog tal van andere functies zoals led animation etc...

Elke thread kan ook zijn eigen prioriteit krijgen. Ook moeten de threads beschreven worden in een THREAD_TABLE dit gebeurt in **vp_api_thread_helper.h**. Wij zullen onze eigen thread maken die zorgt voor de beeldverwerking. Deze moeten we dan ook toevoegen aan de THREAD_TABLE. code BEGIN_THREAD_TABLE THREAD_TABLE_ENTRY( eigen_thread, 20 ) // For your own application THREAD_TABLE_ENTRY( navdata_update, 20 ) //Mandatory THREAD_TABLE_ENTRY( ardrone_control, 20 ) //Mandatory END_THREAD_TABLE code Alle threads moeten opgestart en afgesloten worden. Dit doe je met: code /* Start all threads of your application */ START_THREAD( directx_renderer_thread, NULL); START_THREAD( video_stage, NULL ); START_THREAD( ardrone_control,NULL); START_THREAD( navdata_update,NULL); START_THREAD( eigen_thread, NULL );

/* Stop all threads of your application */ JOIN_THREAD(directx_renderer_thread); JOIN_THREAD(video_stage); JOIN_THREAD(eigen_thread); JOIN_THREAD(ardrone_control); JOIN_THREAD(navdata_update);

code Meer uitleg over Pthread, en hoe threads te gebruiken: > >
 * [] (wiki over Pthread)
 * [] (tutorial over Pthread)
 * [] (parallelle processen in C)

__Uitleg C-file__

 * ardrone_tool_win32.c
 * custom_code.c
 * directx_rendering.cpp
 * gamepad.cpp
 * navdata.c
 * video_stage.c

gamepad.cpp
Hierin staat een functie waarmee de toetsen van het keyboard worden ingelezen. Deze kan je aanpassen wanneer je de Drone met andere toetsen wil besturen.

__Controls aanpassen__
Hierbij een korte uitleg hoe je de besturing via het toetsenbord kan aanpassen naar eigen behoeften. Hiervoor moet je in de volgende file werken: **gamepad.cpp** De controls kan je in volgende functie aanpassen: code C_RESULT update_dx_keyboard(void) code Volgende stukken code kunnen dan aangepast worden: code // Process the keyboard data

#define EVENTKB(I)     ( keyboardState[I] != previous_keyboardState[I] ) #define TESTKB(I)      ( keyboardState[I] & 0x80 ) #define SETKB(I,J)     if( keyboardState[I] & 0x80 )  J(1); else J(0);

/*VOORUIT / ACHTERUIT */ pitch = //(TESTKB(DIK_NUMPAD2))? (+1.0f) : (TESTKB(DIK_NUMPAD8))? (-1.0f) : //(TESTKB(DIK_K))? (+1.0f)      : (TESTKB(DIK_I))? (-1.0f)           :(0.0f) ; (TESTKB(DIK_DOWN))? (+1.0f)      : (TESTKB(DIK_UP))? (-1.0f)           :(0.0f) ;//DH

/* LINKS / RECHTS */ roll = //(TESTKB(DIK_NUMPAD4))? (-1.0f) : (TESTKB(DIK_NUMPAD6))? (+1.0f) : //(TESTKB(DIK_J))? (-1.0f)      : (TESTKB(DIK_L))? (+1.0f)       : (0.0f) ; (TESTKB(DIK_LEFT))? (-1.0f)      : (TESTKB(DIK_RIGHT))? (+1.0f)       : (0.0f) ;//DH

/* DRAAIEN ROND AS */ yaw  = //(TESTKB(DIK_NUMPAD7))? (-1.0f) : (TESTKB(DIK_NUMPAD9))? (+1.0f) : //(TESTKB(DIK_NUMPAD3))? (-1.0f) : (TESTKB(DIK_NUMPAD1))? (+1.0f) : //(TESTKB(DIK_U))? (-1.0f)      : (TESTKB(DIK_O))? (+1.0f) : (0.0f) ; (TESTKB(DIK_NUMPAD4))? (-1.0f) : (TESTKB(DIK_NUMPAD6))? (+1.0f) :       //DH (TESTKB(DIK_W))? (-1.0f)      : (TESTKB(DIK_X))? (+1.0f) : (0.0f) ;    //DH

/* OMHOOG / OMLAAG */ gaz  = (TESTKB(DIK_NUMPAD2))? (-1.0f) : (TESTKB(DIK_NUMPAD8))? (+1.0f) :       //DH (TESTKB(DIK_A))? (-1.0f)      : (TESTKB(DIK_Q))? (1.0f) : (0.0f) ;

hovering = (TESTKB(DIK_G))? (1):(0) ;

keyboard_in_use = !((pitch+roll+gaz+yaw)==0);

if (EVENTKB(DIK_ESCAPE)) { if (TESTKB(DIK_ESCAPE)) {               exit_ihm_program=0; }   }

if (EVENTKB(DIK_TAB)) { if (TESTKB(DIK_TAB)) {               ardrone_tool_set_ui_pad_start(0); ardrone_tool_set_ui_pad_select(1); printf("Sending emergency.%s\n",linefiller); }       else {                   ardrone_tool_set_ui_pad_select(0); }   }

if (EVENTKB(DIK_SPACE) && TESTKB(DIK_SPACE)) {           start^=1; ardrone_tool_set_ui_pad_start(start); printf("Sending start %i.%s\n",start,linefiller); }

if (EVENTKB(DIK_F) && TESTKB(DIK_F)) {           ardrone_at_set_flat_trim; printf("Sending flat trim.%s\n",linefiller); } code

Nu kan je sturen met de pijltjes van het keyboard, rond de as draaien met **4** en **6**, stijgen en dalen met **8** en **2**. Opstijgen en landen gebeurt met de **spatie** en een emergency gebeurt met **escape** of **tab**.

Een lijst met alle codes van het toetsenbord vind je [|hier].

Achter elke lijn code die ik aanpas zet ik de initialen DH. Zo kan ik snel terug vinden wat ik heb aangepast.  //Process the keyboard data//

 //#define EVENTKB(I) ( keyboardState[I] != previous_keyboardState[I] )//  //#define TESTKB(I) ( keyboardState[I] & 0x80 )//  //#define SETKB(I,J) if( keyboardState[I] & 0x80 ) J(1); else J(0);//

 ///*VOORUIT / ACHTERUIT *///  //pitch =// (TESTKB(DIK_NUMPAD2))? (+1.0f) : (TESTKB(DIK_NUMPAD8))? (-1.0f) :  //(TESTKB(DIK_K))? (+1.0f) : (TESTKB(DIK_I))? (-1.0f) :(0.0f) ;//  //(TESTKB(DIK_DOWN))? (+1.0f) : (TESTKB(DIK_UP))? (-1.0f) :(0.0f) ;//DH

 /* LINKS / RECHTS */  roll = //(TESTKB(DIK_NUMPAD4))? (-1.0f) : (TESTKB(DIK_NUMPAD6))? (+1.0f) ://  (TESTKB(DIK_J))? (-1.0f) : (TESTKB(DIK_L))? (+1.0f) : (0.0f) ;  (TESTKB(DIK_LEFT))? (-1.0f) : (TESTKB(DIK_RIGHT))? (+1.0f) : (0.0f) ;//DH//

 ///* DRAAIEN ROND AS *///  //yaw =// (TESTKB(DIK_NUMPAD7))? (-1.0f) : (TESTKB(DIK_NUMPAD9))? (+1.0f) :  //(TESTKB(DIK_NUMPAD3))? (-1.0f) : (TESTKB(DIK_NUMPAD1))? (+1.0f) ://  (TESTKB(DIK_U))? (-1.0f) : (TESTKB(DIK_O))? (+1.0f) : (0.0f) ; <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> (TESTKB(DIK_NUMPAD4))? (-1.0f) : (TESTKB(DIK_NUMPAD6))? (+1.0f) : //DH// <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> //(TESTKB(DIK_W))? (-1.0f) : (TESTKB(DIK_X))? (+1.0f) : (0.0f) ;// DH

<span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> /* OMHOOG / OMLAAG */ <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> gaz = (TESTKB(DIK_NUMPAD2))? (-1.0f) : (TESTKB(DIK_NUMPAD8))? (+1.0f) : //DH <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> (TESTKB(DIK_A))? (-1.0f) : (TESTKB(DIK_Q))? (1.0f) : (0.0f) ;

<span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> hovering = (TESTKB(DIK_G))? (1):(0) ;

<span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> keyboard_in_use = !((pitch+roll+gaz+yaw)==0);

<span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> if (EVENTKB(DIK_ESCAPE)) { <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> if (TESTKB(DIK_ESCAPE)) <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> { <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> exit_ihm_program=0; <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> } <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> }

<span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> if (EVENTKB(DIK_TAB)) { <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> if (TESTKB(DIK_TAB)) <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> { <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> ardrone_tool_set_ui_pad_start(0); <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> ardrone_tool_set_ui_pad_select(1); <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> printf("Sending emergency.%s\n",linefiller); <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> } <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> else <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> { <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> ardrone_tool_set_ui_pad_select(0); <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> } <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> }

<span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> if (EVENTKB(DIK_SPACE) && TESTKB(DIK_SPACE)) <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> { <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> start^=1; <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> ardrone_tool_set_ui_pad_start(start); <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> printf("Sending start %i.%s\n",start,linefiller); <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> }

<span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> if (EVENTKB(DIK_F) && TESTKB(DIK_F)) <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> { <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> ardrone_at_set_flat_trim; <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> printf("Sending flat trim.%s\n",linefiller); <span style="display: block; height: 1px; left: -10000px; overflow: hidden; position: absolute; top: 1222px; width: 1px;"> }