Changes between Initial Version and Version 1 of Tutorial2UsingThe3DSimulator


Ignore:
Timestamp:
Nov 22, 2017, 8:52:00 AM (8 years ago)
Author:
fma
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Tutorial2UsingThe3DSimulator

    v1 v1  
     1= Tutorial 2: Using the 3D simulator =
     2
     3''Files for this tutorial are available in [https://framagit.org/fma38/Py4bot/tree/master/py4bot/examples/tutorial_2 py4bot/examples/tutorial_2/]''
     4
     5Here, we will see how to use the 3D simulation stuff.
     6
     7As before, we create a new empty dir in our home dir:
     8
     9{{{
     10$ mkdir tutorial_2
     11$ cd tutorial_2
     12}}}
     13
     14{{{
     15#!python
     16
     17#!/usr/bin/env python
     18# -*- coding: utf-8 -*-
     19
     20import math
     21
     22import visual
     23
     24from py4bot.api import *
     25
     26import settings
     27}}}
     28
     29Nothing fancy, here.
     30
     31{{{
     32#!python
     33
     34class Hexapod3D(Robot3D):
     35    def _createBody(self):
     36        return Body(settings.LEGS_ORIGIN)
     37
     38    def _createLegs(self):
     39        legs = {}
     40        legIk = {}
     41        for legIndex in settings.LEGS_INDEX:
     42            legs[legIndex] = Leg3Dof(legIndex, {'coxa': Coxa(), 'femur': Femur(), 'tibia': Tibia()}, settings.FEET_NEUTRAL[legIndex])
     43            legIk[legIndex] = Leg3DofIk(settings.LEGS_GEOMETRY[legIndex])
     44
     45        return legs, legIk
     46}}}
     47
     48Same as before, except that we inherits from {{{Robot3D}}}, instead of {{{Robot}}}.
     49
     50{{{
     51#!python
     52
     53    def _createActuatorPool(self):
     54        driver = Driver3D()
     55        pool = ActuatorPool(driver)
     56
     57        num = 0
     58        for leg in self._legs.values():
     59
     60            # Create joints actuators
     61            coxa3D = Coxa3D(leg.coxa, num, settings.LEGS_GEOMETRY[leg.index]['coxa'])
     62            pool.add(coxa3D)
     63            num += 1
     64
     65            femur3D = Femur3D(leg.femur, num, settings.LEGS_GEOMETRY[leg.index]['femur'])
     66            pool.add(femur3D)
     67            num += 1
     68
     69            tibia3D = Tibia3D(leg.tibia, num, settings.LEGS_GEOMETRY[leg.index]['tibia'])
     70            pool.add(tibia3D)
     71            num += 1
     72
     73            # Init 3D view
     74            coxa3D.frame = self._body3D
     75            femur3D.frame = coxa3D
     76            tibia3D.frame = femur3D
     77
     78            coxa3D.pos = (settings.LEGS_ORIGIN[leg.index]['x'], 0, -settings.LEGS_ORIGIN[leg.index]['y'])
     79            femur3D.pos = (settings.LEGS_GEOMETRY[leg.index]['coxa'], 0, 0)
     80            tibia3D.pos = (settings.LEGS_GEOMETRY[leg.index]['femur'], 0, 0)
     81
     82            coxa3D.rotate(angle=math.radians(settings.LEGS_ORIGIN[leg.index]['gamma0']), axis=(0, 1, 0))
     83
     84        return pool
     85}}}
     86
     87Here, we use specific 3D actuators: {{{Coxa3D}}}, {{{Femur3D}}}, {{{Tibia3D}}}; they all use the [http://vpython.org VPython] library to represent themselves on the screen.
     88
     89Note that we don't use a custom actuator mapping; nums are automatically incremented.
     90
     91We also need to configure the hierarchy, and the relative positions of the actuators.
     92
     93''Note: this may change in the future; I'm working on a simpler way to do all this''.
     94
     95{{{
     96#!python
     97
     98class Gamepad(RemoteControl):
     99    def _createFrontend(self):
     100        return Thrustmaster(settings.THRUSTMASTER_PATH)
     101
     102    def _buildComponents(self):
     103        self._addConfig("walk")
     104        self._addConfig("body")
     105
     106        self._addComponent(Button, command=self.selectNextConfig, key="button_008", trigger="hold")
     107        self._addComponent(Button, command=self.selectPreviousConfig, key="button_009", trigger="hold")
     108
     109        self._addComponent(Button, command=self.robot.incBodyPosition, key="button_004", mapper=MapperSetValue(dz=+5))
     110        self._addComponent(Button, command=self.robot.incBodyPosition, key="button_005", mapper=MapperSetValue(dz=-5))
     111        self._addComponent(Joystick, configs="walk", command=GaitSequencer().walk, keys=("analog_02", "analog_03", "analog_00"), mapper=MapperWalk())
     112
     113        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_00", mapper=MapperSetMultiply('yaw', coef=-15))
     114        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_03", mapper=MapperSetMultiply('pitch', coef=-15))
     115        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_02", mapper=MapperSetMultiply('roll', coef=15))
     116}}}
     117
     118Same as before...
     119
     120{{{
     121#!python
     122
     123def main():
     124    def addGait(gaitClass, gaitName):
     125        group = settings.GAIT_LEGS_GROUPS[gaitName]
     126        params = settings.GAIT_PARAMS['default']
     127        for key1, value1 in settings.GAIT_PARAMS[gaitName].items():
     128            for key2, value2 in value1.items():
     129                params[key1][key2] = value2
     130        gait = gaitClass(gaitName, group, params)
     131        GaitManager().add(gait)
     132
     133    scene = visual.display(width=settings.SCENE_WIDTH, height=settings.SCENE_HEIGHT)
     134    ground = visual.box(axis=(0, 1, 0), pos=(0, 0, 0), length=0.1, height=500, width=500, color=visual.color.gray(0.75), opacity=0.5)
     135
     136    addGait(GaitTripod, "tripod")
     137    addGait(GaitTetrapod, "tetrapod")
     138    addGait(GaitRiple, "riple")
     139    addGait(GaitWave, "metachronal")
     140    addGait(GaitWave, "wave")
     141    GaitManager().select("riple")
     142
     143    robot = Hexapod3D()
     144
     145    remote = Gamepad(robot)
     146
     147    GaitSequencer().start()
     148    remote.start()
     149
     150    robot.setBodyPosition(z=30)
     151
     152    robot.mainLoop()
     153
     154    remote.stop()
     155    remote.join()
     156    GaitSequencer().stop()
     157    GaitSequencer().join()
     158
     159if __name__ == "__main__":
     160    main()
     161}}}
     162
     163The only difference, here, is the scene size init, and the ground addition (optional).
     164
     165== Settings ==
     166
     167{{{
     168#!python
     169
     170# -*- coding: utf-8 -*-
     171
     172from py4bot.common import config
     173
     174
     175# Legs index
     176LEGS_INDEX = ('RF', 'RM', 'RR', 'LR', 'LM', 'LF')
     177
     178# Legs geometry
     179LEGS_GEOMETRY = {
     180    'RM': {'coxa': 25, 'femur': 45, 'tibia': 65},
     181    'RF': {'coxa': 25, 'femur': 45, 'tibia': 65},
     182    'LF': {'coxa': 25, 'femur': 45, 'tibia': 65},
     183    'LM': {'coxa': 25, 'femur': 45, 'tibia': 65},
     184    'LR': {'coxa': 25, 'femur': 45, 'tibia': 65},
     185    'RR': {'coxa': 25, 'femur': 45, 'tibia': 65}
     186}
     187
     188# Legs origin
     189LEGS_ORIGIN = {
     190    'RM': {'x':  35., 'y':   0., 'gamma0' :   0.},
     191    'RF': {'x':  35., 'y':  65., 'gamma0' :  30.},
     192    'LF': {'x': -35., 'y':  65., 'gamma0' : 150.},
     193    'LM': {'x': -35., 'y':   0., 'gamma0' : 180.},
     194    'LR': {'x': -35., 'y': -65., 'gamma0' : 210.},
     195    'RR': {'x':  35., 'y': -65., 'gamma0' : 330.},
     196}
     197
     198# Legs feet neutral position
     199FEET_NEUTRAL = {
     200    'RM': LEGS_GEOMETRY['RM']['coxa'] + LEGS_GEOMETRY['RM']['femur'],
     201    'RF': LEGS_GEOMETRY['RF']['coxa'] + LEGS_GEOMETRY['RF']['femur'],
     202    'LF': LEGS_GEOMETRY['LF']['coxa'] + LEGS_GEOMETRY['LF']['femur'],
     203    'LM': LEGS_GEOMETRY['LM']['coxa'] + LEGS_GEOMETRY['LM']['femur'],
     204    'LR': LEGS_GEOMETRY['LR']['coxa'] + LEGS_GEOMETRY['LR']['femur'],
     205    'RR': LEGS_GEOMETRY['RR']['coxa'] + LEGS_GEOMETRY['RR']['femur'],
     206}
     207
     208# Gaits
     209GAIT_LEGS_GROUPS = {
     210    'tripod':      (('RM', 'LF', 'LR'), ('RF', 'LM', 'RR')),
     211    'tetrapod':    (('RR', 'LM'), ('RF', 'LR'), ('RM', 'LF')),
     212    'riple':       (('RR',), ('LM',), ('RF',), ('LR',), ('RM',), ('LF',)),
     213    'metachronal': (('RR',), ('LM',), ('RF',), ('LR',), ('RM',), ('LF',)),
     214    'wave':        (('RR',), ('RM',), ('RF',), ('LR',), ('LM',), ('LF',))
     215}
     216
     217# Gaits parameters
     218GAIT_PARAMS = {
     219    'default': {
     220        'length': {
     221            'min': 5.,
     222            'max': 40.
     223        },
     224        'angle': {
     225            'min': 0.5,
     226            'max': 5.
     227        },
     228        'height': {
     229            'min': 20.,
     230            'max': 40.
     231        },
     232        'speed': {
     233            'min': 25.,
     234            'max': 250.
     235        }
     236    },
     237    'tripod': {},
     238    'tetrapod': {},
     239    'riple': {},
     240    'metachronal': {},
     241    'wave': {}
     242}
     243
     244# Gamepad path
     245THRUSTMASTER_PATH = "/dev/input/by-id/usb-Mega_World_Thrustmaster_dual_analog_3.2-event-joystick"
     246
     247# VPython scene default size
     248SCENE_WIDTH = 640
     249SCENE_HEIGHT = 480
     250
     251}}}
     252
     253We removed the servos mapping/calibration, as we don't need them anymore, and we just added the scene default size.