ACCUEILCAS D'USAGESPLATEFORMEMATÉRIELACCOMPAGNEMENTACADÉMIENOUS
Hengbot Sirius

Hengbot Sirius : documentation développeur

Le protocole réel du robot, ses capteurs, et les quatre pièges qui font perdre des journées.

Le Hengbot Sirius est vendu « code-friendly », mais sa documentation constructeur, en juillet 2026, s'arrête au mouvement : aucune lecture de capteur, et la fiche technique officielle ne mentionne même pas la caméra. Cette page rassemble ce que nous avons établi en cartographiant le robot, et vérifié en direct sur la machine. Tout ce qui est marqué « vérifié » a été observé sur un Sirius réel ; ce qui reste incertain est signalé comme tel.

Mis à jour le 26 juillet 2026

Visuel officiel Hengbot du robot quadrupède Sirius, de trois quarts, en appui sur ses quatre pattes

1En bref

Si votre Sirius reçoit vos commandes sans rien faire d'utile, la réponse est presque toujours dans cette liste. Les quatre pièges ci-dessous produisent tous le même symptôme : un robot qui accuse réception, renvoie fidèlement la valeur reçue, et piétine.

  1. L'unité de vitesse : les consignes sont normalisées dans [-1, 1], ce ne sont pas des m/s. Demander 0.15 revient à demander 15 % de la vitesse maximale, pas 0,15 m/s.
  2. Le mode robot : sorti d'usine, le robot est en desktop, un mode qui bride volontairement la démarche pour qu'il ne tombe pas de la table.
  3. La priorité d'action : un ACTION_PLAY joué en priorité 1 se fait écraser par le comportement autonome en cours. Il faut la priorité 5.
  4. Le sommeil : après inactivité, le robot s'accroupit et n'exécute plus rien d'utile. Jouer l'action de redressement le remet debout et opérant, à distance.

À quoi s'ajoute un cinquième piège, côté protocole : les noms de commandes du WebSocket sont en majuscules. Les noms en minuscules que l'on trouve dans les binaires sont les handlers internes, pas ce qui circule sur le fil.

Le sujet le plus inédit est le capteur ToF : sa position réelle, sa grille, ses unités et son auto-occultation ne sont publiées nulle part, et c'est de là que vient la détection de vide gratuite décrite plus bas.

2Ce qu'est le robot, vraiment

Sous la carrosserie, le Sirius est un mini-ordinateur Linux (puce D-Robotics RDK X3, environ 5 TOPS) qui fait tourner ROS 2 Humble. Tout son comportement est un ensemble de nœuds ROS 2 qui discutent entre eux. L'application vit dans /root/sirius_ros2 et démarre au boot via le service ros2_launch.service.

Il existe deux niveaux pour le piloter, et le choix engage la sécurité mécanique du robot.

NiveauQuoiPour quoi faire
Haut niveauWebSocket :8765, services et topics ROS 2Marcher, jouer une action, lire les gestes et la vision. Passe par les protections du robot (modes cinématiques, couple par action, équilibre).
Bas niveauUDP :8768 et suivants, paquets Play_KeyframeStreamer des poses image par image, c'est la voie de l'add-on Blender. Court-circuite les protections : à réserver aux limites articulaires connues.

Les nœuds qui tournent vraiment

ros2 node list renvoie 31 entrées, dont deux doublons (core_api_node et camera_publisher_node apparaissent deux fois) : 29 nœuds distincts. Ceux qui comptent :

  • core_api_node : le serveur WebSocket :8765, c'est lui qui répond aux 59 commandes.
  • sirius_motion_control_node : le mouvement. C'est lui qui consomme /gait_generation_trot/cmd_vel et publie filtered_velocity, ainsi que les topics /kinematics/*.
  • behavior_engine_node : le comportement autonome, les émotions, l'arbre de décision. Il a absorbé ce que le paquet 2.3.6 répartissait entre robot_behavior_controller et emotion_manager.
  • perception_bridge_node, face_detection_bridge, camera_publisher_node : la perception visuelle.
  • state_sensor_tof_node : le capteur de distance, sujet d'une section entière plus bas.
  • imu_onbody, internal_sensor_battery_onbody : centrale inertielle et batterie.
  • action_player_node : joue les actions nommées de /root/material/actions/.
  • lvgl_gui_node : l'écran de la tête, y compris le tactile.
  • sirius_gamepad et xbox_bluetooth_gamepad sur le topic /joy : la manette Xbox est gérée nativement, ce que la documentation ne dit nulle part.
  • Et le reste de la machinerie : lifecycle_manager_node, ota_update_node, network_config_node, sync_manager_node, motor_torque_controller_node, fan_controller_node, modbus_driver, wmix_audio_player_node, ai_interaction_node, character_state_node, user_data_manager, user_interface_udp_server_node, production_test_node, sirius_bt, ble_control_server, robot_led_controller_node.
Télécharger l'inventaire ROS brutRelevé du 25 juillet 2026 à 23 h 37 sur la machine · texte, 18 Ko
Nœuds, topics, types de messages : la source de tout ce que cette page affirme sur l'architecture.

Fiche technique officielle

  • Dimensions 250 x 130 x 250 mm, 960 g, charge utile 300 g.
  • Autonomie annoncée 45 à 50 min en usage actif.
  • Vitesse maximale annoncée 0,4 m/s (voir plus bas : trois valeurs contradictoires circulent).
  • Aucun capteur n'est mentionné dans la section Spécifications. Ni ToF, ni centrale inertielle, ni caméra.

