Modélisation dans onshape:
Commencer par créer un document onshape. Dans celui-ci nous allons modéliser les pièces du vérin dans une position statique dans un onglet « parts », vous pouvez accéder au document sur onshape:
- commencer par la base:
- on va l’utiliser deux fois pour l’assemblage, on poursuit avec la partie mâle du vérin:
- puis la partie femelle:
- Dans un nouvel onglet « part », on va créer un objet composite « frame »:
- Cet objet va nous permettre de placer des points de repère pour la suite: ce sont trois cylindres qui sont ensuite regroupé au sein d’un objet composite que l’on nomme « frame ». Pour l’utiliser dans les assemblages, on ajoute à cet objet un « mate connector » sur l’origine (orienté comme votre objet). Par cohérence, faites attention à avoir z normal au plan top, x normal au plan right et y normal au plan front. Par la suite, on copiera/utilisera ce repère pour d’autres projets 🙂
- ensuite on passe à l’assemblage: on ajoute deux fois la bases, les deux parties du vérin et trois frames:
- de là, on peut ajouter des contraintes:
- Le but étant de construire un URDF à partir de l’assemblage, il faut garder en tête une vision arborescente de notre assemblage: on a une base qui à des enfants (qui auront possiblement des enfants etc…). Cette relation entre les objets doit être suivie dans la façon de faire les contraintes: le premier objet de la contrainte être l’enfant puis le parent. Les explications détaillées sont sur https://onshape-to-robot.readthedocs.io/en/latest/design.html
- On va commencer par un de élément « base »: on lui fixe une frame à son centre (cela nous servira de repère plus tard) avec l’outil « fastened mate » et on nomme celle relation « frame_root »:
- On ajoute une contrainte en rotation entre la base et la partie mâle du vérin, on nomme la relation dof_passive_1:
- On peut ajouter une contrainte de glissement linéaire (slider mate) entre les deux parties du vérin. On en profite pour ajouter des limites en Z. Ensuite, on va nommer (colonne de gauche) cette liaison « dof_cylinder »
- Avec la contrainte « fixe » (fastened mate), nous allons fixer deux frames: une à l’extrémité femelle du vérin (on nomme la relation frame_a1) et l’autre sur l’axe de rotation de la deuxième base (on nomme la relation frame_a2):
- On repart de la base (la racine du robot) pour ajouter une liaison de rotation avec la deuxième base:
- On termine en ajouter une dernière liaison rotative qui va « boucler » le vérin. On peut alors tester notre ensemble dans onshape.
Passage en URDF: onshape-to-robot
onshape-to-robot permet de transformer votre assemblage en URDF, format qui nous permettra de charger la géométrie du robot dans un programme et ainsi de faire des simulation par exemple.
Une fois onshape-to-robot installé, créer un répertoire « robot » et dans ce répertoire, ajouter un fichier « config.json » avec le contenu ci-dessous:
{
"documentId": "00d2aaf32880ba0d7fb8dda2",
"outputFormat": "urdf",
"useScads": true,
}
Le documentId est récupéré via l’URL de votre document onshape. Il faudra également que vous créiez une clé d’accès sur https://dev-portal.onshape.com/ (voir les explications sur onshape-to-robot)
Dans le répertoire parent on peut alors générer l’URDF:
Pour améliorer les choses pour la suite (et éviter les warning), allez dans onshape et dans l’onglet part sélectionnez vos éléments (colonne de gauche) et affecter leur un matériau (clique droit, assign material).
Pour terminer cette partie, charger votre urdf dans l’exemple pybullet de onshape-to-robot:
onshape-to-robot-bullet -f robot
Si vous essayez de bouger le vérin, ça se passe pas très bien car la liaison « loop_a » n’a pas été inclue dans l’URDF (elle ne commence pas par « dof »). Seulement, on ne peut pas fermer la boucle de contraintes dans l’URDF (c’est une représentation en arbre). On va donc devoir fermer la boucle après le chargement…
placo: cinématique et plus…
L’étape suivante consiste à résoudre le mouvement: étant donné l’élongation du vérin, quels sont les angles et positions des pièces. Pour cela, nous allons utiliser placo:
import time
import numpy as np
import pinocchio as pin
import placo
from placo_utils.visualization import robot_viz, frame_viz, point_viz, robot_frame_viz
robot = placo.RobotWrapper("robot/")
viz = robot_viz(robot)
solver = robot.make_solver()
joints_task = solver.add_joints_task()
joints_task.configure("joints", "soft", 1.0)
constraint = solver.add_relative_position_task("a1", "a2", np.array([0., 0., 0.]))
constraint.configure("constraint", "hard", 1.0)
constraint.mask.set_axises("xy")
t:float = 0.0
dt:float = 0.01
while True:
viz.display(robot.state.q)
joints_task.set_joints({"cylinder": np.sin(t)*0.02})
robot.update_kinematics()
solver.solve(True)
solver.dump_status()
t += dt
time.sleep(dt)
Commencer par suivre les instructions d’installation de placo et de ses dépendances.
- La ligne
robot = placo.RobotWrapper("robot/")
va charger votre urdf qui est dans le répertoire « robot/ ». On obtient un objet robot qui représente maintenant le robot. - La ligne suivante:
viz = robot_viz(robot)
est optionnelle et créée une visualisation 3D basée sur meshcat de votre robot qui sera accessible via votre navigateur. Il faudra appeléeviz.display(robot.state.q)
pour mettre à jour la visualisation du robot quand vous modifiez l’état de celui-ci. - Ensuite nous allons instancier un solveur:
solver = robot.make_solver()
. C’est lui qui va résoudre les questions géométriques (et plus) en fonction de contraintes. joints_task = solver.add_joints_task()
etjoints_task.configure("joints", "soft", 1.0)
ajoute au solveur la demande de calculer les valeurs de liaisons.constraint = solver.add_relative_position_task("a1", "a2", np.array([0., 0., 0.]))
constraint.configure("constraint", "hard", 1.0)
constraint.mask.set_axises("xy")- Ici, on ferme la boucle du vérin: comme l’URDF ne peut contenir de boucle et que notre modèle en contient une, on va créer une tache au solveur qui est de faire que nos deux frames a1 et a2 soient positionnées au même endroit (la position relative des deux est nulle). On termine en précisant au solveur que cela ne concerne que le plan xy.
- Pour finir, on va boucler à une fréquence de 100hz (dt vaut 0.01) et demander à fixer la valeur d’élongation de notre vérin puis mettre à jour le robot et faire tourner le solveur.
Voilà une base de travail pour un robot composé de vérin. On peut maintenant modifier notre solveur et demander à la frame de bout de vérin d’atteindre une cible: le solveur nous indiquera l’élongation du vérin nécessaire et l’erreur de distance à la cible.
Remarque : une vidéo a été faite par Grégoire Passault sur youtube (lien)