Description du robot

Le paquet ratbot_description (dans ros2_ws/src/) contient la description URDF du robot, écrite en xacro : urdf/ratbot.urdf.xacro.

Contenu du modèle

Le modèle décrit une base différentielle :

  • base_footprint : projection du robot au sol (racine du modèle) ;

  • base_link : le châssis ;

  • left_wheel_link / right_wheel_link : les roues motrices (articulations continuous) ;

  • caster_link : le point d’appui.

S’ajoutent une frame imu_link, un lidar RPLidar optionnel (laser_link, activable par use_lidar:=true|false) et un capteur de distance multizone VL53L5CX optionnel à l’avant (tof_link et tof_optical_link, activable par use_tof:=true|false).

Où est l’origine

base_link est sur l’axe des roues, à mi-chemin entre elles (REP-105 pour une base différentielle) : c’est le point autour duquel le robot tourne, et celui que l’odométrie intègre. Le reste est placé par rapport à lui, d’après le plan du châssis :

pièce

x

remarque

roues

0

à ±70 mm

centrale (imu_link)

−45 mm

montée à l’envers et tournée : X vers la droite, Y vers l’arrière, Z vers le bas, soit rpy="π 0 −π/2"

lidar (laser_link)

−45 mm

à l’aplomb de la centrale, tourné d’un demi-tour : rpy="0 0 π". Mesuré le 2026-10-04 : une boîte devant le robot sortait à +172° du scan, une boîte à sa gauche à −94° (rotation pure, pas de miroir). Sans cette correction, la carte se construirait à l’envers. Contre un mur droit, il reste 1,2° : la précision d’un robot posé parallèle à l’œil, non corrigée. Vérification par robot : lidar-check (ratbot_calibration/lidar/), voir la page utilisateur « Vérifier le montage du lidar »

capteur ToF (tof_link)

+35 mm

collé à l’avant de la plaque, au centre, à 10 cm du sol, pointé droit devant. Position prévue, pas encore mesurée (2026-10-14) : à reprendre une fois le capteur monté, l’inclinaison surtout — un degré d’erreur de tangage déplace le sol vu à 1 m de 1,7 cm, assez pour en faire un obstacle. tof_optical_link en est le repère caméra (z devant, x à droite, y en bas), celui de l’image sensors/tof/depth. Le visuel est derrière l’origine : le capteur simulé voit les visuels, un boîtier devant ses rayons l’aveuglerait

centre de la plaque

−50 mm

plaque de 158 mm

bille (caster_link)

−101,34 mm

Warning

Jusqu’au 2026-09-27, ``base_link`` était au centre de la plaque, 50 mm derrière l’axe. L’odométrie déplaçait l’axe et l’appelait centre de la plaque : pendant une rotation sur place, chaque scan était replacé jusqu’à 10 cm à côté de sa vraie position — de quoi dédoubler les murs d’une carte. Et la centrale était déclarée à l’endroit : l’EKF fusionnait un lacet de signe inverse. Les deux sont corrigés ; une carte faite avant est à refaire.

L’empreinte Nav2 suit. Un rectangle exact (3 cm devant l’axe à 13 cm derrière, sur ±8 cm), en place du 2026-09-27 au 2026-10-18, laissait Nav2 approcher une planche puis faire demi-tour dessus : Regulated Pure Pursuit ne vérifie pas le balayage d’une rotation sur place, et le coin arrière décrit un cercle de 15,3 cm. Contact sur le robot réel le 2026-10-16. Depuis, l’empreinte est un disque de 16 cm centré sur l’axe des roues (robot_radius: 0.16 dans ratbot_nav/config/nav2.yaml) : le robot garde toujours la place de tourner. Au banc, la marge pendant un demi-tour près d’une planche passe de 5 à 16 cm ; un but à moins de 16 cm d’un obstacle est ramené par le planificateur (tolerance: 0.25) au point sûr le plus proche, et Nav2 l’annonce atteint. Le labyrinthe (ouvertures de 38 cm) devient presque impossible.

Les dimensions (châssis, rayon et entraxe des roues, positions) sont définies comme propriétés xacro en tête de fichier, d’après le plan mécanique (Châssis et mécanique). Les visuels utilisent les maillages DAE (voir ci-dessous) ; les collisions restent des primitives (boîte/cylindre), et use_mesh:=false bascule aussi les visuels en primitives. Exception : les roues de collision sont des sphères, pas des cylindres — un cylindre couché touche le sol par ses deux bords, et Gazebo voyait un entraxe de 16 cm au lieu de 14 (+14 % de rotation comptée par les roues). Seul Gazebo lit les collisions : sans effet sur le vrai robot.

TODO :

  • ajouter la frame du marqueur ArUco (surface supérieure du robot), utile à tout système de localisation externe ;

  • renseigner les inerties réelles (actuellement estimées).

Maillages 3D : où mettre quoi