3Versions et firmware

Savoir sur quelle version vous êtes conditionne tout le reste : entre le paquet source que le constructeur distribue avec ses outils et le firmware réellement installé, l'architecture a changé.

ÉlémentValeurComment on le sait
Firmware de notre robot2.5.0 bêta, installée le 23/07/2026Vérifié : Centre de mise à jour du robot, « System is up to date »
Dernière version stable2.4.8, 17/07/2026Vérifié : canal RELEASE de la même page
API embarquéeSirius Core API 4.0.0Vérifié : annoncée par le robot dans server_info au handshake
Paquet source livré avec les outils OTA2.3.6Vérifié : antérieur au firmware installé, et l'écart est documenté par le constructeur lui-même
Application citée dans la documentation officielle240726Documenté : soit une compilation de juillet 2024, ce qui date la documentation

Ce que le journal nous a appris

  • 2.5.0, 23 juillet 2026 : « les nœuds de comportement et d'émotion ont été supprimés, fusionnés dans un nœud unique de pilotage par arbre de comportement ». C'est l'explication exacte du décalage avec le paquet 2.3.6.
  • 2.4.7, 2 juillet 2026 : passage au WebRTC pour le flux vidéo web, et ajout de la détection de squelette humain. La documentation qui annonce la caméra « non disponible » n'est donc pas fausse : elle est antérieure.
  • 2.4.7 et 2.4.9 : balayage vers le haut = déverrouillage de l'écran, balayage vers le bas = mise en veille, décrits comme un « geste de réveil ». Cela tranche une question restée longtemps ouverte, voir le piège 3.
  • 2.4.6, 10 juin 2026 : ajout d'une protection contre la surcharge de couple dans le firmware bas niveau. Un filet de plus, sous les écrêtages articulaires et sous tout coupe-circuit logiciel.
  • 2.4.5, 3 juin 2026 : « protocole d'API mis à jour ». C'est probablement là que naît le protocole en majuscules décrit dans cette page, et l'écart avec l'API que documente le constructeur.

Relire la version depuis le robot, si vous préférez la ligne de commande à l'interface :

ssh root@<IP_DU_ROBOT>
source /opt/ros/humble/setup.bash
source /root/sirius_ros2/install/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
[ -f /root/cyclonedds.xml ] && export CYCLONEDDS_URI=file:///root/cyclonedds.xml

ros2 topic echo --once /esp32/firmware_version   # version du microcontroleur
ros2 topic echo --once /ota/status               # etat du systeme de mise a jour

La console du constructeur

Sa barre de navigation liste neuf outils, dont plusieurs ne sont documentés nulle part : Material Manager, Inner World, System Update, Node Management (gestion des nœuds ROS, avec journal depuis la 2.4.5), Gait Debug, Group Dance, Net Debug, Behavior Tree et Timeline Editor. Un retour arrière de firmware y est également disponible. Nous n'en avons exploré que deux : les autres sont des pistes ouvertes, pas du connu.

4Les sept canaux de communication

Le robot expose sept voies d'accès distinctes. Le WebSocket est le canal principal : il pousse l'état en continu et répond aux requêtes. Mais celui qui compte le plus pour un développeur est le dernier de la liste.

CanalAdresseRôleStatut
WebSocketws://<IP>:8765?audience=webCanal principal : état poussé et requêtes/réponsesVérifié
WebSocket vidéows://<IP>:8766Signalisation WebRTC de la caméra, sans paramètre d'URLVérifié
RESThttp://<IP>:8088/api/v1/…Configuration IA, identifiants, compétences, journauxVérifié
UDP<IP>:8768 (mouvement et LED), :8770 (yeux)Streaming de poses Play_Keyframe, la voie BlenderDocumenté
MJPEGhttp://<IP>:8080/video_streamFlux image simple, alternative au WebRTCÀ confirmer, crédit dspeers
SSHroot@<IP>:22Accès ROS 2 et déploiementVérifié
ROS 2à bord, RMW CycloneDDS29 nœuds, environ 130 topics : le seul accès aux capteursVérifié

Le paramètre ?audience=web figure dans l'URL de l'interface officielle. La connexion fonctionne sans, mais autant rester fidèle à ce que fait le robot.

Enveloppes du WebSocket

// handshake reçu à la connexion
{"type":"event","event_type":"connection_info",
 "data":{"client_id":30,"status":"connected",
   "server_info":{"name":"Sirius Core API","version":"4.0.0",
     "architecture":"Service-based",
     "capabilities":["play_motion","status_monitoring","factory_test","ota_update"]}}}

// requête
{"type":"request","request_type":"<NOM>","request_id":"<id>","data":{}}

// réponse
{"type":"response","request_id":"<id>","success":true,"code":"ok","data":{},"error":""}

// battement de cœur, émis par le client
{"type":"ping","data":{"timestamp":0}}

Codes d'erreur observés : invalid_request, not_found (avec le message « Unknown request_type »), invalid_argument, service_unavailable. Sonder un nom de commande inconnu est sans effet sur le robot : on peut explorer l'API sans rien casser.

Le flux d'événements poussés

