···11#import "@preview/zebraw:0.5.5"
22#import "@preview/fletcher:0.5.8": diagram, node, edge
33+#import "@preview/cetz:0.4.2"
34#import "./utils.typ": dontbreak
45#show figure: set block(spacing: 2em)
56#let zebraw = (..args) => zebraw.zebraw(lang: false, background-color: luma(255).opacify(0%), ..args)
···10111112Une première tentative a été de suivre la documentation de CycloneDDS pour écouter sur le canal @cyclonedds-helloworld `rt/lowcmd`, en récupérant les définitions IDL des messages, disponibles sur le dépot `unitree_ros2`#footnote[`unitree_mujoco` n'avait pas encore été découvert] @unitree_ros2
12131313-// On commence par importer la bibliothèque DDS et les définitions IDL de `rt/lowcmd`
1414-//
1515-// ```cpp
1616-// #include "messages/LowCmd_.hpp"
1717-// #include "dds/dds.h"
1818-// ...
1919-//
2020-// int main (int argc, char ** argv)
2121-// {
2222-// ```
2323-//
2424-// On initialise les différents objets permettant de lire sur un canal
2525-//
2626-// ```cpp
2727-// dds_entity_t participant, topic, reader;
2828-// LowCmd_ *msg;
2929-// void *samples[MAX_SAMPLES];
3030-// ...
3131-//
3232-// participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
3333-//
3434-// topic = dds_create_topic(participant, &LowCmd__desc, "HelloWorldData_Msg", NULL, NULL);
3535-//
3636-// qos = dds_create_qos();
3737-// dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_SECS (10));
3838-//
3939-// reader = dds_create_reader(participant, topic, qos, NULL);
4040-//
4141-// dds_delete_qos(qos);
4242-//
4343-// samples[0] = LowCmd___alloc();
4444-// ```
4545-//
4646-// Et on attend qu'un message arrive sur le canal, pour l'afficher
4747-//
4848-// ```cpp
4949-// /* Poll until data has been read. */
5050-// while (true)
5151-// {
5252-// rc = dds_read(reader, samples, infos, MAX_SAMPLES, MAX_SAMPLES);
5353-//
5454-// /* Check if we read some data and it is valid. */
5555-// if ((rc > 0) && (infos[0].valid_data))
5656-// {
5757-// /* Print Message. */
5858-// msg = (LowCmd_*) samples[0];
5959-// printf("=== [Subscriber] Received : ");
6060-// fflush(stdout);
6161-// break;
6262-// }
6363-// else
6464-// {
6565-// dds_sleepfor(DDS_MSECS(20));
6666-// }
6767-// }
6868-// ```
6969-//
7070-// Enfin, on libère les ressources avant la terminaison du programme
7171-//
7272-// ```cpp
7373-// LowCmd__free(samples[0], DDS_FREE_ALL);
7474-// dds_delete(participant);
7575-// return EXIT_SUCCESS;
7676-// }
7777-// ```
7878-7914Malheureusement, cette solution s'est avérée infructueuse, à cause de (ce qui sera compris bien plus tard) un problème de numéro de domaine DDS.
80158116On change d'approche en préférant plutôt utiliser les abstractions fournies par le SDK de Unitree (cf @receive-lowcmd et @send-lowstate)
8282-83178418Enfin, si un pare-feu est actif, il faut autoriser le traffic udp l'intervalle d'addresses IP `224.0.0.0/4`. Par exemple, avec _ufw_
8519···8822sudo ufw allow in proto udp to 224.0.0.0/4
8923```
90242525+Pour arriver à ces solutions, du débuggage du traffic RTPS (le protocole sur lequel est construit DDS @dds) s'est avéré utile.
2626+2727+_Wireshark_ @wireshark supporte le décodage de paquets RTPS
2828+2929+#let img = image("./wireshark-trace.png")
3030+// https://forum.typst.app/t/how-to-blend-a-color-with-an-image-and-make-the-image-transparent/1677/5
3131+#let overlayed-img = contents => layout(bounds => {
3232+ let size = measure(img, ..bounds)
3333+ img
3434+ place(top+left, block(..size, contents))
3535+})
3636+3737+#figure(
3838+ caption: [Trace de paquets RTPS sur _Wireshark_],
3939+ overlayed-img[
4040+ #diagram({
4141+ set math.equation(numbering: none)
4242+ import "@preview/fletcher:0.5.8": shapes
4343+ node(enclose: ((5, 2), (5, 5)), shape: shapes.bracket.with(dir: right))[Initialisation]
4444+ })
4545+ ]
4646+)
914792489349== Installation du plugin dans Gazebo