{"id":19686193,"url":"https://github.com/berlingoqc/scdrone","last_synced_at":"2026-05-15T19:33:13.171Z","repository":{"id":93505740,"uuid":"155936234","full_name":"berlingoqc/SCDrone","owner":"berlingoqc","description":"Self Control Drone : sdk et application pour contrôler automatiquement un ARDrone avec OpenCV dans un environnement prédéfinis","archived":false,"fork":false,"pushed_at":"2018-12-13T19:38:43.000Z","size":1270,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-27T08:55:41.696Z","etag":null,"topics":["automation","c-plus-plus-17","drone","opencv","tracking"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/berlingoqc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-03T00:44:29.000Z","updated_at":"2018-12-13T16:32:52.000Z","dependencies_parsed_at":"2023-03-05T08:45:24.235Z","dependency_job_id":null,"html_url":"https://github.com/berlingoqc/SCDrone","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/berlingoqc/SCDrone","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berlingoqc%2FSCDrone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berlingoqc%2FSCDrone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berlingoqc%2FSCDrone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berlingoqc%2FSCDrone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/berlingoqc","download_url":"https://codeload.github.com/berlingoqc/SCDrone/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berlingoqc%2FSCDrone/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33076204,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T11:35:32.926Z","status":"ssl_error","status_checked_at":"2026-05-15T11:35:31.362Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","c-plus-plus-17","drone","opencv","tracking"],"created_at":"2024-11-11T18:26:38.545Z","updated_at":"2026-05-15T19:33:13.155Z","avatar_url":"https://github.com/berlingoqc.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SCDrone : Self-Control Drone\n\nProjet final dans le cadre de notre cours de Vision dans le programme d'informatique industrielle du Cégep de Lévis-Lauzon.\n\n- [SCDrone : Self-Control Drone](#scdrone--self-control-drone)\n  - [Objectif](#objectif)\n  - [Technologie utilisé](#technologie-utilis%C3%A9)\n  - [Implémentation du SDK du ARDrone 2.0](#impl%C3%A9mentation-du-sdk-du-ardrone-20)\n    - [Mes classes de bases](#mes-classes-de-bases)\n    - [Thread AT](#thread-at)\n    - [Thread NavData](#thread-navdata)\n    - [Thread Control](#thread-control)\n    - [Thread Video](#thread-video)\n    - [Utilisation des la librairie de controler pour crée une application](#utilisation-des-la-librairie-de-controler-pour-cr%C3%A9e-une-application)\n  - [Ardrone GUI](#ardrone-gui)\n  - [Qu'es-ce qu'on n'a implémenter finalement avec le drone ?](#ques-ce-quon-na-impl%C3%A9menter-finalement-avec-le-drone)\n    - [Design a prendre](#design-a-prendre)\n\n## Objectif\n\nCrée une application en c++ avec OpenCV qui controlera automatiquement un drone (AR Drone 2.0) dans un cas et environnement prédéfinis par l'application.\n\nExemple d'appliction possible :\n\n* Voler dans un parcours avec des boîtes a esquiver et des anneaux a traverser pour attérir sur une cible d'hélicoptère\n* Identifier une cible comme une personne ou un signe et le suivre à une distance prédéterminer\n* Mapper une environnement et s'y déplacer automatiquement pour détecter des intrus ( comme un agent de sécurité )\n\nAucune application n'est définit pour l'instant mais pour les accomplirs la même base doit être crée avec le drone pour executer l'application.\n\nLe drone fournit par l'école est un AR Drone 2.0 qui vient avec un SDK fournit par la compagnie Parrot.\nMais pour des raisons de plaisirs et compatibilité nous avons décider de réecrire le SDK en c++ moderne.\nPour ce faire nous avons comme références :\n\n* [SDK Parrot](\"http://developer.parrot.com/docs/SDK2\") :  lien pour télécharger le code source\n* [Documentation SDK Parrot](https://drive.google.com/open?id=13GH4rXcP_LP_JtIrr1bc2artrZ25EUrx) : documentation du drone\n* [Port du SDK en C# et C++/cli](https://github.com/ARDrone2Windows/SDK) : le github d'un projet en C# qui a réimplémenter le sdk \n\n## Technologie utilisé \n\nLes technologies suivantes sont utilisé par au moins une composante : \n\n* [C++17](https://en.wikipedia.org/wiki/C%2B%2B11) : nous utilisons c++17 car nous roulons exculisvement sur des compilateurs récent et je voulais utilisé std::filesystem\n* [Qt](https://www.qt.io/developers/) : nous allons utilisé boost pour les composantes suivantes :\n    * QNetwork   : pour communication TCP et UDP (j'aimerais crisser ca la)\n* [OpenCV 3.4.3](https://docs.opencv.org/3.4.3/) : pour le traitement d'image et nous allons utilisé les fonctionnalités cuda et contrib pour le tracking et la détection d'object.\n* [FFMPEG](https://www.ffmpeg.org/documentation.html) : utiliser pour faire le decoding du flux video depuis le drone\n* [CMake](https://cmake.org/documentation/) : comme système de build pour le projet\n* [GLEW](https://github.com/catchorg/Catch2) : Systeme pour charger le context OpenGL\n* [GLFW](https://github.com/) : Systeme pour gerer les fenetres et les inputs\n* [ASIO](https://github.com/) : Librairie pour le networking\n* [STL](www.cppreferences.com) : Utiliser les fonctions de la STL pour les thread et pour gerer le file system.\n\nCe choix de librairie permet à notre sdk et notre application d'être compilé sur toute les plateformes majeurs\nsans problème sauf pour la dépendence à cuda qui coupe la possiblité d'être executer sur rasberry pi, android,\nmingw parmis tant d'autre. Mais va nous permettre j'imagine d'avoir un gain de performance pour réduire le délais\nde controle du drone.\n\n## Implémentation du SDK du ARDrone 2.0\n\nLa première partit à compléter pour pouvoir accomplir le projet est d'implémenter notre SDK qui ressemble grosso-modo à :\n\n* Thread AT : thread qui s'occupe d'envoyer les commandes de contrôle et de configuration au drone\n* Thread NavData : thread qui s'occupe de la réception des informations de pilotage du drone\n* Thread Control : thread qui s'occupe de la réception des informations de configuration du drone\n* Thread Video : thread qui s'occupe de la réception du flux vidéo du drone\n\nEt dans cette ensemble de thread viennent s'ajouter les threads de l'application qui serait :\n* Thread Staging : thread qui s'occupe de la conversion du flux vidéo vers le format désirer pour l'application\n* Thread App : thread qui recoit les informations de pilotages et vidéos et qui envoie des commandes pour ajuster\n\n![Diagram](ressources/sdk_fonctionnement.png)\n\n\n### Mes classes de bases\n\n\n```c++\n\n\nclass Runnable {\nprotected:\n    std::promise\u003cvoid\u003e\texitSignal;\n    std::future\u003cvoid\u003e\tfutureObject;\n\n    std::atomic\u003cbool\u003e\tstate = false;\n\npublic:\n    virtual ~Runnable() = default;\n    Runnable() :futureObject(exitSignal.get_future()) {}\n    Runnable(Runnable \u0026\u0026 obj) : exitSignal(std::move(obj.exitSignal)), futureObject(std::move(obj.futureObject)) {\n        std::cout \u003c\u003c \"Move Constructor called\" \u003c\u003c std::endl;\n    }\n    Runnable \u0026 operator=(Runnable \u0026\u0026 obj) {\n        std::cout \u003c\u003c \"Move assignment is called\" \u003c\u003c std::endl;\n        exitSignal = std::move(obj.exitSignal);\n        futureObject = std::move(obj.futureObject);\n        return *this;\n    }\n\n    // les classes enfants doivent donn� une d�finition\n    virtual void run_service() = 0;\n\n    // La fonction thread a executer\n    std::thread start() {\n        return std::thread([this] { this-\u003erun_service(); });\n    }\n\n    bool stopRequested() const\n    {\n        return !(futureObject.wait_for(0ms) == std::future_status::timeout);\n    }\n\n    virtual void stop() {\n        exitSignal.set_value();\n    }\n\n    bool isRunning()\n    {\n        return state;\n    }\n\n};\n\ntemplate\u003ctypename dataType\u003e\nclass ConcurrentQueue {\nprivate:\n    std::queue\u003cdataType\u003e\tqueue;\n    std::mutex\t\t\t\tmutex;\n\n    std::condition_variable cv;\n\n    std::atomic\u003cbool\u003e\t\tforceExit = false;\n\npublic:\n\n    dataType\u0026 pop()\n    {\n        std::unique_lock\u003cstd::mutex\u003e lk(mutex);\n        cv.wait(lk, [this] { return !queue.empty(); }); // Attend que la queue ne soit plus vide et utiliser\n        dataType\u0026 f = queue.front();\n        queue.pop();\n        return f;\n    }\n\n    dataType pop2() {\n        std::unique_lock\u003cstd::mutex\u003e lk(mutex);\n        cv.wait(lk, [this] { return !queue.empty(); }); // Attend que la queue ne soit plus vide et utiliser\n        dataType f = queue.front();\n        queue.pop();\n        return f;\n    }\n\n    dataType pop2_wait(std::chrono::milliseconds timeout, bool* has_data) {\n        std::unique_lock\u003cstd::mutex\u003e lk(mutex);\n        if (!cv.wait_for(lk, timeout, [this] { return !queue.empty(); }))\n        {\n            *has_data = false;\n            return dataType();\n        }\n        *has_data = true;\n        dataType f = queue.front();\n        queue.pop();\n        return f;\n    }\n\n    dataType pop_wait(std::chrono::milliseconds timeout,bool* has_data)\n    {\n        std::unique_lock\u003cstd::mutex\u003e lk(mutex);\n        if(!cv.wait_for(lk, timeout, [this] { return !queue.empty(); }))\n        {\n            *has_data = false;\n            return dataType();\n        }\n        *has_data = true;\n        dataType f = queue.front();\n        queue.pop();\n        return f;\n    }\n\n    dataType* pop_all_wait(std::chrono::milliseconds timeout,int* nbrElement)\n    {\n        std::unique_lock\u003cstd::mutex\u003e lk(mutex);\n        if (!cv.wait_for(lk, timeout, [this] { return !queue.empty(); }))\n        {\n            *nbrElement = 0;\n            return nullptr;\n        }\n        *nbrElement = queue.size();\n        dataType* d = new dataType[*nbrElement];\n        for(int i =0; i\u003c*nbrElement;i++)\n        {\n            d[i] = queue.front();\n            queue.pop();\n        }\n        return d;\n\n    }\n\n    void push(dataType const\u0026 data) {\n        forceExit.store(false);\n        std::unique_lock\u003cstd::mutex\u003e lk(mutex);\n        queue.push(data);\n        lk.unlock();\n        cv.notify_one();\n    }\n\n    void empty()\n    {\n        std::unique_lock\u003cstd::mutex\u003e lk(mutex);\n        for(int i = 0; i \u003c queue.size(); i++)\n        {\n            queue.pop();\n        }\n        lk.unlock();\n    }\n\n    bool isEmpty() {\n        std::unique_lock\u003cstd::mutex\u003e lk(mutex);\n        return queue.empty();\n    }\n\n};\n\n\n\n```\n\n\n### Thread AT\n\nThread qui s'occupe de l'envoi des trames de contrôles au drone. Pour que le drone soit controller fluidement\nl'interval entre les messages envoier doit être de 30ms.\n\nC'est cette thread qui controle l'etats du drone ( s'il est en vole  , arrêter ou en mode urgence ). Et qui envoie\ndes les messages de configuration du drone.\n\nIl y a plusieurs facons d'utiliser la thread AT :\n\n* Avec la Queue de message\n* En utilisant directement les variables atomiques pour controler ce qui le drone fait quand il ne recoit pas de message\n... de la queue\n* En utilisant la classe DroneControle qui est un wrapper autour de la Queue avec des taches async pour envoyer constament un message jusqu'a l'arreter de la tache\n\n```c++\nclass ATClient : public QObject, public Runnable\n{\n\tATQueue* queue;\n\n\tQUdpSocket* socket;\n\tQHostAddress* sender;\n\tquint16 port;\n\n\tstd::atomic\u003cref_flags\u003e\t\t\tref_mode;\n\tstd::atomic\u003cprogressive_flags\u003e\tprog_flag;\n\tstd::atomic\u003cspeed\u003e\t\t\t\tspeed_drone;\n\n\tint sequence_nbr;\n\npublic:\n\tATClient(ATQueue* queue,QObject* parent = 0);\n\t~ATClient();\n\t\n\tvoid setVector2D(float x, float y);\n\n    void setSpeedX(x_direction d, float x);\n\tvoid setSpeedY(y_direction d, float y);\n\tvoid setSpeedZ(z_direction d, float z);\n\tvoid setSpeedR(x_direction d, float r);\n\n\tvoid hover();\n\n\tvoid setProgressiveFlag(progressive_flags f)\n\t{\n\t\tprog_flag = f;\n\t}\n\n\tspeed getSpeed() const\n\t{\n\t\treturn speed_drone;\n\t}\n\tprogressive_flags getProgressiveFlag() const\n\t{\n\t\treturn prog_flag;\n\t}\n\n\tvoid set_ref(ref_flags f);\n\n\tconst char* get_ref() const\n\t{\n\t\tref_flags f = ref_mode;\n\t\tswitch(f)\n\t\t{\n\t\tcase EMERGENCY_FLAG:\n\t\t\treturn \"EMERGENCY\";\n\t\tcase TAKEOFF_FLAG:\n\t\t\treturn \"FLYING\";\n\t\tdefault:\n\t\t\treturn \"LANDED\";\n\t\t}\n\t\t\n\t}\n\n\npublic slots:\n\tvoid run_service();\n\nprivate slots:\n\tvoid on_read_ready();\n};\n\n```\n\n\n### Thread NavData\n\nThread qui recoit les messages suivants d'information de navigation. Il y a plusieurs informations possibles de recevoir mais nous utilisions le message\nde base qui contient toute les informations que nous avons besoin\n\n\n```c++\n\n#define NAVDATA_HEADER                  0x55667788\n\n#define NAVDATA_MAX_SIZE                4096\n#define NAVDATA_MAX_CUSTOM_TIME_SAVE    20\n\n\ntypedef struct _navdata_option_t {\n    uint16_t    tag;   // Tag pour l'option spécifique\n    uint16_t    size;  // Longeur de la structure\n\n    uint8_t     data[];\n} navdata_option_t;\n\n\ntypedef struct _navdata_t {\n    uint32_t    header;\n    uint32_t    ardrone_state;\n    uint32_t    sequence;\n    bool_t      vision_defined;\n\n\tnavdata_option_t* options;\n} navdata_t;\n\n/**\n * @brief Minimal navigation data for all flights.\n */\ntypedef struct _navdata_demo_t {\n  uint16_t    tag;\t\t\t\t\t  /*!\u003c Navdata block ('option') identifier */\n  uint16_t    size;\t\t\t\t\t  /*!\u003c set this to the size of this structure */\n\n  uint32_t    ctrl_state;             /*!\u003c Flying state (landed, flying, hovering, etc.) defined in CTRL_STATES enum. */\n  uint32_t    vbat_flying_percentage; /*!\u003c battery voltage filtered (mV) */\n\n  float   theta;                  /*!\u003c UAV's pitch in milli-degrees */\n  float   phi;                    /*!\u003c UAV's roll  in milli-degrees */\n  float   psi;                    /*!\u003c UAV's yaw   in milli-degrees */\n\n  int32_t     altitude;               /*!\u003c UAV's altitude in centimeters */\n\n  float   vx;                     /*!\u003c UAV's estimated linear velocity */\n  float   vy;                     /*!\u003c UAV's estimated linear velocity */\n  float   vz;                     /*!\u003c UAV's estimated linear velocity */\n\n  uint32_t    num_frames;\t\t\t  /*!\u003c streamed frame index */ // Not used -\u003e To integrate in video stage.\n\n  // Camera parameters compute by detection\n  matrix33_t  detection_camera_rot;   /*!\u003c  Deprecated ! Don't use ! */\n  vector31_t  detection_camera_trans; /*!\u003c  Deprecated ! Don't use ! */\n  uint32_t\t  detection_tag_index;    /*!\u003c  Deprecated ! Don't use ! */\n\n  uint32_t\t  detection_camera_type;  /*!\u003c  Type of tag searched in detection */\n\n  // Camera parameters compute by drone\n  matrix33_t  drone_camera_rot;\t\t  /*!\u003c  Deprecated ! Don't use ! */\n  vector31_t  drone_camera_trans;\t  /*!\u003c  Deprecated ! Don't use ! */\n} navdata_demo_t;\n\n```\n\nVu la simpliciter de cette thread, le nombre de message que nous recevons est beaucoup trop volumineux pour nos besoin. Donc au lieu d'utiliser\nune queue pour echanger les informations, j'utilise une variable atomique qui contient le plus récent message.\n\nIl aurra pu être interessent d'implementer un systeme pour voire la variation des différentes variables sur une temps prédéfinit ou demander sur le fly.\nPour rentabiliser la thread et permettre d'avoir des informations de vol appronfondie.\n\n\n### Thread Control\n\nPas implémenter dans l'application pour le moment.\n\n### Thread Video\n\nLe flux vidéo utilisé par le drone est H264 ( MPEG4.10 AVC ) et il peut être configuré avec les options suivantes :\n\n* FPS : entre 15 et 30\n* Bitrate : entre 250kbps et 4Mbps\n* Résolution : 360p (640x360) ou 720p (1280x720)\n\nLes structures et les définitions du flux vidéo sont définit dans libardrone/include/video_common.h\nEt ce qu'il en résulte comme flux vidéo une fois reconstruit est la structure suivante qui représente une frame :\n\n```c++\nstruct VideoPacket\n{\n\tlong Timestamp;\n\tlong Duration;\n\tunsigned int FrameNumber;\n\tunsigned short Height;\n\tunsigned short Width;\n\tframe_type_t FrameType;\n\tARBuffer Buffer;\n}\n```\nLes frames sont de deux type : IDR-Frame ( une frame complète de référence ) et les P-Frame ( frame d'update ).\n\n```c++\n\nclass VideoStaging : public Runnable\n{\n\tvideo_encapsulation_t\t\tprev_encapsulation_ = {}; // Dernier header PaVE re�u\n\n\tAVPixelFormat\t\t\t\tformat_in;\t\t\t\t\t// Format pixel du flux video\n\tAVPixelFormat\t\t\t\tformat_out;\t\t\t\t\t// Format pixel de l'image de sortit pour OpenCV\n\tint\t\t\t\t\t\t\tdisplay_width;\t\t\t\t// Largeur de l'image dans le stream\n\tint\t\t\t\t\t\t\tdisplay_height;\t\t\t\t// Hauteur de l'image dans le stream\n\tint\t\t\t\t\t\t\tbit_rate;\t\t\t\t\t// Bit-rate du stream re�u\n\tint\t\t\t\t\t\t\tfps;\t\t\t\t\t\t// FPS du stream re�u\n\n#ifdef DEBUG_VIDEO_STAGING\n\tint\t\t\t\t\t\t\t\tframe_lost = 0;\n\tTimePoint\t\t\t\t\t\tstart_gap;\n\tTimePoint\t\t\t\t\t\tend_gap;\n\tTimePoint\t\t\t\t\t\tlast_start;\n\tTimePoint\t\t\t\t\t\tlast_end;\n\tstd::vector\u003clong\u003e\t\t\t\ttimes;\n#endif\n\tAVCodec*\t\t\t\t\tcodec;\t\t\t\t\t\t// Contient les informations du codec qu'on utilise (H264)\n\tAVCodecContext*\t\t\t\tcodec_ctx;\t\t\t\t\t// Contient le context de notre codec ( information sur comment decoder le stream )\n\tAVCodecParserContext*\t\tcodec_parser;\t\t\t\t// Contient le context sur comment parser les frame de notre stream\n\n\n\tAVFrame*\t\t\t\t\tframe;\t\t\t\t\t\t// Contient la derni�re frame qu'on na re�u a reconstruire de notre stream\n\tAVFrame*\t\t\t\t\tframe_output;\t\t\t\t// Contient la derni�re frame convertit dans le format pour l'envoyer a OpenCV\n\tAVPacket*\t\t\t\t\tpacket;\n\n\tPacketBuffer\u003cH264_INBUF_SIZE\u003e packet_buffer;\t\t\t// Structure qui contient mon buffer que je remplit pou avoir une frame\n\n\n\tint\t\t\t\t\t\t\tline_size;\n\n\tSwsContext*\t\t\t\t\timg_convert_ctx;\t\t\t// Contient le context pour effectuer la conversion entre notre image YUV420 et BGR pour OpenCV\n\n\tint\t\t\t\t\t\t\tfirst_frame;\t\t\t\t// Contient le num�ro de la premi�re frame re�u\n\tint\t\t\t\t\t\t\tlast_frame;\t\t\t\t\t// Contient le num�ro de la derni�re frame re�u\n\n\tbool\t\t\t\t\t\thave_received;\t\t\t\t// Indique si on n'a d�j� commencer a recevoir des trames\n\tbool\t\t\t\t\t\tonly_idr = true;\t\t\t// Indique si on souhaite selon parser les frames IDR et de skipper les frames P\n\n\tatomic\u003cbool\u003e\t\t\t\trecord_to_file_raw = false; // Indique si on souhaite sauvegarder le stream dans un fichier\n\n\tfs::path\t\t\t\t\trecord_folder = fs::path(\"./recording\");\t\t// Indique le chemin du fichier a sauvegarder le stream\n\tint\t\t\t\t\t\t\tstream_index = 0;\n\tstd::ofstream\t\t\t\tof;\n\n\tbool\t\t\t\t\t\tthread_mode = false;\n\tVFQueue*\t\t\t\t\tqueue;\t\t\t\t\t\t// La queue dans laquelle les frames sont recu  si on n'est en mode MultiThread Video\n\n\tMQueue*\t\t\t\t\t\tmqueue;                     // Queue pour envoyer les mat.\n\n\tstd::atomic\u003cvideo_staging_info\u003e staging_info;\n\t\n\npublic:\n\tVideoStaging(MQueue* mqueue);\n\tVideoStaging(VFQueue* queue, MQueue* mqueue);\n\t//VideoStaging(VFQueue* queue, const char* filepath);\n\t~VideoStaging();\n\n\tint\tinit() const;\n\n\tvoid run_service() override;\n\n\tvoid set_raw_recording(bool state);\n\n\tvoid onNewVideoFrame(VideoFrame\u0026 vf);\n\n\tvideo_staging_info getInfo()\n\t{\n\t\treturn staging_info;\n\t}\n\nprivate:\n\n\tbool have_frame_changed(const VideoFrame\u0026 vf);\n\tbool add_frame_buffer(const VideoFrame\u0026 vf);\n\tvoid init_or_frame_changed(const VideoFrame\u0026 vf,bool init = false);\n\tbool frame_to_mat(const AVFrame* avframe, cv::Mat\u0026 m);\n\tvoid append_file(const VideoFrame\u0026 vf);\n};\n\n```\n\n### Utilisation des la librairie de controler pour crée une application\n\nVoici la classe de base qu'on peut implémenter pour simplifier le démarrage d'une nouvelle\napplicaton avec le drone \n\n```c++\n/**\n * \\brief DroneClient is the mother class to create a application with the ARDrone\n */\nclass DroneClient {\nprotected:\n\t~DroneClient() = default;\n\n\tbool\t\t\t\tunited_video_thread;\n\n\tVFQueue\t\t\t\tvf_queue;\n\tMQueue\t\t\t\tmat_queue;\n\tATQueue\t\t\t\tat_queue;\n\tNAVQueue\t\t\tnav_queue;\n\n\tVideoStaging\t\tvideo_staging;\t\n\tVideoClient\t\t\tvideo_client;\n\tATClient\t\t\tat_client;\n\tNavDataClient\t\tnd_client;\n\tDroneControl\t\tcontrol;\nprivate:\n\tstd::thread\t\t\tvs_thread;\n\tstd::thread\t\t\tvc_thread;\n\tstd::thread\t\t\tat_thread;\n\tstd::thread\t\t\tnd_thread;\n\npublic:\n\tDroneClient();\n\tDroneClient(bool lol = true);\n\n\tint Start();\n\n\tbool isAllThreadRunning();\n\n\tvirtual void mainLoop() = 0;\nprotected:\n\n\tint init();\n\tint stop();\n\n};\n```\n\n\nPrograme d'exemple\n\n```c++\n\n#include \"drone_client.h\"\n\n\nclass DroneKB : public DroneClient\n{\npublic:\n\tvirtual ~DroneKB() = default;\n\n\tDroneKB() : last_mat(640,360,CV_8UC3,cv::Scalar(0,0,0)), presentation_mat(last_mat.clone())\n\t{\n\t\tnd = {};\n\t\tspeedXZ = 0.1f;\n\t\tspeedYR = 0.4f;\n\t}\n\nprivate:\n\n\tcv::Mat\t\t\t\t\tlast_mat;\n\tcv::Mat\t\t\t\t\tpresentation_mat;\n\n\tnavdata_demo_t\t\t\tnd;\n\n\n\tvoid mainLoop() override\n\t{\n\t\tcv::Mat m;\n\t\tconst char* wname = \"Drone video stream\";\n\t\tcv::namedWindow(wname);\n\n\t\tbool has_image = false;\n\t\tbool has_navdata = false;\n\n        // Demande de recevoir les navada_demo\n\t\tstring navconf = at_format_config(\"general:navdata_demo\", \"TRUE\");\n\t\tnavconf.append(at_format_ack());\n\t\tat_queue.push(navconf);\n\n\t\tfor (;;)\n\t\t{\n\t\t\tm = mat_queue.pop2_wait(100ms,\u0026has_image);\n\t\t\tnd = nd_client.get_last_nd_demo();\n\t\t\tif (has_image)\n\t\t\t\tlast_mat = m;\n\n\t\t\tcv::imshow(wname, last_mat);\n\n\t\t}\n\t\tcv::destroyAllWindows();\n\t}\n};\n\n\nint main(int argc,char* argv[])\n{\n\tDroneKB kb;\n\treturn kb.Start();\n}\n```\n\n## Ardrone GUI\n\nPour l'interface visuelle , nous utilisons la librairie ImGui pour nous permmettre de facilement controler les différents parametrage. Pour affichier\nle flux vidéos j'utilise simplement des textures OpenGL qui j'update a chaque frame avec les pointeurs de données recus pour chaqu'un des channels.\n\nLes textures ce déplace selon le nombre de crée et supporte jusqu'a 4 videos simultané pour pouvoir acceder à ;\n\n* Video du drone\n* Video de traitement lors de tracking\n* Camera local pour faire du tracking de cette caméra\n* ....\n\n\n\n## Qu'es-ce qu'on n'a implémenter finalement avec le drone ?\n\nLa première étapde dans nos objectifs était d'être capable de faire un tracking simple avec des thresholds pour suivre un objets sur deux axes (x,y).\n\n\n### Design a prendre\n\nDu la nature multithreader du code et qu'il s'agit d'une application qui doit intéragir en temps réal et que nous devons toujours pourvoir puller les\nderniers informations du drone pour bien agir en conséquence.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fberlingoqc%2Fscdrone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fberlingoqc%2Fscdrone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fberlingoqc%2Fscdrone/lists"}