ÉvénementCadenceContenu
gait-trajectory10 Hzfiltered_velocity : ce que le générateur de démarche applique réellement
motor-load1 Hz14 charges moteur, plage ±1000, unité pour mille de PWM
motor-temperature1 Hz4 pattes, mais renvoie 0 sur ce firmware (sondes muettes)
battery-status1 Hzpercentage est un ratio 0 à 1, plus tension, courant, température
emotion-update1 Hzétat émotionnel, valence, éveil, satiété, fatigue
behavior-status1 Hzarbre de comportement actif, intention, événements récents (dont les tapes sur le crâne)
vision-detection~30 Hzdétections et squelettes, voir la section vision
system_metrics1 Hzprocesseur, charge moyenne, disque
lifecycle_update~0,1 Hztous les nœuds ROS et leur état

5Se connecter au robot

Trouver son adresse IP

  • Sur l'écran de la tête, menu Réseau.
  • Depuis la liste des baux de votre routeur.
  • Par le mode point d'accès du robot : SSID sirius_xx, mot de passe hengbot123 (publié par le constructeur dans son manuel), passerelle 192.168.233.1.

Votre machine et le robot doivent être sur le même réseau. L'interface de debug du constructeur est une page hébergée chez Hengbot, pas sur le robot : http://8.163.38.44:8082/connect?robot=<IP_DU_ROBOT>. Elle ouvre ensuite un WebSocket directement vers votre robot sur :8765. On y trouve le joystick virtuel, la lecture d'actions, la vision et le mode autonome. C'est le moyen le plus rapide de vérifier que tout répond avant d'écrire une ligne de code, et c'est ce test qui nous a mis sur la piste du piège 1.

Accès SSH

ssh root@<IP_DU_ROBOT>

# charger l'environnement ROS 2, sinon aucun nœud n'est visible
source /opt/ros/humble/setup.bash
source /root/sirius_ros2/install/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
[ -f /root/cyclonedds.xml ] && export CYCLONEDDS_URI=file:///root/cyclonedds.xml

ros2 node list      # 31 nœuds
ros2 topic list     # environ 130 topics

6Piège 1 : la vitesse est normalisée, pas en m/s

Les champs linear_x, linear_y et angular_z attendent une valeur dans [-1, 1] : une fraction du débattement maximal, pas des mètres par seconde. La touche « avancer » de l'interface officielle envoie tout simplement linear_x: 1.

{"type":"request","request_type":"gait_control",
 "data":{"linear_x":1,"linear_y":0,"angular_z":0}}

Envoyer 0.15 en croyant demander 0,15 m/s revient donc à demander 15 % de la vitesse maximale : la foulée devient minuscule et le robot marche sur place. Les ordres de grandeur relevés en télémétrie :

ConsigneComportement observé
0,10piétine sur place
0,45 à 0,50marche franche

Pour convertir une vitesse réelle en consigne, en s'appuyant sur le domaine de validité relevé sur le robot : linear_x = vx / 0.24 en marche avant, vx / 0.16 en marche arrière, linear_y = vy / 0.20, angular_z = wz / 1.20.

La preuve, côté ROS 2

entrée : /gait_generation_trot/cmd_vel           geometry_msgs/msg/Twist
retour : /gait_generation_trot/filtered_velocity geometry_msgs/msg/Twist

consigne vx=+0.50  ->  mesuré vx=+0.500   (rapport 1.00)

La consigne ressort à l'identique sur filtered_velocity, or 0,50 dépasse la vitesse maximale déclarée du robot. Ce ne peut donc pas être des mètres par seconde. filtered_velocity fait foi : il dit ce que le générateur de démarche applique vraiment, et permet de distinguer « le robot refuse » de « on lui demande trop peu ».

Trois vitesses maximales contradictoires

SourceVitesse avant annoncée
Fiche technique officielle0,4 m/s
Documentation de l'API WebSocket0,28 m/s
ros2 param dump sur le robot0,24 m/s

C'est la dernière valeur qui gouverne le comportement réel, puisqu'elle vient des paramètres chargés par le nœud de contrôle. Domaine complet relevé sur la machine : avant 0,24 m/s, arrière 0,16 m/s, latéral ±0,20 m/s, rotation ±1,2 rad/s, tangage et roulis ±0,524 rad. Les garde-fous joint_clamp_enabled et ws_clamp_enabled sont actifs : une consigne hors domaine est écrêtée, pas poussée contre la butée.

7Piège 2 : les noms de commandes sont en majuscules

C'est le piège principal du protocole WebSocket. Le fil réseau utilise des clés en majuscules, par exemple BEHAVIOR_SET_PAUSE. Les noms en minuscules que l'on trouve en fouillant les binaires, comme set_behavior_pause, sont les handlers internes, pas ce qui circule.

Certaines commandes acceptent les deux formes, par alias hérité : play_motion, gait_control, get_status et get_actions répondent en minuscules. Mais les commandes de mode n'existent qu'en majuscules. Chercher set_behavior_pause sur le fil renvoie « Unknown request_type » et fait croire à tort que la fonction est inaccessible.

Le protocole complet compte 59 commandes, extraites du bundle officiel. Les plus utiles :

