Aller au contenu

Le monde warehouse

Le projet final se déroule dans un entrepôt simulé (Gazebo Ionic, gz-sim 9) où le manipulateur mobile LeKiwi + SO-101 détecte un objet, le saisit sur une station de prélèvement, puis le transporte vers une zone de dépôt liée à sa classe. Cette page décrit le monde et son outillage — les interfaces, le detector et le coordinateur restent à votre charge (Jours 1, 4 et 5).

Entrepôt de 15 × 12 m, murs d’enceinte + cloison (obstacles pour le LiDAR / Nav2), rayonnages, piliers et caisses (décor de navigation), plus :

ÉlémentRôlePosition (monde)
pick_stationTable basse où apparaissent les objets à saisir.(0, 4.6), plateau à z ≈ 0.15 m
zone_a (rouge)Dépôt — classe metal (exemple)(-5, 3.5)
zone_b (vert)Dépôt — classe plastic (exemple)(5, 3.5)
zone_c (bleu)Dépôt — classe paper (exemple)(0, -3.5)

Les trois zones sont éloignées les unes des autres pour forcer la navigation Nav2 entre la station et le dépôt. Le mapping classe → zone ci-dessus n’est qu’une proposition : c’est votre mission_coordinator qui le fixe (via un YAML).

Une caméra RGB-D est montée sur le poignet du SO-101 (arm_wrist_link) et regarde vers la pince. Elle est pontée automatiquement par sim_full.launch.py :

TopicType
/wrist_camera/image (alias /camera/image_raw)sensor_msgs/Image
/wrist_camera/camera_info (alias /camera/camera_info)sensor_msgs/CameraInfo
/wrist_camera/depth_image (alias /camera/depth_image)sensor_msgs/Image
/wrist_camera/pointssensor_msgs/PointCloud2

L’alias /camera/* (option camera_alias:=true, activée par défaut) republie la même caméra sous le nom d’interface attendu par votre detector du Jour 4. Le frame_id est wrist_camera_optical_frame (convention REP-103), relié au TF du bras.

  1. Compiler & sourcer :

    Fenêtre de terminal
    cd ~/ros2_bootcamp_ws && colcon build --packages-select lekiwi_bringup
    source install/setup.bash
  2. Lancer le monde + le robot + la caméra :

    Fenêtre de terminal
    ros2 launch lekiwi_bringup warehouse_sim.launch.py
    # variantes : headless:=true (sans GUI) | camera_alias:=false | spawn:=true
  3. Vérifier les flux (autre terminal) :

    Fenêtre de terminal
    ros2 topic hz /scan
    ros2 topic hz /camera/image_raw
    ros2 topic echo /camera/camera_info --once

warehouse_sim.launch.py est le point d’entrée unique. Les options sont combinables :

ArgumentDéfautEffet
headless:=truefalseGazebo sans GUI
camera_alias:=falsetruene pas republier /camera/*
spawn:=truefalseposer un objet au démarrage (avec object_type:=…)
moveit:=truefalsedémarrer MoveIt (move_group)
rviz:=truefalseRViz MoveIt (nécessite moveit:=true)
nav2:=truefalsedémarrer localisation + Nav2
slam_mode:=…mapmap (SLAM live) | localize | amcl (cf. ci-dessous)
map_name:=…carte pour localize / amcl (ex. warehouse)
Fenêtre de terminal
# Tout-en-un : sim + MoveIt + RViz + Nav2 (AMCL sur la carte warehouse)
ros2 launch lekiwi_bringup warehouse_sim.launch.py \
moveit:=true rviz:=true nav2:=true slam_mode:=amcl map_name:=warehouse

nav2:=true démarre Nav2 (planner + controller) et la localisation choisie par slam_mode :

slam_modeLocalisationCarte
map (défaut)slam_toolbox mappingconstruite en direct
localizeslam_toolbox localizationcarte sauvegardée (map_name)
amclnav2_map_server + AMCLcarte statique (map_name)

Une carte warehouse est fournie (lekiwi_navigation/maps/warehouse/). En mode amcl / localize, donnez la pose initiale dans RViz (« 2D Pose Estimate ») ou via /initialpose : tant qu’AMCL n’est pas localisé, des avertissements costmap « odom → base_footprint » au démarrage sont normaux.

Les objets ne sont pas pré-placés : on les spawne à la demande avec spawn_object.launch.py (qui démarre le pont de services gz et le nœud de spawn). Le monde doit déjà tourner.

Fenêtre de terminal
# Cube de couleur (détection HSV) — classe = couleur
ros2 launch lekiwi_bringup spawn_object.launch.py object_type:=cube_color color:=green
# Cube ArUco (pose 6D + classe = ID du marqueur)
ros2 launch lekiwi_bringup spawn_object.launch.py object_type:=cube_aruco aruco_id:=1
# Déchets simples (scénario de tri) : can=metal, bottle=plastic, carton=paper
ros2 launch lekiwi_bringup spawn_object.launch.py object_type:=waste_can
ros2 launch lekiwi_bringup spawn_object.launch.py object_type:=waste_bottle count:=2
# Rejouer une mission proprement : supprime puis re-spawne
ros2 launch lekiwi_bringup spawn_object.launch.py action:=respawn name:=pick_object_0
# Modèle arbitraire (SDF/URDF) — branchez vos propres objets
ros2 launch lekiwi_bringup spawn_object.launch.py object_type:=sdf model_path:=/chemin/model.sdf
object_typeDescriptionClasse par défaut
cube_colorCube 4 cm coloré (color:=red/green/blue/yellow ou "r g b a")la couleur
cube_arucoCube 4 cm, marqueur ArUco DICT_4X4_50 sur le dessusl’aruco_id
waste_canCanette (cylindre métal)metal
waste_bottleBouteille plastique (cylindre + col)plastic
waste_cartonCarton (boîte brune)paper
sdfModèle arbitraire via model_pathnom du fichier
Pour……éditer
Changer d’objetobject_type / color / aruco_id / model_pathargument de launch
Poser à un endroit précispose:="x y z [yaw]" (vide ⇒ aléatoire sur la station)argument de launch
Forcer la classeclass_id:=… (sinon dérivée du type / couleur / aruco_id)argument de launch
Changer la zone d’apparitionstation_xy, station_z, jitterparamètres du spawn
Repositionner la stationla <pose> du modèle pick_station + station_xyworlds/warehouse.sdf
Déplacer / ajouter une zonela <pose> (ou un nouveau modèle) zone_*worlds/warehouse.sdf
Générer un nouveau marqueur ArUcoros2 run lekiwi_bringup generate_aruco.py --id N

Le monde fournit tout le terrain de jeu ; à vous de brancher vos briques du Jour 1 :

  1. Detector (Jour 4) : s’abonne à /camera/image_raw, publie Detection.msg (class_name + class_id + score + boîte 2D + geometry_msgs/Pose pose) sur /detections.

  2. Bras (Jour 3) : service PickRequest.srv (Pose targetbool success) avec MoveIt 2 (lekiwi_manipulation_moveit_config, groupe arm, poses home / ready / gripper_open / gripper_close).

  3. Navigation (Jour 2) : action NavigateToPose (Nav2 sur LeKiwi) vers la zone liée à la classe.

  4. Coordinateur (Jour 5) : orchestre détection → pick → navigation → dépôt, piloté par un YAML classe → zone.

Cours conçu et animé par Etienne Schmitz