Changes between Version 6 and Version 7 of Tutorial5AdvancedRemoteControlUsage


Ignore:
Timestamp:
Nov 22, 2017, 12:49:56 PM (8 years ago)
Author:
fma
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Tutorial5AdvancedRemoteControlUsage

    v6 v7  
    11= Tutorial 5: Advanced remote control usage =
    22
    3 As we've seen in [[Tutorial1FirstRobot|tutorial 1]], we created a {{{Gamepad}}} class in order to control our robot. This class inherits from {{{RemoteControl}}}, and implements a few virtual methods:
     3As we've seen in [[Tutorial1FirstRobot|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''':
    44
    55{{{
     
    88class Gamepad(RemoteControl):
    99    def _createFrontend(self):
    10         return Thrustmaster(settings.THRUSTMASTER_PATH)
     10        return Thrustmaster(THRUSTMASTER_PATH)
    1111
    1212    def _buildComponents(self):
     
    1414        self._addConfig("body")
    1515
    16         self._addComponent(Button, command=self.selectNextConfig, key="button_008", trigger="hold")
    17         self._addComponent(Button, command=self.selectPreviousConfig, key="button_009", trigger="hold")
     16        self._addComponent(Button, command=self.selectNextConfig, key="button_003", trigger="hold")
    1817
    19         self._addComponent(Button, command=self.robot.incBodyPosition, key="button_004", mapper=MapperSetValue(dz=+5))
    20         self._addComponent(Button, command=self.robot.incBodyPosition, key="button_005", mapper=MapperSetValue(dz=-5))
     18        self._addComponent(Button, configs="walk", command=GaitSequencer().walkStop, key="button_000")
     19        self._addComponent(Button, configs="walk", command=GaitSequencer().walkStep, key="button_002")
     20        self._addComponent(Button, configs="walk", command=GaitSequencer().selectNextGait, key="button_006", trigger="hold")
     21        self._addComponent(Button, configs="walk", command=GaitSequencer().selectPrevGait, key="button_007", trigger="hold")
     22
    2123        self._addComponent(Joystick, configs="walk", command=GaitSequencer().walk, keys=("analog_02", "analog_03", "analog_00"), mapper=MapperWalk())
    2224
    23         self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_00", mapper=MapperSetMultiply('yaw', coef=-15))
    24         self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_03", mapper=MapperSetMultiply('pitch', coef=-15))
    25         self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_02", mapper=MapperSetMultiply('roll', coef=15))
     25        # Body inc. translation
     26        self._addComponent(Analog, command=self.robot.incBodyPosition, key="analog_04", modifier="button_008", mapper=MapperSetMultiply('dx', coef=5))
     27        self._addComponent(Analog, command=self.robot.incBodyPosition, key="analog_05", modifier="button_008", mapper=MapperSetMultiply('dy', coef=5))
     28        self._addComponent(Button, command=self.robot.incBodyPosition, key="button_004", modifier="button_008", mapper=MapperSetValue(dz=+10))
     29        self._addComponent(Button, command=self.robot.incBodyPosition, key="button_005", modifier="button_008", mapper=MapperSetValue(dz=-10))
     30
     31        # Body inc. rotation
     32        self._addComponent(Analog, command=self.robot.incBodyPosition, key="analog_04", modifier="button_009", mapper=MapperSetMultiply('droll', coef=5))
     33        self._addComponent(Analog, command=self.robot.incBodyPosition, key="analog_05", modifier="button_009", mapper=MapperSetMultiply('dpitch', coef=-5))
     34        self._addComponent(Button, command=self.robot.incBodyPosition, key="button_004", modifier="button_009", mapper=MapperSetValue(dyaw=+5))
     35        self._addComponent(Button, command=self.robot.incBodyPosition, key="button_006", modifier="button_009", mapper=MapperSetValue(dyaw=-5))
     36
     37        # Body extra translation
     38        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_02", modifier="button_008", mapper=MapperSetMultiply('x', coef=30))
     39        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_03", modifier="button_008", mapper=MapperSetMultiply('y', coef=30))
     40        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_01", modifier="button_008", mapper=MapperSetMultiply('z', coef=20))
     41
     42        # Body extra rotation
     43        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_00", modifier="button_009", mapper=MapperSetMultiply('yaw', coef=-10))
     44        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_03", modifier="button_009", mapper=MapperSetMultiply('pitch', coef=-10))
     45        self._addComponent(Analog, configs="body", command=self.robot.setBodyExtraPosition, key="analog_02", modifier="button_009", mapper=MapperSetMultiply('roll', coef=10))
     46
     47        # Inc feet neutral position
     48        self._addComponent(Button, command=self.robot.incFeetNeutral, key="button_005", mapper=MapperSetValue(dneutral=-10))
     49        self._addComponent(Button, command=self.robot.incFeetNeutral, key="button_007", mapper=MapperSetValue(dneutral=+10))
    2650}}}
    2751
    2852The first method, {{{_createFrontend()}}} must return a valid frontend (we just saw in [[Tutorial4AddInputFrontendSupport|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.
    2953
    30 The second method, {{{_buildComponents()}}} is where interesting things take place. Here, we create the buttons/axis mapping to the robot controls.
     54In the second method, {{{_buildComponents()}}}, interesting things take place: this is where {{{Component}}}s ({{{Button}}}, {{{Analog}}}...) of our remote control are created.
    3155
     56We 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.
     57
     58Then 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.
     59
     60
     61
     62
     63
     64'''Mappers''' are simple objects helping to adapt params from '''!RemoteControl''' '''Components''' output to '''Robot'''/'''!GaitSequencer''' methods input.
     65
     66For example, to control the robot walk, we can create a '''Joystick''' component with 3 axes: X, Y, RZ.
     67
     68But 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|tutorials]].
     69
     70See [https://framagit.org/fma38/Py4bot/blob/master/py4bot/inputs/mappers/mapper.py py4bot/inputs/mappers/mapper.py] to see how this mapper is defined.
     71
     72Of course, you can define your own '''Mappers'''.
     73
     74