Clé réseauHandler interneUsage
ACTION_PLAYplay_motionjouer une action nommée ou un fichier
ACTION_STOP / ACTION_STOP_ALLcancel_motioninterrompre
ACTION_GET_LISTget_actionslister la bibliothèque d'actions du robot
BEHAVIOR_SET_PAUSEset_behavior_pausemettre le comportement autonome en pause
BEHAVIOR_SET_RANDOM_ACTIONenable_random_actionanimations spontanées au repos
USER_GET_ROBOT_MODE / USER_SET_ROBOT_MODEget/set_robot_modemode sol ou bureau (piège 3)
MOTOR_SET_TORQUE / MOTOR_SET_THERMAL_PROTECTIONcouple et protection thermique
VISION_SET_DETECTIONenable_detectionactive la perception et le flux vidéo
VISION_SET_FACE_TRACKINGface_tracking_controlsuivi de visage
BATTERY_GET_STATUSget_battery_statusétat de la batterie

Familles complètes également présentes : EMOTION_*, USER_* (thème, MBTI, langue, paramètres de nœud), LIFECYCLE_*, NETWORK_*, OTA_*, SYNC_*, MATERIAL_*.

8Piège 3 : le mode sol ou bureau

Deuxième cause classique du « il piétine sans avancer », après l'unité de vitesse. Le robot possède deux modes de fonctionnement, et il sort d'usine dans celui qui bride la marche.

USER_GET_ROBOT_MODE  {}                        -> {"robot_mode":"desktop"}
USER_SET_ROBOT_MODE  {"robot_mode":"ground"}   -> {"robot_mode":"ground"}
  • desktop : selon le firmware, « limite les mouvements amples et la démarche pour empêcher le robot de tomber de la table ». Les pattes bougent sur place.
  • ground : « active toutes les actions, y compris la démarche et les déplacements amples ».
Le sélecteur de mode de Sirius Studio positionné sur BureauLe même sélecteur positionné sur Sol
Le sélecteur Sol / Bureau dans nos deux états, tel qu'il apparaît dans notre outil de pilotage.

L'écran de la tête affiche un état nommé « Ground », et le robot y bascule de lui-même après une période d'inactivité. Un balayage vertical sur l'écran « débraye » cet état, mais ce n'est pas un changement de mode robot. Les notes de version du constructeur sont explicites : le balayage vers le haut déverrouille l'écran et sert de geste de réveil (versions 2.4.7 et 2.4.9), le balayage vers le bas met en veille. Le mode sol ou bureau, lui, ne se change que par USER_SET_ROBOT_MODE, ou depuis une interface.

La documentation officielle décrit par ailleurs un mode Développeur sur l'écran de tête, qui « suspend l'interface pour permettre la programmation Python via les API ». Nous ne l'avons pas testé. La navigation dans cet écran se fait par les boutons d'oreille, la validation par une tape sur le crâne.

9Piège 4 : le capteur n'est pas là où on croit

Pendant dix sessions, notre robot en déambulation autonome s'arrêtait net devant un obstacle situé à 191 mm. Toujours 191 mm, avec 5 mm d'écart-type. Un obstacle qui n'existait pas : il fuyait sa propre mâchoire.

Le capteur ToF n'est pas dans la tête, comme la position de la « bouche » du robot le laisse croire. Il est sous le cou, en haut du poitrail. Placé si haut et si en avant, il voit son propre menton dans le haut de son champ, et ses propres pattes avant dans le bas.

La mesure qui tranche

Quand on bascule la tête de ±0,30 rad (17°) sur son axe de tangage, les distances ToF ne varient que de 1 à 2 mm. Un capteur logé dans la tête verrait ses distances au sol changer de plusieurs dizaines de millimètres pour un tel basculement.

Axe de têteÉcart rangée basseÉcart rangée haute
x (tangage, la tête bouge de visu)1 mm2 mm
y (lacet)0 mm0 mm
z0 mm0 mm

Les conséquences sont presque toutes favorables. La géométrie du ToF ne dépend que de l'assiette du corps, que le générateur de démarche régule déjà : il n'y a donc aucun angle de tête à suivre dans vos calculs. Et la tête peut regarder ailleurs, suivre un visage, sans perturber la navigation. En contrepartie, le champ est fixe par rapport au corps : impossible d'orienter le capteur pour balayer les côtés, c'est le corps entier qu'il faut tourner.

L'auto-occultation par les pattes

RangéeAu reposMain devantChute
12-15 (haut)866 mm168 mm79 %
8-11838 mm170 mm81 %
4-7334 mm211 mm37 %
0-3 (bas)237 mm195 mm18 %, occultée

Une main passée devant le capteur fait chuter les distances mesurées de 80 % sur les rangées hautes, mais de 18 % seulement sur la rangée basse : les pattes avant y occupent déjà le champ. Et en marchant, elles balancent, donc elles entrent et sortent du champ à chaque foulée. D'où deux règles de conception : ne jamais fonder une détection sur la seule rangée 0-3, et apprendre le fond en marchant, jamais à l'arrêt.

Caractérisation complète du ToF

GrandeurValeur mesurée
Topic/state_sensor/tof/distance_array
Typestate_sensor_tof/msg/ToFDistanceArray
Unitémillimètre
Plage11 à 2047 mm, où 2047 signifie pas de cible
Cadenceenviron 38 Hz (384 trames en 10 s)
Zones16, en grille 4 x 4, toutes vivantes

Le même relevé est aussi publié en image mono16 4 x 4 sur /state_sensor/tof/heatmap. Le champ raw_registers (11 valeurs, souvent 65535) est du débogage constructeur, sans intérêt.

        haut   [12] [13] [14] [15]
               [ 8] [ 9] [10] [11]
               [ 4] [ 5] [ 6] [ 7]
        bas    [ 0] [ 1] [ 2] [ 3]
                gche            drte

