wiki:Tutorials

Version 2 (modified by fma, 10 years ago) ( diff )

--

Tutorial

This is a draft version.

Vocabulary

Before we dive into this tutorial, lets define a few words. I tried to use commonly used vocabulary, and hope I did understand them correclty. Feel free to contact me if you find mistakes.

  • IK: Inverse Kinematic

Robot

Simple example

As Py4bot is just a framework, it is up to you to write the application matching your rogot. But don't worry, it is very easy.

For this example, we are going to setup an application for a 3DoF hexapod. This hexapod will use a ​Veryon servo driver, from DFRobot, as this driver is fully supported by Py4bot. To control this hexapod, we are going to use a ​Thrustmaster Firestorm Dual Analog 3 gamepad.

All usefull classes are available from the api.py module. So, we just have to import things from here. Let's create a hexapod.py file to put our code, and import what we are going to use in this tutorial:

# -*- coding: utf-8 -*-

from py4bot.api import Logger
from py4bot.api import GaitFactory, GaitManager, GaitSequencer
from py4bot.api import Robot, Body
from py4bot.api import ActuatorPool, ServoPool, Veyron
from py4bot.api import Leg3DofIk, Leg3Dof, Coxa, Femur, Tibia
from py4bot.api import RemoteControl, FrontendFactory
from py4bot.api import MapperSet, MapperSetValue, MapperWalk

Now, let's create the robot! A multi-legs robot is mainly build from a body, and several legs. In most cases, the defaut body provided by Py4bot is OK, but in any case, we need to create legs. The second thing we also need to create is the actuator pool, which contain all legs joints. In our example, joints are standard servos. So, here is what the main robot class looks like:

import settings


class Hexapod(Robot):
    def _createLegs(self):
        legIk = Leg4DofIk(settings.LEGS_GEOMETRY)

        legs = {}
        legIk = {}
        for legIndex in settings.LEGS_INDEX:
            legs[legIndex] = Leg4Dof(legIndex, {'coxa': Coxa(), 'femur': Femur(), 'tibia': Tibia()})
            legIk[legIndex] = Leg4DofIk(settings.LEGS_GEOMETRY[legIndex])

        return legs, legIk

    def _createActuatorPool(self):
        driver = Veyron("/dev/ttyACM0", 57600)

        pool = ServoPool(driver)
        for leg in self._legs.values():

            # Create joints actuators
            num = settings.LEGS_SERVOS_MAPPING[leg.index]['coxa']
            servo = pool.create(leg.coxa, num, **settings.SERVOS_CALIBRATION[num])
            pool.add(servo)

            num = settings.LEGS_SERVOS_MAPPING[leg.index]['femur']
            servo = pool.create(leg.femur, num, **settings.SERVOS_CALIBRATION[num])
            pool.add(servo)

            num = settings.LEGS_SERVOS_MAPPING[leg.index]['tibia']
            servo = pool.create(leg.tibia, num, **settings.SERVOS_CALIBRATION[num])
            pool.add(servo)

        return pool

As you can see, we just implemented 2 virtual methods, _createLegs() and _createActuatorPool(). Also note that we used some values from the settings.py module. This module is just a way to centralise the configuration of our hexapod. For now, it should contain s omething like:

# -*- coding: utf-8 -*-

import math

from py4bot.api import config


# Legs index
LEGS_INDEX = ('RF', 'RM', 'RR', 'LR', 'LM', 'LF')

# Legs geometry
LEGS_GEOMETRY = {
    'RM': {'coxa': 25, 'femur': 45, 'tibia': 50},
    'RF': {'coxa': 25, 'femur': 45, 'tibia': 50},
    'LF': {'coxa': 25, 'femur': 45, 'tibia': 50},
    'LM': {'coxa': 25, 'femur': 45, 'tibia': 50},
    'LR': {'coxa': 25, 'femur': 45, 'tibia': 50},
    'RR': {'coxa': 25, 'femur': 45, 'tibia': 50}
}

# Legs origin
LEGS_ORIGIN = {
    'RM': {'x':  50., 'y':   0., 'gamma0' :   0.},
    'RF': {'x':  35., 'y':  80., 'gamma0' :  30.},
    'LF': {'x': -35., 'y':  80., 'gamma0' : 150.},
    'LM': {'x': -50., 'y':   0., 'gamma0' : 180.},
    'LR': {'x': -35., 'y': -80., 'gamma0' : 210.},
    'RR': {'x':  35., 'y': -80., 'gamma0' : 330.},
}
config.initOrigin(LEGS_INDEX, LEGS_ORIGIN)

