Le Revolute Joint

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.

  1. 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))

  1. 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.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Retour en haut