Signature au repos

robot debout, tete au neutre, champ degage

   ..   765    ..    ..      <- horizon : hors portee
  780   786    ..    ..      <- sol lointain
  304   295   291   298      <- sol a ~30 cm
  198   219   218   201      <- sol a ~20 cm, juste devant les pattes

Les rangées basses voient le plancher à distance croissante. C'est de là que découlent les deux lectures qui fondent toute navigation autonome, et la section suivante.

10La détection de vide, gratuite

C'est la trouvaille la plus utile de tout ce travail, et elle ne demande aucun matériel supplémentaire. Puisque les rangées basses du ToF voient en permanence le plancher, entre 20 et 30 cm devant elles, il suffit de surveiller sa disparition.

  • Obstacle : les rangées hautes cessent de saturer et les basses raccourcissent.
  • Vide (bord de table, marche, escalier) : les rangées basses, qui voyaient le sol, passent brutalement à 2047, c'est-à-dire « pas de cible ».

Le principe d'implémentation retenu : le nœud apprend son fond pendant cinq secondes de marche en ligne droite, sous forme d'enveloppe minimum et maximum par zone. Il ne réagit ensuite qu'aux écarts. Ce qui raccourcit est un obstacle, ce qui s'allonge est un vide.

Les garde-fous qui se sont révélés nécessaires

  • Le vide l'emporte sur toute autre décision.
  • Seules les rangées basses ont le droit de déclarer un vide, et seulement les zones qui voyaient le sol de près (moins de 50 cm) et presque toujours (80 % des trames).
  • Toute décision doit persister trois cycles avant d'être appliquée : le trot fait tanguer le corps, une seule trame ne prouve rien.
  • Le recul est bridé à la moitié de la vitesse d'avance et borné à 1,5 s, parce que le robot ne voit rien derrière lui.
  • Une rotation sans issue de plus de 5 s déclenche un recul et un changement de sens, sinon le robot tourne indéfiniment.
  • Le nœud publie dix consignes nulles à l'arrêt, y compris sur SIGHUP. Validé en réel lors d'une coupure Wi-Fi : le robot s'arrête proprement au lieu de continuer sur sa dernière consigne.

L'historique des versions dit tout du chemin parcouru : recul perpétuel en v1 (seules 8 zones apprises, les autres signalaient sans cesse un obstacle surgi de nulle part), vides fantômes en v6 (zones lointaines saturées prises pour des précipices), rotation sans fin en v7, et v8 qui a révélé le piège de la vitesse normalisée. La v9 se faufile et esquive. La v10 a tenu 11 s de marche rectiligne et survécu à une perte de SSH.

La v12 masque une bande étroite de 170 à 225 mm dans le haut du champ, la signature de la mâchoire, mais seulement si les rangées basses ne confirment pas la présence d'un obstacle, pour qu'une étagère basse reste visible. Elle remplace aussi la marge fixe de 120 mm par une marge proportionnelle au fond appris (30 %, plancher à 50 mm) : avec un fond à 200 mm, une marge fixe de 120 mm rendait les rangées basses incapables de déclencher quoi que ce soit. Trente-quatre tests hors ligne rejouent de vraies trames capturées sur le robot.

11Faire marcher le robot

Deux voies, selon que vous travaillez depuis votre machine (WebSocket) ou depuis le robot lui-même (ROS 2). Dans les deux cas, relisez d'abord les pièges 1 et 3 : ils expliquent la plupart des cas où le robot refuse d'avancer.

Par le WebSocket

CommandeCharge utileEffet
gait_control{linear_x, linear_y, angular_z} dans [-1, 1]marche continue
gait_step_move{linear_x, linear_y, angular_z, steps}marche sur un nombre de foulées donné, le robot les compte lui-même
set_motion_mode{mode, mode_name}profils DEFAULT, SLOW, WALK, PRECISION, CLIMB, FAST_RUN
self_recover{}redressement après chute

Par ROS 2, depuis le robot

import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist

# ATTENTION : linear.x est NORMALISE dans [-1, 1], pas des m/s.
# 0.10 fait pietiner sur place. 0.45 fait marcher.

rclpy.init()
node = Node('hello_move')
pub = node.create_publisher(Twist, '/gait_generation_trot/cmd_vel', 10)

cmd = Twist()
cmd.linear.x = 0.45
for _ in range(30):
    pub.publish(cmd)
    rclpy.spin_once(node, timeout_sec=0.1)

# toujours republier des zeros a l arret
cmd.linear.x = 0.0
for _ in range(10):
    pub.publish(cmd)
    rclpy.spin_once(node, timeout_sec=0.05)

Le service /gait_generation_trot/step_move (type gait_generation_trot/srv/GaitStepMove, champs velocity et duration) fait un pas net et rend la main. C'est le plus simple pour un premier essai : une vitesse négative fait reculer.

Se relever, se coucher

ACTION_PLAY {
  "file_path":"/root/material/actions/stand_default_returnPosition_brief.avi",
  "loop":false,
  "priority":5,
  "torque":2047
}

Trois détails comptent, et chacun a coûté du temps : l'action est returnPosition et non stand_default_idle ; la priorité 5 est indispensable, car en priorité 1 (la valeur par défaut) le comportement autonome en cours écrase l'action et le robot reste couché ; et le couple doit être au maximum.