Les formats CAO (STEP) ne sont pas lisibles par RViz/Gazebo : il faut distinguer la source de conception des maillages exportés.

Fichier

Emplacement

Rôle

*.step / *.stp

conception/3d/

La source CAO, éditable — jamais référencée par l’URDF.

*.dae (Collada) ou *.stl

ros2_ws/src/ratbot_description/meshes/

Les exports pour l’URDF : DAE pour le visuel (couleurs), STL simplifié pour la collision.

L’URDF les référence ainsi :

<mesh filename="package://ratbot_description/meshes/chassis.dae"/>

Règles d’export (depuis FreeCAD, Fusion 360…) :

  • unités : mètres — les CAO travaillent en millimètres, un maillage exporté en mm apparaîtra 1000 fois trop grand (sinon, scale="0.001 0.001 0.001" dans la balise <mesh>) ;

  • origine et orientation du maillage cohérentes avec la frame du link ;

  • pour la collision, préférer une version simplifiée (voire garder les primitives boîte/cylindre actuelles) : Gazebo calcule les contacts dessus, la finesse ne sert à rien.

Placement d’un maillage

Les maillages CAO ont souvent leur origine sur un coin (ou sur la carte) et un axe vertical Y_UP. Le placement se règle sans toucher au fichier, via des propriétés en tête de l’URDF :

  • struct_mesh_xyz / struct_mesh_rpy : position et orientation de la structure dans la frame base_link ;

  • wheel_mesh_rpy : orientation de la roue (son axe de rotation doit suivre l’axe Y du joint) ;

  • mesh_scale : facteur d’échelle (voir le piège des unités ci-dessous).

L’interrupteur use_mesh:=false revient aux primitives boîte/cylindre — pratique pour vérifier un problème d’alignement.

Gazebo reçoit toujours les primitives. spawn_robot.launch.py pose le modèle avec use_mesh:=false (create -string), alors que robot_description, donc RViz, garde les maillages. Le lidar simulé (gpu_lidar) est un capteur de rendu : il mesure les visuels, pas les collisions. Or le haut de ratbot_struct_asembly.dae monte à ~0,204 m dans base_link, au-dessus du plan de balayage (~0,202 m). Avec le maillage, les rayons partaient de l’intérieur de la structure, et le lidar devenait aveugle selon l’orientation du robot, jusqu’à 0 rayon sur 360 : cartographie figée, exploration en boucle (mesuré le 2026-10-11). Avec les primitives : 360 sur 360 à toute orientation.

Nettoyage des exports DAE (fix_dae.py)

Les DAE issus de la CAO ou de MeshLab tombent régulièrement sur trois pièges qui cassent le rendu dans RViz et/ou Gazebo. Le script meshes/fix_dae.py les corrige en une passe (idempotent, valide le XML avant d’écrire) ; à relancer après chaque ré-export.

Piège

Symptôme / cause

Correctif

Balise <unit>

Double mise à l’échelle : le loader applique l’unité et le mesh_scale de l’URDF → maillage microscopique, invisible.

<unit> supprimée.

transparency=1

Les exports CAO écrivent transparency=1 pour « opaque » (convention A_ONE), qu’Assimp/RViz interprète comme totalement transparent → maillage invisible.

<transparency> supprimée.

Aucun matériau

MeshLab strippe les matériaux → la pièce apparaît blanche dans Gazebo (RViz est plus tolérant).

Matériau uniforme injecté et lié (couleur configurable).

cd ros2_ws/src/ratbot_description/meshes
python3 fix_dae.py ratbot_struct_asembly.dae          # nettoie + injecte le gris
python3 fix_dae.py wheel.dae --no-material             # nettoie sans toucher au bleu du DAE
python3 fix_dae.py ratbot_struct_asembly.dae --color 0.5 0.55 0.6   # couleur personnalisée

Note

MeshLab ne conserve pas les matériaux : un ré-export redonne une belle géométrie mais sans couleur, et fix_dae.py réinjecte un gris uniforme. Pour un vrai rendu multi-couleurs, passer plutôt par Blender (import DAE → Decimate → export DAE), qui préserve les matériaux.

Ne committer (et donc n’installer via colcon) que les maillages réellement référencés par l’URDF : supprimer les copies de sauvegarde ou de travail qui traînent dans meshes/.

Visualisation

Le launch display.launch.py permet de visualiser le modèle :

source ros2_ws/install/local_setup.bash
ros2 launch ratbot_description display.launch.py

Il démarre robot_state_publisher, joint_state_publisher_gui et RViz. L’argument gui:=false ne lance que robot_state_publisher (utile sur le robot, sans écran).

Dans RViz, ajouter un affichage RobotModel (topic /robot_description) et choisir base_footprint comme Fixed Frame.

Dépendances : xacro, robot_state_publisher, et pour la visualisation joint_state_publisher_gui et rviz2.