Ce dossier contient un pipeline LLM → JSON strict → Behavior Tree XML Nav2 et un script de lancement Gazebo TurtleBot3 + Nav2 qui exécute le Behavior Tree généré.
L’objectif est de recevoir une mission en langage naturel, de la convertir via un LLM (Mistral) en étapes structurées contraintes, puis de garantir que le XML produit est compatible avec les nœuds BT disponibles côté Nav2.
behavior_trees/: exemples de BT Nav2 (XML)behavior_trees/__generated/: sortie des BT générés (XML)params/nav2_params.yaml: paramètres Nav2 (dontbt_navigator.plugin_lib_names)maps/: maps de simulationscript/:bt_nodes_catalog.json: catalogue des compétences/nœuds autorisés (ports + description)gen_turtlebot_mission_bt.py: générateur prompt → LLM → JSON → XMLvalidate_bt_xml.py: validateur statique post-génération (XML/structure/ports/blackboard)run_turtlebot3_nav2_generated_bt.sh: pipeline Gazebo + Nav2 utilisant le BT généré
Environnement cible: ROS 2 Humble (Linux/WSL2 recommandé).
À installer/configurer:
- ROS 2 Humble
- Nav2 (
nav2_bringup,nav2_bt_navigator, etc.) - TurtleBot3:
turtlebot3_gazebo- modèles TB3 (ex:
burger)
- Un workspace ROS 2 “principal” (par défaut
ROS_MAIN_WS=$HOME/ros2_ws) déjà compilé avec les dépendances.
Le script BT_Navigator/script/run_turtlebot3_nav2_generated_bt.sh source:
/opt/ros/humble/setup.bash- puis optionnellement
$ROS_MAIN_WS/install/setup.bash
Le générateur (gen_turtlebot_mission_bt.py) appelle un endpoint OpenAI-compatible via le client Python openai.
À prévoir:
- une clé API:
LLM_API_KEY - un modèle:
LLM_MODEL(défaut:mistral-large-latest) - une base URL:
LLM_API_BASE(défaut:https://api.mistral.ai/v1)
Dépendances Python:
openai(obligatoire)python-dotenv(optionnel, pour charger un fichier.env)
Le LLM n’a pas le droit de produire du XML.
Il doit produire uniquement une liste JSON d’étapes de la forme:
[
{ "skill": "Wait", "params": { "wait_duration": 2.0 }, "comment": "Stabilisation" },
{ "skill": "Spin", "params": { "spin_dist": 1.57 }, "comment": "Tourner ~90°" }
]Le script:
- refuse tout
skillnon listé dansscript/bt_nodes_catalog.json - vérifie les ports requis (
optionaldans le catalogue = non requis) - génère ensuite un XML Nav2 lisible et compatible
Depuis la racine du repo:
python3 BT_Navigator/script/gen_turtlebot_mission_bt.py --prompt "Attends 2s, tourne de 90°, attends 1s"Sortie par défaut (timestampée):
BT_Navigator/behavior_trees/__generated/turtlebot_mission_generated_YYYYMMDDhhmmss.xml
Options utiles:
--output <path>: choisir le chemin de sortie--dry-run: affiche sur stdout sans écrire de fichier--model,--api-base,--api-key: override des paramètres LLM--mode {interactive,fail-fast,auto-rewrite}: gestion prompts longs/ambigus (défaut:interactive)--max-prompt-chars 2000: budget de taille du prompt avant appel LLM--max-clarify-rounds 3: nombre max de boucles de clarification (mode interactif)--guardrails {off,heuristic,hybrid}: guardrails sécurité (défaut:hybrid)--moderation-api-key,--moderation-api-base,--moderation-model: modération optionnelle (OpenAI-compatible)--validate-xml: valide le BT XML généré viavalidate_bt_xml.pyavant écriture--strict-validate-attrs,--strict-validate-blackboard: options strictes de validation
Script principal:
BT_Navigator/script/run_turtlebot3_nav2_generated_bt.sh
Exemple:
bash BT_Navigator/script/run_turtlebot3_nav2_generated_bt.sh "Attends 2s, tourne de 90°"Ce script:
- génère un BT XML via
gen_turtlebot_mission_bt.py - crée un
params_filetemporaire (/tmp/nav2_params_generated_bt.yaml) où:bt_navigator.default_nav_to_pose_bt_xmlpointe vers le XML généré
- lance ensuite:
- Gazebo TB3 world
nav2_bringup localization_launch.py- publie
/initialpose(AMCL) nav2_bringup navigation_launch.py- (optionnel) RViz
--auto: ignore la confirmation “Valider le BT ?”--no-rviz: ne lance pas RViz--send-goal: envoie automatiquement un goal Nav2 (déclenche l’exécution du BT)--validate-bt: valide le BT XML avant simulation (par défaut: activé)--no-validate-bt: désactive la validation statique avant simulation--strict-validate-attrs: mode strict (attributs inconnus = erreur)--initial-pose "x,y,yaw": pose initiale AMCL (map), ex:"0.0,0.0,0.0"--goal-pose "x,y,yaw": goal/navigate_to_pose, ex:"2.0,1.0,0.0"
Note:
- Sans RViz, le script active automatiquement
SEND_GOAL=1(sinon la mission ne démarre pas).
ROS_MAIN_WS: workspace ROS principal (défaut:$HOME/ros2_ws)MAP_FILE: map utilisée (défaut:BT_Navigator/maps/exploration_map.yaml)NAV2_PARAMS_SRC: yaml nav2 source (défaut:BT_Navigator/params/nav2_params.yaml)GENERATED_BT_XML: chemin du XML de mission (défaut:BT_Navigator/behavior_trees/__generated/turtlebot_mission.xml)
-
1) Prompt utilisateur (langage naturel)
Exemple: “Aller à un goal, attendre, tourner…” -
2) Appel LLM (Mistral)
Le système prompt force une sortie JSON uniquement et limiteskillà la liste du catalogue. -
3) Validation JSON
Le script vérifie:- structure (liste d’objets)
skillautorisés- paramètres requis présents
-
4) Génération XML Nav2
Le script produit un XMLBehaviorTree.CPPcomposé uniquement de tags connus (ex:Wait,Spin,SubTree NavigateToPoseWithReplanningAndRecovery, etc.). -
5) Lancement Nav2
Le launcher remappebt_navigator.default_nav_to_pose_bt_xmlvers le BT généré via un params yaml temporaire. -
6) Déclenchement mission
Le BT “default_nav_to_pose” s’exécute quand un goalNavigateToPoseest envoyé:- via RViz (Nav2 Goal), ou
- via
--send-goal(script)
-
Le robot ne bouge pas:
- vérifier qu’une pose initiale AMCL a bien été publiée (
/initialpose) - vérifier qu’un goal a bien été envoyé (RViz ou
--send-goal)
- vérifier qu’une pose initiale AMCL a bien été publiée (
-
Erreur “Réponse LLM non JSON”:
- le LLM n’a pas respecté la contrainte; réduire la complexité du prompt et relancer
- ou utiliser
--mode interactive(défaut) qui proposera des clarifications / réparations contrôlées
-
Erreur “Guardrails: prompt bloqué”:
- le prompt contient des éléments détectés comme sensibles/malveillants (injection, secrets/PII, haine/violence)
- en interactif, fournissez une version “mission robot uniquement” sans données confidentielles
-
Skill non autorisé:
- ajouter la compétence dans
script/bt_nodes_catalog.json+ implémenter sa traduction XML si nécessaire
- ajouter la compétence dans
Le script de lancement exécute désormais une validation statique du BT avant Gazebo/Nav2.
Validation manuelle:
python3 BT_Navigator/script/validate_bt_xml.py BT_Navigator/behavior_trees/__generated/turtlebot_mission.xmlUn exemple volontairement invalide est fourni pour déclencher des issues:
BT_Navigator/behavior_trees/__generated/invalid_bt_for_validator_demo.xml