Le sommeil

Après inactivité, le robot passe en état émotionnel sleeping, avec un éveil proche de zéro, et s'accroupit. Dans cet état, la marche ne produit rien d'utile. Pour le réveiller à distance, jouez l'action de redressement, celle de la sous-section précédente, en priorité 5. Vérifié sur le robot : il se relève et obéit de nouveau.

Ce qui ne se pilote pas à distance, c'est l'état émotionnel lui-même : EMOTION_SET_STATE répond service_unavailable sur ce firmware, et EMOTION_INTERACTION refuse tous les types tentés (touch_tap, touch, pet, dog_bone). La distinction compte : on ne peut pas changer son humeur, on peut parfaitement le remettre au travail.

12Gestes, vision et caméra

Les gestes de la main : à vérifier sur votre firmware

Un modèle de reconnaissance de gestes existe côté D-Robotics, et le paquet sirius_full_v2.3.6 référence le topic /hobot_hand_gesture_detection (ai_msgs/PerceptionTargets), avec un attribut gesture porteur d'une valeur entière.

ValeurGesteValeurGeste
2ThumbUp (pouce levé)11Okay
3Victory (V)12Thumb Left
4Mute (chut)13Thumb Right
5Palm (main ouverte)14Awesome

L'événement vision-detection

Une fois VISION_SET_DETECTION actif, le robot pousse sur le canal principal un événement à environ 30 Hz. C'est la sortie du modèle de perception, disponible sans toucher au flux vidéo : on peut donc faire du suivi sans jamais afficher d'image.

{"type":"event","event":"vision-detection","data":{
  "detections":[
    {"class_id":0,"class_name":"body","type":"body","confidence":1,
     "rect":{"x":239,"y":1,"width":126,"height":192}},
    {"class_name":"head","rect":{}},
    {"class_name":"face","rect":{}}
  ],
  "skeletons":[
    {"track_id":1,"type":"body",
     "points":[{"x":191,"y":3,"score":0.859}]}
  ],
  "image_width":640,"image_height":360}}
  • Les coordonnées sont dans le repère 640 x 360 du modèle, pas dans celui de la vidéo affichée. Il faut les remettre à l'échelle, et tenir compte du letterboxing si la vidéo est en object-fit: contain.
  • track_id persiste entre les trames : c'est du suivi, pas de la détection image par image.
  • Classes observées à ce jour : body, head, face. Les objets « os, balle, peluche » du firmware sont des items virtuels du système d'émotions, pas des classes de vision.
  • À 30 Hz, ne jamais faire passer ces trames par l'état d'un composant React : les stocker dans une référence et dessiner dans un requestAnimationFrame.
Le panneau de suivi en temps réel de Sirius Studio, avec un compteur par classe détectée
Le panneau de suivi liste une nomenclature fixe avec un compteur par classe, et révèle automatiquement toute classe inconnue qui apparaîtrait. C'est le moyen le plus simple de découvrir ce que le modèle embarqué sait réellement détecter : le laisser tourner devant une balle, une main, un animal, et regarder si une ligne s'ajoute.

La caméra, en WebRTC

Ce n'est pas une image à récupérer : c'est un flux WebRTC négocié sur une seconde WebSocket. La vidéo circule ensuite directement entre le navigateur et le robot, en pair-à-pair. Un backend ne peut donc que relayer la signalisation, jamais servir le flux.

  1. Sur :8765, envoyer VISION_SET_DETECTION {enabled: true}. Le robot répond « Web streaming enabled ».
  2. Le navigateur ouvre ws://<IP>:8766, sans paramètre d'URL. C'est le point qui nous a coûté le plus de temps : la signalisation vidéo ne vit pas sur le canal principal.
  3. Le robot y envoie {"type":"welcome","client_id":"ws_N"}. Cet identifiant est une chaîne, distincte du client_id numérique du handshake. Reconstruire ws_<numéro> ne fonctionne pas.
  4. Le navigateur envoie webrtc_offer avec ce client_id, le robot répond webrtc_answer.
  5. Échange de webrtc_ice. Les candidats du robot arrivent préfixés a=, à retirer avant addIceCandidate.

Si le pair-à-pair est bloqué par le réseau, il reste une voie plus simple : le service ROS /camera/capture_jpeg, en affichage par images successives. Services caméra côté ROS : /camera/capture_jpeg, /camera_publisher_node/enable_web_streaming, /camera_publisher_node/enable_yolo_shm.

13Commander la tête

Le canal confirmé sur le robot est un topic ROS d'entrée du nœud de cinématique inverse. Il reçoit une consigne et ne publie rien en retour.

topic : /kinematics/ik_subscriber/head_euler_follow
type  : geometry_msgs/msg/Point
unite : RADIANS

x = tangage (haut / bas)
y = lacet (gauche / droite)
z = sans effet observable
  • x commande le tangage, confirmé de visu.
  • y commande le lacet.
  • z n'a aucun effet observable : la tête n'a que deux degrés de liberté.
  • De 0,10 à 0,35 rad, les mouvements sont progressifs. Rester sous 0,35 rad : au-delà d'environ 1 rad, c'est la butée articulaire.

