wiki:Tutorial5AdvancedRemoteControlUsage

Version 8 (modified by fma, 8 years ago) ( diff )

--

Tutorial 5: Advanced remote control usage

As we've seen in tutorial 1, we created a Gamepad class in order to control our robot. This class inherits from RemoteControl, and implements a few virtual methods. As an example, we will use my setup for my big 4 DoF hexapod, Cronos:

class Gamepad(RemoteControl):
    def _createFrontend(self):
        return Thrustmaster(THRUSTMASTER_PATH)

    def _buildComponents(self):
        self._addConfig("walk")
        self._addConfig("body")

        self._addComponent(Button, command=self.selectNextConfig, key="button_003", trigger="hold")

        self._addComponent(Button, configs="walk", command=GaitSequencer().walkStop, key="button_000")
        self._addComponent(Button, configs="walk", command=GaitSequencer().walkStep, key="button_002")
        self._addComponent(Button, configs="walk", command=GaitSequencer().selectNextGait, key="button_006", trigger="hold")
        self._addComponent(Button, configs="walk", command=GaitSequencer().selectPrevGait, key="button_007", trigger="hold")

        self._addComponent(Joystick, configs="walk", command=GaitSequencer().walk, keys=("analog_02", "analog_03", "analog_00"), mapper=MapperWalk())

        # Body inc. translation
        self._addComponent(Analog, command=self.robot.incBodyPosition, key="analog_04", modifier="button_008", mapper=MapperSetMultiply('dx', coef=5))
        self._addComponent(Analog, command=self.robot.incBodyPosition, key="analog_05", modifier="button_008", mapper=MapperSetMultiply('dy', coef=5))
        self._addComponent(Button, command=self.robot.incBodyPosition, key="button_004", modifier="button_008", mapper=MapperSetValue(dz=+10))
        self._addComponent(Button, command=self.robot.incBodyPosition, key="button_005", modifier="button_008", mapper=MapperSetValue(dz=-10))

        # Body inc. rotation
        self._addComponent(Analog, command=self.robot.incBodyPosition, key="analog_04", modifier="button_009", mapper=MapperSetMultiply('droll', coef=5))
        self._addComponent(Analog, command=self.robot.incBodyPosition, key="analog_05", modifier="button_009", mapper=MapperSetMultiply('dpitch', coef=-5))
        self._addComponent(Button, command=self.robot.incBodyPosition, key="button_004", modifier="button_009", mapper=MapperSetValue(dyaw=+5))
        self._addComponent(Button, command=self.robot.incBodyPosition, key="button_006", modifier="button_009", mapper=MapperSetValue(dyaw=-5))

        # Body extra translation
        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_02", modifier="button_008", mapper=MapperSetMultiply('x', coef=30))
        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_03", modifier="button_008", mapper=MapperSetMultiply('y', coef=30))
        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_01", modifier="button_008", mapper=MapperSetMultiply('z', coef=20))

        # Body extra rotation
        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_00", modifier="button_009", mapper=MapperSetMultiply('yaw', coef=-10))
        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_03", modifier="button_009", mapper=MapperSetMultiply('pitch', coef=-10))
        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_02", modifier="button_009", mapper=MapperSetMultiply('roll', coef=10))

        # Inc feet neutral position
        self._addComponent(Button, command=self.robot.incFeetNeutral, key="button_005", mapper=MapperSetValue(dneutral=-10))
        self._addComponent(Button, command=self.robot.incFeetNeutral, key="button_007", mapper=MapperSetValue(dneutral=+10))

The first method, _createFrontend() must return a valid frontend (we just saw in previous tutorial how to create such frontends). This methods takes as first argument the frontend path in /dev. An additional argument can be given to override the DEFAULT_AXIS_CALIBRATION table.

In the second method, _buildComponents(), interesting things take place: this is where Components (Button, Analog...) of our remote control are created.

We first define 2 remote control configs, walk and body, as we don't have enough buttons to do all we want. In the first config, walk, we define some components to make the robot walk, but also to change the body position (by increments). Note that when the config is not specified in the component definition, it means it is available in all configs. In the second config, body, we define additional components to control the body.

Then we add the components, using the _addComponent() method helper. This method takes the component class, the command to execute, the frontend key, a optional modifier, and a mapper.

Mappers are simple objects helping to adapt params from RemoteControl Components output to Robot/GaitSequencer methods input.

For example, to control the robot walk, we can create a Joystick component with 3 axes: X, Y, RZ.

But the GaitSequencer walk() method expects speed, direction, length and angle params. Using the MapperWalk mapper, you can compute all these params from X/Y/RZ axes, and send them to the walk() method. That's what we did in the tutorials.

See py4bot/inputs/mappers/mapper.py to see how this mapper is defined.

Of course, you can define your own Mappers.

Note: See TracWiki for help on using the wiki.