# Legs (feet) neutral position (femur horizontal, tibia vertical)
LEGS_NEUTRAL = {
    'RM': {
        'l': LEGS_GEOMETRY['RM']['coxa'] + LEGS_GEOMETRY['RM']['femur'],
        'z': LEGS_GEOMETRY['RM']['tibia']
    },
    'RF': {
        'l': LEGS_GEOMETRY['RF']['coxa'] + LEGS_GEOMETRY['RF']['femur'],
        'z': LEGS_GEOMETRY['RF']['tibia']
    },
    'LF': {
        'l': LEGS_GEOMETRY['LF']['coxa'] + LEGS_GEOMETRY['LF']['femur'],
        'z': LEGS_GEOMETRY['LF']['tibia']
    },
    'LM': {
        'l': LEGS_GEOMETRY['LM']['coxa'] + LEGS_GEOMETRY['LM']['femur'],
        'z': LEGS_GEOMETRY['LM']['tibia']
    },
    'LR': {
        'l': LEGS_GEOMETRY['LR']['coxa'] + LEGS_GEOMETRY['LR']['femur'],
        'z': LEGS_GEOMETRY['LR']['tibia']
    },
    'RR': {
        'l': LEGS_GEOMETRY['RR']['coxa'] + LEGS_GEOMETRY['RR']['femur'],
        'z': LEGS_GEOMETRY['RR']['tibia']
    }
}
config.initNeutral(LEGS_INDEX, LEGS_NEUTRAL)

# Legs / servos mapping
LEGS_SERVOS_MAPPING = {
    'RF': {'coxa':  0, 'femur':  1, 'tibia':  2},
    'RM': {'coxa':  4, 'femur':  5, 'tibia':  6},
    'RR': {'coxa':  8, 'femur':  9, 'tibia': 10},
    'LR': {'coxa': 15, 'femur': 14, 'tibia': 13},
    'LM': {'coxa': 19, 'femur': 18, 'tibia': 17},
    'LF': {'coxa': 23, 'femur': 22, 'tibia': 21}
}

# Servos calibration
SERVOS_CALIBRATION = {
     0: {'pulse90': 1500, 'ratio': 1000./90.},  # tibia leg RF
     1: {'pulse90': 1500, 'ratio': 1000./90.},  # femur leg RF
     2: {'pulse90': 1500, 'ratio': 1000./90.},  # coxa leg RF
     3: {'pulse90': 1500, 'ratio': 1000./90.},  # free

     4: {'pulse90': 1500, 'ratio': 1000./90.},  # tibia leg RM
     5: {'pulse90': 1500, 'ratio': 1000./90.},  # femur leg RM
     6: {'pulse90': 1500, 'ratio': 1000./90.},  # coxa leg RM
     7: {'pulse90': 1500, 'ratio': 1000./90.},  # free

     8: {'pulse90': 1500, 'ratio': 1000./90.},  # tibia leg RR
     9: {'pulse90': 1500, 'ratio': 1000./90.},  # femur leg RR
    10: {'pulse90': 1500, 'ratio': 1000./90.},  # coxa leg RR
    11: {'pulse90': 1500, 'ratio': 1000./90.},  # free

    12: {'pulse90': 1500, 'ratio': 1000./90.},  # free 
    13: {'pulse90': 1500, 'ratio': 1000./90.},  # tibia leg LR
    14: {'pulse90': 1500, 'ratio': 1000./90.},  # femur leg LR
    15: {'pulse90': 1500, 'ratio': 1000./90.},  # coxa leg LR

    16: {'pulse90': 1500, 'ratio': 1000./90.},  # free
    17: {'pulse90': 1500, 'ratio': 1000./90.},  # tibia leg LM
    18: {'pulse90': 1500, 'ratio': 1000./90.},  # femur leg LM
    19: {'pulse90': 1500, 'ratio': 1000./90.},  # coxa leg LM

    20: {'pulse90': 1500, 'ratio': 1000./90.},  # free
    21: {'pulse90': 1500, 'ratio': 1000./90.},  # tibia leg RM
    22: {'pulse90': 1500, 'ratio': 1000./90.},  # femur leg RM
    23: {'pulse90': 1500, 'ratio': 1000./90.},  # coxa leg RM
}

Note: have a look at py4bot/examples/cronos/ to see how to build a 4DoF hexapod.

Conclusion

That's it for now with this tutorial. This is the first working dev. release; their are many additional things to do, and final implementation may change, according to feedback/suggestions I will get. But the core is there. Again, the goal of this framework is to provide a high level tool to build complete and powerfull applications to control you multi-legs robots.

Note: See TracWiki for help on using the wiki.