Rappel utile : puisque le ToF est dans le poitrail et non dans la tête, bouger la tête ne perturbe pas la navigation. La tête peut donc suivre un visage pendant que le corps se dirige avec ce même champ ToF, sans que l'un gêne l'autre.

14Ce qui n'existe pas, et ce que la doc omet

Cette section est là pour vous éviter de chercher pendant des heures quelque chose qui n'est pas dans la machine.

Ce qui n'existe pas

  • Pas de retour d'angle de tête : les topics existent mais restent muets.
  • Pas de température moteur : l'événement motor-temperature renvoie 0 sur ce firmware, les sondes sont muettes.
  • Pas de réglage de l'état émotionnel à distance : EMOTION_SET_STATE répond service_unavailable. Le réveil, lui, passe très bien par l'action de redressement.
  • Pas de détection de clap native, ni de doigt pointé dans le modèle de gestes.
  • Pas de classes de vision au-delà de body, head et face à ce jour. Le service enable_yolo_shm laisse penser qu'un modèle YOLO existe par ailleurs, non confirmé.

Ce qui existe, et que la documentation ignore aussi

La liste précédente a son pendant positif : la centrale inertielle est lisible, alors que la fiche technique ne la mentionne pas plus que le reste des capteurs.

/state_sensor/imu_onbody/imu_publisher/imu_data    sensor_msgs/msg/Imu
/state_sensor/imu_onbody/imu_publisher/imu_angle   geometry_msgs/msg/Vector3
/state_sensor/imu_onbody/imu_publisher/diagnostic  "IMU sensor is operating normally"

imu_angle sert de garde-fou dans notre déambulation : si l'assiette dérive de plus de 0,10 rad par rapport à celle apprise, la géométrie du ToF n'est plus valable et toute décision de vide est suspendue. C'est un exemple concret d'un capteur non documenté employé pour sécuriser un autre capteur non documenté.

Ce que la documentation officielle omet

SujetDocumenté par le constructeur ?
Lecture de capteurs, quelle qu'elle soitNon
Le capteur ToF, y compris dans les spécificationsNon
La centrale inertielle, la caméraNon
ROS 2, alors qu'une version EDU est vendue sur cet argumentNon
Le mode sol / bureau, la priorité d'action, le sommeilNon
Le système d'émotions, la bibliothèque d'actions, l'interaction IANon
Le REST du port 8088, l'accès SSHNon
Le protocole « Sirius Core API v4.0.0 » et ses 59 commandesNon, il n'apparaît nulle part
L'API WebSocket « keyframes » et l'API Python hengbotOui
Les modes Emergency_Stop et Free_ModeOui, et nous les ignorions

La documentation officielle existe et mérite d'être lue : elle décrit une API WebSocket différente de celle que nous avons cartographiée, la voie « keyframes » du port UDP 8768, avec les commandes Mode_Switch, Control_Move, Start_Record, Play_Keyframe, Get_Status, Set_Parameter. Elle documente aussi un mode Liberté et un mode Développeur sur l'écran de tête, et un auto-test matériel (IMU, boutons, batterie, Wi-Fi, servomoteurs).

L'écosystème indépendant, en juillet 2026

Le terrain est quasi vierge. Huit mois après les premières livraisons, le nombre de tutoriels développeur publiés sur YouTube, toutes langues confondues, est de zéro. Tout ce qui existe tient en deux dépôts, d'une seule personne :

  • dspeers/sirius-control-panel : découvre le REST sur :8088 et un flux MJPEG sur :8080. Son test_api.py est la seule documentation d'API reconstituée publiquement disponible, et la seule source publique mentionnant la grille 4 x 4.
  • dspeers/sirius-voice-bridge : substitue une reconnaissance vocale locale à celle d'origine. Révèle au passage que la voix du Sirius transite par le cloud ByteDance / Volcano Engine, ce qu'aucune couverture presse ne mentionne.
  • mitchrk/sirius-osrd annonce un firmware open source et est entièrement vide.
  • Le paquet PyPI hengbot-api est un faux ami : il date de novembre 2024 et pilote le Sparky, le robot précédent.

15Piloter le robot depuis un navigateur

Le kit que nous utilisons pour tout ce travail est téléchargeable. Il n'a rien d'un produit : c'est un outil de rétro-ingénierie devenu utilisable, publié parce qu'il fait gagner des heures à qui veut commencer.

Le poste de pilotage de Sirius Studio : une vue au ras du sol à gauche, deux joysticks de déplacement, un joystick de tête, la sécurité moteurs et le journal des appels d'API
Le poste de pilotage, connecté au simulateur. La vue caméra est une illustration, pas une image produite par le robot : le simulateur rejoue le vrai protocole mais ne diffuse pas de vidéo. Elle est là pour montrer la hauteur de champ d'une machine de trente centimètres. Tout le reste de l'écran est réel, y compris la télémétrie des 14 moteurs et le journal d'API.

Ce qu'il fait : deux joysticks pour marcher et s'orienter, un troisième pour la tête, la vue caméra en direct avec les détections dessinées par-dessus, la bibliothèque d'actions du robot avec ses noms traduits du chinois, la télémétrie des 14 moteurs, le journal de tous les appels d'API, le sélecteur Sol / Bureau, et un coupe-circuit qui arrête le robot au-delà de 850 ‰ de charge moteur maintenus 0,8 s.

