Skip to content

Closed loop

Every axis can define a closed loop, provided they are built on top of a controller which supports it. At the moment, only hardware closed loops (ie: managed by the hardware controller) are supported.

Configuration

A closed loop is defined by creating a closed_loop configuration section under an axis.

This section should always contain a field state to define whether the closed loop must be activated at initialization or not.

Each type of motor controller requires a specific set of parameters, known as controller requirements.

For example, the mockup controller needs:

controller:
  - class: Mockup
    module: mockup
    axes:
      - name: servo1
        steps_per_unit: 1000
        velocity_high_limit: 500
        velocity_low_limit: 10
        velocity: 100
        acceleration: 200
        low_limit: -1000
        high_limit: 1000
        unit: mm
        closed_loop:
            state: on
            kp: 0.1 # <─┬ controller specific
            ki: 0.2 # <─┤
            kd: 0.3 # <─┘

Controller requirements

Each motor controller provides the list of parameters it needs to instantiate a closed loop. One should refer to the particular controller documentation to find the list and description for these parameters.

When a parameter is missing, an error provides details on what is missing:

!!! === RuntimeError: For device servo1:closed_loop configuration must
contain {'kp', 'ki', 'kd'}. === !!!

Alternatively, it is possible to directly query the controller with get_closed_loop_requirements():

TEST_SESSION [1]: servo1.controller.get_closed_loop_requirements()
         Out [1]: ['kp', 'ki', 'kd']

Usage

Closed loops are always related to an axis, thus they have no name and are located under their axis.

TEST_SESSION [2]: servo1.closed_loop
         Out [2]: CLOSED LOOP:
                       state: ON
                       kp: 0.1
                       ki: 0.2
                       kd: 0.3

They can be turned on and off with the so-named functions. The controller specific parameters are also accessible this way.

TEST_SESSION [3]: servo1.closed_loop.off()
TEST_SESSION [4]: servo1.closed_loop.ki = 0.75
TEST_SESSION [5]: servo1.closed_loop
         Out [5]: CLOSED LOOP:
                       state: OFF
                       kp: 0.1
                       ki: 0.75
                       kd: 0.3

Note

All parameters (state included) are stored in redis, consequently the closed loop will always start in the same state it has been left in.