Simulation physique 2D avec Box2d et wxPython

Avec l'environnement du gymnase et de Deep Mind qui sortent pour l'apprentissage par renforcement, il y a des signes qu'il fera chaud l'année prochaine, mais après tout, voulez-vous souvent résoudre votre propre problème court (contrôle du robot)?

Dans L'environnement du traceur de ligne a été créé Open AI I / F \ -Qiita, le traceur de ligne ignorant la loi physique se déplaçait, mais à l'avenir, Afin de s'attaquer au problème de l'adhérence des pneus et de l'accélération gravitationnelle, nous devons intégrer la loi physique dans la simulation.

Il existe différents simulateurs de robots 3D tels que Gazebo et Webot sur le marché, mais la 2D est plus légère pour PoC et plus rapide à essayer conceptuellement, je voudrais donc le recommander d'abord pour PoC. Je pense personnellement.

C'est pourquoi pendant un certain temps, la simulation physique avec Box2D, qui était populaire, et l'animation avec le wxPython classique (pour moi).

2016-12-18.png

Introduction de Box2d

J'utilise toujours le mauvais environnement de Windows, j'ai donc dû préparer Swig d'abord ⇒ [SWIG introduit dans Windows \ -Volo di notte](http://chachay.hatenablog.com/entry/2016/12/ 18/090010)

Maintenant, clonez et installez pybox2d!

python setup.py build
python setup.py install

Les utilisateurs de Windows peuvent avoir besoin d'outils de construction VC ++. vérifier.

Introduction de wxPython

Je suis récemment passé à Python3, alors notez l'installation de wxPython. De Index of / Phoenix / snapshot \ -builds, "https://www.wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix- 3.0.3.dev2700 + c524ed1-cp35-cp35m-win_amd64.whl "prenez le lien du paquet de roues qui vous concerne

pip install https://www.wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3.dev2700+c524ed1-cp35-cp35m-win_amd64.whl

La facilité de création d'un environnement ici est la meilleure en python.

Let's box2D

Déterminez d'abord le facteur d'échelle et l'heure de la simulation

PPM = 20.0  # pixels per meter
TimeStep = 20 # ms

C'est le seul package à utiliser

# -*- coding: utf-8 -*-
import Box2D 
from Box2D.b2 import (world, polygonShape, staticBody, dynamicBody)
import wx

Initialisation wxPython

C'est le même que la série Chachay précédente, mais nous le ferons avec la configuration suivante basée sur la classe wx.App.

class APPWINDOW(wx.Frame):
    def __init__(self, parent=None, id=-1, title=None):
        # 1.Initialisation de la fenêtre de dessin, initialisation de la minuterie
        # 2.CloseWindow liaison
        # 3.Initialisation du moteur physique+Objet physique(Le sol ou les objets)Définition de
        # 4.Démarrer la boucle du minuteur
    def CloseWindow(self, event):
        #Processus de résiliation simple
    def OnTimer(self, event):
        # 1.Nettoyer la vitre claire
        # 2.Dessin d'objets physiques
        # 3.Simulation physique pour 1 étape

Initialisation du moteur physique

Tout d'abord, définissez la gravité dans le monde, créez le sol (Create Static Body), puis placez la boîte dans l'air (Create Dynamic Body).

        # pybox2d world
        self.phys_world = world(gravity=(0, -10), doSleep=True)
        self.ground_body = self.phys_world.CreateStaticBody(
            position=(0, 1),
            shapes=polygonShape(box=(50, 5)),
        )
        self.dynamic_body = self.phys_world.CreateDynamicBody(position=(10, 15), angle=15)
        self.box = self.dynamic_body.CreatePolygonFixture(box=(2, 1), density=1, friction=0.3)

Traitement de la boucle de minuterie

Si vous le définissez jusqu'à présent, la simulation est super facile. Appelez simplement la fonction Step. Après cela, je n'ai imaginé que l'endroit pour dessiner une image. Vous pouvez utiliser kivy ou tout ce que vous voulez comme animation.

Il s'agit d'une simulation d'une boîte tombant des airs et atterrissant au sol.

    def OnTimer(self, event):
        # 1.Nettoyer la vitre claire
        self.bdc = wx.BufferedDC(self.cdc, self.bmp)
        self.gcdc = wx.GCDC(self.bdc)
        self.gcdc.Clear()
        
        self.gcdc.SetPen(wx.Pen('white'))
        self.gcdc.SetBrush(wx.Brush('white'))
        self.gcdc.DrawRectangle(0,0,640,640)
        
        # 2.Dessin d'objets physiques
        for body in (self.ground_body, self.dynamic_body):  # or: world.bodies
            for fixture in body.fixtures:
                shape = fixture.shape

                vertices = [(body.transform * v) * PPM for v in shape.vertices]
                vertices = [(int(v[0]), int(480 - v[1])) for v in vertices]
                
                self.gcdc.SetPen(wx.Pen(wx.Colour(50,50,50)))
                self.gcdc.SetBrush(wx.Brush(wx.Colour(colors[body.type])))
                self.gcdc.DrawPolygon(vertices)
        
        # 3.Simulation physique pour 1 étape
        self.phys_world.Step(TimeStep/1000, 10, 10)