Comment il est fait : un pont Python tourne sur votre machine (FastAPI), il parle WebSocket au robot et sert une interface React à votre navigateur. La vidéo, elle, va directement du robot au navigateur en WebRTC : un backend ne peut relayer que la signalisation, jamais le flux.

L'interface est bilingue français et anglais : un bouton FR / EN dans la barre du haut, à côté du thème, et le choix est mémorisé. Le bouton de posture s'appelle Couché et non « Au sol », pour ne pas le confondre avec le mode Sol / Bureau, qui décrit l'environnement du robot et non sa posture. Depuis la v2.6, ce sélecteur reflète l'état réel du robot, y compris quand le comportement autonome agit seul : la posture est déduite de l'action jouée, signalée comme telle, et rien ne s'allume tant qu'elle n'est pas connue.

Télécharger Sirius Studio v2.6 (129 Ko)Windows · archive à décompresser, pas d'installateur
SHA-256 eb6fcd75c78276e5bec7cd1ac2555eb7f2de4d30b2ca6403306d480cf4dfd2a4

Ce qu'il vous faut

  • Python 3 installé sur votre PC, avec la case « Add Python to PATH » cochée à l'installation. C'est la cause numéro un des échecs de démarrage.
  • Un robot Sirius sur le même réseau Wi-Fi que votre PC.
  • Un navigateur récent, la vidéo passe par WebRTC.

Aucune dépendance à installer à la main : le lanceur récupère fastapi, uvicorn, websockets et httpx à la première utilisation, une fois pour toutes, en une trentaine de secondes.

Se connecter, en trois étapes

  1. Allumez le robot et vérifiez qu'il est sur le même réseau Wi-Fi que votre PC. Son adresse IP s'affiche sur l'écran de sa tête, menu Réseau.
  2. Décompressez l'archive et double-cliquez demarrer.bat. Une fenêtre noire s'ouvre, affiche le numéro de version, puis votre navigateur s'ouvre seul sur l'interface. Si ce n'est pas le cas, allez sur http://127.0.0.1:8787.
  3. Saisissez l'adresse IP du robot dans l'interface, puis cliquez « Connecter ». Elle est mémorisée : les fois suivantes, un clic sur l'adresse récente suffit.
L'écran de connexion de Sirius Studio, avec le champ où saisir l'adresse IP du robot
L'étape 3 : le champ d'adresse. Pour tout arrêter, fermez la fenêtre noire.

S'il ne bouge pas

Par ordre de fréquence, et les deux premières causes sont les pièges 1 et 3 de cette page :

  • Il bouge les pattes sans avancer : il est en mode Bureau, basculez sur Sol dans Modes et comportement. Ou la vitesse demandée est trop faible : montez le curseur.
  • Il ne réagit à rien : soit il dort, jouez une action pour le réveiller, soit le mode autonome est actif et annule vos commandes, coupez-le.
  • « Impossible de joindre le robot » : vérifiez l'adresse IP, et que le PC et le robot sont bien sur le même réseau.
  • « Python introuvable » : réinstallez Python en cochant « Add Python to PATH ».
  • Voir ce qui se passe : l'API du pont est documentée et testable sur http://127.0.0.1:8787/docs.

Le kit est fourni sans garantie : il pilote du matériel qui peut tomber ou se coincer. Les lanceurs sont des fichiers .bat, donc Windows ; le pont Python est multiplateforme mais n'a été testé nulle part ailleurs. Un bug, une remarque, un résultat d'essai : écrivez-nous, c'est ainsi que cette page progresse.

16Sécurité

  • Le robot ne voit rien derrière lui. Le ToF regarde vers l'avant et il n'existe aucun capteur arrière. Toute marche arrière est aveugle : vitesse réduite et durée bornée.
  • Les moteurs chauffent. Évitez les sessions très longues en continu, d'autant que la remontée de température est muette sur ce firmware.
  • Ne modifiez pas les fichiers du firmware sans sauvegarde. Travaillez avec vos propres scripts dans /root/ ou un dossier à vous.
  • Gardez un arrêt d'urgence sous la main, dans un terminal déjà ouvert. Publier des consignes nulles en boucle est le moyen le plus fiable de tout arrêter.
  • La voie UDP Play_Keyframe court-circuite les protections du robot. Ne l'utilisez qu'après avoir relevé les limites articulaires, et jamais pour un premier essai.

Surveiller la charge moteur

L'événement motor-load remonte 14 charges à 1 Hz, en pour mille de PWM, sur une plage de ±1000. C'est le seul instrument fiable dont on dispose pour détecter une butée, puisque les sondes de température sont muettes. Mesures réelles :

ConditionPic observé
Repos120 à 162 ‰
Marche 0,06 m/s540 ‰
Marche à vitesse maximale530 ‰
Rotation à vitesse maximale540 ‰
Moteur en butée950 à 985 ‰, soutenus

Le firmware applique par ailleurs ses propres garde-fous, actifs en permanence : écrêtage des angles articulaires, écrêtage de l'espace de travail, seuil de saut articulaire à 0,5 rad, régime moteur plafonné à 200 tr/min. Une consigne hors domaine est donc écrêtée plutôt que poussée contre la butée. Cela ne dispense d'aucune précaution, mais c'est un filet de plus.

Enfin, la documentation officielle mentionne un mode Emergency_Stop via Mode_Switch, que nous n'avons pas encore testé et que nous avions reconstruit à la main. Si vous le validez, écrivez-nous.

Haut de page