Les revolute joint reviendront forcément dans les expérimentations futures, mais commençons par des exemples simples. Comme un distance Joint le revolute joint a besoin de deux body pour fonctionner, donc deux objet présents dans le monde 2D de Box2D. Il lui faut aussi un point d’accroche sur les deux objets. C’est que l’on va appeler le Hinge. Ensuite dans les paramètres on pourra définir la force de ce hinge et choisir d’actionner un moteur ou de laisser la rotation libre. Les deux cas d’applications seront une sorte de moulin qui doit interagir en présence de particules ayant un poids, ainsi que l’implémentation d’une voiture avec les roues accrochés au corps de la voiture par un revolute joint.
- Le moulin à particules
https://github.com/Thibautomaton/RevoluteJointWithParticles/tree/main
On commence par créer un objet Windmill :
windmill = Windmill(WIDTH/2, HEIGHT-150, world)
On a ce qui semble la localisation et world, le monde Box2D afin de créer des body et des joints.
Toujours dans le main on a l’événement keypressed qui déclenche dans le code :
if pygame.key.get_pressed()[pygame.K_m]:
windmill.rjd.motorEnabled=True
else:
windmill.rjd.motorEnabled=False
On accède à l’attribut rjd de Windmill. C’est donc le revolute joint qui est en attribut de windmill. motorEnabled=True a pour effet d’activer le moteur du revolute joint lorsqu’on maintient la touche “m” enfoncée.
Voyons comment on initialise le revolute joint dans le constructeur de windmill :
self.box1 = Box(x_, y_, 250, 20, False, world)
self.box2 = Box(x_, y_+35, 20, 80, True, world)
self.rjd = world.CreateRevoluteJoint(
bodyA =self.box1.body,
bodyB =self.box2.body,
anchor = (self.box1.body.worldCenter),
motorSpeed = math.pi,
maxMotorTorque=10000.0,
enableMotor=False
)
On a donc créé deux objets qu’on imagine être des Static ou des Dynamic Bodies étant donné qu’on leur passe world dans leur initialisation. On leur donne aussi les coordonnées de Windmill, ainsi que des dimensions.
Dans CreateRevoluteJoint on donne les body des deux objets comme pour le distance joint.
anchor doit être une position, ici on donne le centre du premier body. Les autres arguments concernent le moteur. Ici on impose pas de limite au moteur, l’objectif d’un moulin étant d’effectuer des rotations complètes. On lui donne une vitesse, le torque est la force du moteur et donc sa capacité d’aller à l’encontre d’objet lourds. On laisse enableMotor inactif puisqu’on attend l’input de l’utilisateur pour actionner le moteur du revolute joint.
Rapidement, Box ressemble beaucoup à ce qu’on a fait avec bridge et avec bordure, on lui passe aussi un paramètre pour savoir si on initialise un Static ou un Dynamic Body et la forme est un polygonShape.
class Box():
def __init__(self, x_, y_,w_, h_, static, world):
self.x = x_
self.y = y_
self.w = w_
self.h = h_
self.display_surface = pygame.display.get_surface()
if static:
self.body = world.CreateStaticBody(
position = pixelToWorld((self.x, self.y))
)
else:
self.body = world.CreateDynamicBody(
position = pixelToWorld((self.x, self.y))
)
box2dW = scalarPixelToWorld(self.w/2)
box2dH = scalarPixelToWorld(self.h/2)
ps = polygonShape(
box = (box2dW, box2dH)
)
self.body.CreateFixture(
shape =ps,
density = 1,
friction = 0.3,
restitution = 0.5
)
Les particules sont ajoutées toutes les trois frames en haut de l’écran :
k+=1
if k%3==0:
particles.append(Particle(random.uniform(WIDTH/2-200, WIDTH/2 + 200), 0, random.uniform(1, 10), world))
- L’invention de la roue
https://github.com/Thibautomaton/carRevolute/tree/main
Pour faire rouler notre voiture on va reprendre le travail qui a été fait sur bordure afin d’avoir un sol solide qui n’est pas sujet à modifications.
boundary = Boundary(world)
car = Car(WIDTH-170, 250, world)
On crée un objet boundary et un objet car. Boundary définit ses contours dans la fonction __init__
On crée une liste surface de vertex 2D, qui sont convertis pour former la chainShape qui ira dans CreateFixture
for surface in self.surface:
vertices.append(pixelToWorld(surface))
chain = chainShape(vertices =vertices)
self.ground_body.CreateFixture(
shape = chain,
density = 1,
friction = 1,
restitution = 0.5
)
On sait déjà créer une bordure. Quand est-il d’une voiture ?
On a vu avec Windmill que pour qu’il y ait un revolute joint il faut deux corps, deux objets distincts dans le monde 2D de Box2D qui soient reliés par un hinge.
Dans le cas de notre voiture, il s’agit du corps de la voiture et de ses roues.
Il est assez probable que comme pour Windmill on instancie le revolut joint directement dans le constructeur de car.
import math
from wheel import Wheel
from box import Box
import Box2D
from Box2D import b2Vec2
class Car():
def __init__(self, x, y, world):
self.FWheel = Wheel(x-130, y+70, 45, world)
self.BWheel = Wheel(x+130, y+70, 45, world)
self.mainFrame = Box(x, y, 300, 150,world)
self.rjd1 = world.CreateRevoluteJoint(
bodyA = self.mainFrame.body,
bodyB = self.FWheel.body,
anchor = (self.FWheel.body.worldCenter),
motorSpeed = math.pi,
maxMotorTorque = 10000.0,
enableMotor = False
)
self.rjd2 = world.CreateRevoluteJoint(
bodyA = self.mainFrame.body,
bodyB = self.BWheel.body,
anchor = (self.BWheel.body.worldCenter),
motorSpeed = math.pi,
maxMotorTorque = 1000.0,
enableMotor = False
)
On a donc deux revolute joints, qui sont tous les deux ancrés au centre de la roue. On déinit une vitesse, un torque, et enableMotor est laissé à False, parce qu’on laisse la rotation libre au début. Voyons voir dans quel cas on met le moteur en mouvement:
if pygame.mouse.get_pressed()[0]:
car.rjd1.motorEnabled = True
Donc lorsque le click gauche de la souris est enclenché on actionne le moteur de la roue1. On a pas décidé de créer un 4×4 mais la rotation de l’une des roue devrait être suffisante pour faire avancer la voiture. D’ailleurs il n’y a pas de condition else, une fois que le moteur est actionné, celui-ci tournera en continu (on voit dans notre simulation que dans les faits les particules arrêtent le mouvement de la voiture, c’est un peu une situation d’engluement comme si la voiture se retrouvait dans la vase et n’était plus capable d’avancer -on aurait peut-être eu besoin d’un4x4 au final!-).
Wheel est un objet simple avec une position et un rayon. Sa forme est un circleShape.
CONCLUSION
Nous avons exploré le revolute joint, sans doute celui qui nous sera le plus utile dans notre futur de roboticien. On pourrait imaginer toutes sortes d’objets utilisant des revolute joints.
Nous allons ensuite voir un joint pas moins utile car il trouvera son utilisation dans toute simulation ou jeu où on a besoin de l’interaction de l’utilisateur.