La source entière

# -*- coding: utf-8 -*-
import Box2D 
from Box2D.b2 import (world, polygonShape, staticBody, dynamicBody)
import wx

PPM = 20.0  # pixels per meter
TimeStep = 20 # ms

colors = {
    staticBody: (150,150,150),
    dynamicBody: (112,146,190),
}

class APPWINDOW(wx.Frame):
    def __init__(self, parent=None, id=-1, title=None):
        # 1.Initialisation de la fenêtre de dessin, initialisation de la minuterie
        wx.Frame.__init__(self, parent, id, title)
        self.MainPanel = wx.Panel(self, size=(640, 480))
        self.MainPanel.SetBackgroundColour('WHITE')
        
        self.panel = wx.Panel(self.MainPanel, size = (640,480))
        self.panel.SetBackgroundColour('WHITE')

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        mainSizer.Add(self.panel)

        self.SetSizer(mainSizer)
        self.Fit()
        
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer)
        
        self.cdc = wx.ClientDC(self.panel)
        w, h = self.panel.GetSize()
        self.bmp = wx.Bitmap(w,h)

        # 2.CloseWindow liaison
        self.Bind(wx.EVT_CLOSE, self.CloseWindow)
        
        # 3.Initialisation du moteur physique+Objet physique(Le sol ou les objets)Définition de
        self.phys_world = world(gravity=(0, -10), doSleep=True)
        self.ground_body = self.phys_world.CreateStaticBody(
            position=(0, 1),
            shapes=polygonShape(box=(50, 5)),
        )
        self.dynamic_body = self.phys_world.CreateDynamicBody(position=(10, 15), angle=15)
        self.box = self.dynamic_body.CreatePolygonFixture(box=(2, 1), density=1, friction=0.3)
        
        # 4.Démarrer la boucle du minuteur
        self.timer.Start(TimeStep)

    def CloseWindow(self, event):
        #Processus de résiliation simple
        wx.Exit()

    def OnTimer(self, event):
        # 1.Nettoyer la vitre claire
        self.bdc = wx.BufferedDC(self.cdc, self.bmp)
        self.gcdc = wx.GCDC(self.bdc)
        self.gcdc.Clear()
        
        self.gcdc.SetPen(wx.Pen('white'))
        self.gcdc.SetBrush(wx.Brush('white'))
        self.gcdc.DrawRectangle(0,0,640,640)
        
        # 2.Dessin d'objets physiques
        for body in (self.ground_body, self.dynamic_body):  # or: world.bodies
            for fixture in body.fixtures:
                shape = fixture.shape

                vertices = [(body.transform * v) * PPM for v in shape.vertices]
                vertices = [(int(v[0]), int(480 - v[1])) for v in vertices]
                
                self.gcdc.SetPen(wx.Pen(wx.Colour(50,50,50)))
                self.gcdc.SetBrush(wx.Brush(wx.Colour(colors[body.type])))
                self.gcdc.DrawPolygon(vertices)
        
        # 3.Simulation physique pour 1 étape
        self.phys_world.Step(TimeStep/1000, 10, 10)

if __name__ == '__main__':
    app = wx.App()
    w = APPWINDOW(title='Box2D Test')
    w.Center()
    w.Show()
    app.MainLoop()

Recommended Posts

Simulation physique 2D avec Box2d et wxPython
Simulation AtCoder ARC080 D résolue avec Ruby et Python
Essayez le fonctionnement de la base de données avec Python et visualisez avec d3
Résultat de la simulation de diffusion thermique 2D avec Python VTK
Créer une visionneuse de modèle 3D avec PyQt5 et PyQtGraph
Graphique 3D avec matplotlib
3D ou D avec Py
Résolution avec Ruby et Python AtCoder ABC178 D Méthode de planification dynamique
Résolution avec Ruby et Python AtCoder ABC151 D Recherche de priorité de largeur
Résolution avec Ruby et Python AtCoder ABC133 D Somme cumulée
Résolution avec Ruby et Python AtCoder AISING2020 D Méthode carrée itérative
Essayez la simulation MD avec un potentiel ANN en utilisant AENET et ASE
Créez des RPG 2D avec Ren'Py (3) - Boutique d'objets et d'outils
Résolution avec Ruby et Python AtCoder ABC138 D Liste adjacente
Comparaison des performances entre le calcul matriciel bidimensionnel et pour avec numpy