roboticslab-uc3m / yarp-devices

A place for YARP devices
https://robots.uc3m.es/yarp-devices/
9 stars 7 forks source link

Observe and perform state transitions with YARP control modes #215

Closed PeterBowman closed 4 years ago

PeterBowman commented 5 years ago

YARP's control API exposes several vocabs related to initialization and fault states, per IControlMode.h:

// Read / Write
constexpr yarp::conf::vocab32_t VOCAB_CM_IDLE = yarp::os::createVocab('i','d','l');

// Write only (only from high level toward the joint)
constexpr yarp::conf::vocab32_t VOCAB_CM_FORCE_IDLE = yarp::os::createVocab('f','i','d','l');

// Read only (imposed by the board on special events)
constexpr yarp::conf::vocab32_t VOCAB_CM_HW_FAULT = yarp::os::createVocab('h','w','f','a');
constexpr yarp::conf::vocab32_t VOCAB_CM_CALIBRATING = yarp::os::createVocab('c','a','l'); // the joint is calibrating
constexpr yarp::conf::vocab32_t VOCAB_CM_CALIB_DONE = yarp::os::createVocab('c','a','l','d'); // calibration successfully completed
constexpr yarp::conf::vocab32_t VOCAB_CM_NOT_CONFIGURED = yarp::os::createVocab('c','f','g','n'); // missing initial configuration (default value at start-up)
constexpr yarp::conf::vocab32_t VOCAB_CM_CONFIGURED = yarp::os::createVocab('c','f','g','y'); // initial configuration completed, if any

Their control specs (pdf) describe them as follows:

3.1. ‘Hardware fault’ status

The “hardware fault” status is used to signal both an hardware fault (e.g. broken encoder, overcurrent ecc.), or a user fault (e.g. trying to set a control mode which is not implemented by the control board).

  • When the board is in “hardware fault”, the controller is off (no PWM is given to the motor).
  • If a control board is faulted, the user has to send the special command setControlMode(VOCAB_CM_FORCE_IDLE) to reset the fault before choosing any other desired control mode (Figure 3). Requests to switch to other modalities (including VOCAB_CM_IDLE) are ignored. The purpose is to prevent any automatic switch (e.g. from a user software module) from the fault status to an active control status.
  • If the hardware fault is successfully cleared by the VOCAB_CM_FORCE_IDLE command, getControlMode() will return a standard VOCAB_CM_IDLE. If the fault persists (e.g. a critical sensor is broken) the board will remain in the fault status. Note that VOCAB_CM_FORCE_IDLE is never returned by the method getControlMode().
  • Sending the VOCAB_CM_FORCE_IDLE special command when the board is not in fault status has the same effect of setting VOCAB_CM_IDLE control mode.

3.2. ‘Calibration in progress’ status

A board which is currently performing the calibration procedure internally sets its control mode to the special status “calibration in progress” .

  • In this special status the controller is on (PWM is given to the motor). The control algorithm depends on the specific type of calibrator (e.g. absolute encoder, movement to the hardware limit etc). This is not discussed in this document.
  • In this special status the interaction mode is always ignored.

Transition rules:

  • The calibration procedure is requested during the initialization phase. See Section 3.3
  • The calibration procedure is requested by the user during normal operation. In this case:
    1. The joint status is set to calibration in progress.
    2. The calibration algorithm is executed.
    3. After the calibration, the control mode and interaction mode is set to a value decided by the calibrator type. Default value on the iCub platform is: (...)
  • If the calibration fails, the board sets its internal status to ‘hardware fault’.

3.3. ‘Not Configured’ status

A board which has been just turned on internally sets its control mode to the special status “not configured”.

  • In this special status the controller is off (no PWM is given to the motor).
  • In this special status the interaction mode is always ignored.

The following configuration values must be sent to the board in order to complete the configuration phase:

  • All the controller parameters (PID gains, SW joints limits, max output, max current etc.)
  • All the calibration parameters (encoders zeroes, etc.) [ONLY FOR JOINTS REQUIRING CALIBRATION]

Transition rules:

  • If a joint requires calibration, then the joint exists from “not configured” status when the calibration command is received. The control mode is thus set to “calibration in progress”.
  • If a joint does not require calibration, then the joint exists from “not configured status” when all the controller parameters are received. The control mode is thus set to the default value here recommended: idle status (...).

This task will aim to represent iPOS internal states with the above YARP vocabs. See state diagram (also at https://github.com/roboticslab-uc3m/yarp-devices/issues/120#issuecomment-502392793):

states

Proposed mappings:

PeterBowman commented 5 years ago

Didn't know how to treat calibration vocabs (VOCAB_CM_CALIBRATING, VOCAB_CM_CALIB_DONE), but turns out we could use them for homing procedures (--homePoss):

PeterBowman commented 5 years ago

Added CiA drive state machine at https://github.com/roboticslab-uc3m/yarp-devices/commit/972f8758d246bbb2a85c40cf5af11bd5855597a0.

PeterBowman commented 5 years ago

Homing procedure refactored at https://github.com/roboticslab-uc3m/yarp-devices/commit/e1995b68e0422d4684a47990e50a798bb0168ce9. Turns out the yarp::dev::IControlCalibration & yarp::dev::ICalibrator combo does not support homing commands (just parking - I guess it was aimed for the iKart - and "usual" calibration). Also, it seems to me it's more dated than yarp::dev::IRemoteCalibrator. This one is meant for use by network wrappers, for instance the ControlboardWrapper device, which registers a configured instance via deferred attach. In short: it won't work in locally instantiated control boards nor remote network wrappers opened with the subdevice mechanism (ref).

So, what can we do now? Homing procedure will be started via launcher app, as usual, I've just renamed the YARP option to --home (was --homePoss). A homing command can be issued on runtime, too, either via IRemoteCalibrator::homingWholePart() (alternatively, homingSingleJoint(int)) or via RPC command [set] [reca] [homs] (single joint: [set] [reca] [hom] j). In addition, yarpmotorgui enables per-joint and whole part homing buttons.

PeterBowman commented 4 years ago

20190926_191122-0-0-0-1

PeterBowman commented 4 years ago

Ideas:

Remarks:

PeterBowman commented 4 years ago

Current state machine implementation checks whether the requested transition is supported given the current drive state, which forces the app to add multiple checks in this regard. Perhaps it is better to make the API user just point at the desired final state so that this implementation performs all necessary intermediate transitions.

Added requestState method at https://github.com/roboticslab-uc3m/yarp-devices/commit/4d492af08bedf5a8450d5dcd4851f524f7c657bd.

PeterBowman commented 4 years ago

Regarding object 6041h, Modes of Operation Display:

If the drive is in an inferior state than Operation enabled and object 6060h Modes of operation is changed, object 6061h will take the value of 6060h only after the drive reached Operation enabled state.

All non-state-related YARP control mode vocabs are only meaningful when in operation enabled state (on get), although it is still possible to request (set) their corresponding iPOS mode of operation via SDO at any time.

The CiA 402 diagram is therefore easier to understand in this way:

In order to make this work, I'm introducing two variables designing YARP control modes: the requested (set) and the actual control mode (get).

PeterBowman commented 4 years ago

Compare these control mode setters (WIP):

https://github.com/roboticslab-uc3m/yarp-devices/blob/8e4a1dfef9700d0fa43a959583a1b3a08bbf2e6e/libraries/YarpPlugins/TechnosoftIpos/IControlModeRawImpl.cpp#L437-L438

This operation will always update an internal variable containing the actual control mode before this blocking instruction completes. Said update occurs via TPDO callback, therefore the implicit semaphore timeout needs to take into account PDO inhibit times.

https://github.com/roboticslab-uc3m/yarp-devices/blob/8e4a1dfef9700d0fa43a959583a1b3a08bbf2e6e/libraries/YarpPlugins/TechnosoftIpos/IControlModeRawImpl.cpp#L408-L410

Here, however, the SDO indication will only acknowledge that the transfer completes. The associated TPDO (modes of operation display) callback in this case is not being listened to while the SDO operation blocks this thread, although there is indeed a wait-with-timeout involved. So, I'm not sure whether the control mode status variable change or, in other words, the TPDO transfer, will occur during or after the SDO download call. To make it sure, the inhibit time could be set high enough (but not higher than the PDO semaphore timeout), or configure an event timer (which in turn needs to set a tiny period...).

PeterBowman commented 4 years ago

Mostly ready at https://github.com/roboticslab-uc3m/yarp-devices/commit/a0725515ff0edfa066fe1e7fb45c0e6f527fea65, I added a few more checkboxes to https://github.com/roboticslab-uc3m/yarp-devices/pull/229.

In addition to the original intent of this issue, the patch:

PeterBowman commented 4 years ago

A few words regarding ICalibrator and IRemoteCalibrator:

PeterBowman commented 4 years ago

Regarding fault reset command:

Table 5.1.1 – Drive State Transitions

After leaving the state Fault bit 7, Fault Reset of the Controlword has to be cleared by the host.

Table 5.1.2 – Drive States

The drive remains in fault condition, until it receives a Reset Fault command. If following this command, all the bits from the Motion Error Register are reset, the drive exits the fault state

Table 5.2.1 – Bit Assignment in Controlword

Reset Fault. The faults are reset on 0 to 1 transition of this bit. After a Reset Fault command, the master has to reset this bit.

(further down)

The following table lists the bit combinations for the Controlword that lead to the corresponding state transitions. An X corresponds to a bit state that can be ignored. The single exception is the fault reset: The transition is only started by a bit transition from 0 to 1.

Needs testing: https://github.com/roboticslab-uc3m/yarp-devices/commit/b615fb20d1c11804521ded32386d2896bbf1a154.

Edit: tested and actually works at https://github.com/roboticslab-uc3m/yarp-devices/commit/304ea6d1011410256d8559feacb3737f287c0a91, yay.

PeterBowman commented 4 years ago

Technosoft support answered my questions:

The faults are reset on 0 to 1 transition of this bit. After a "Reset Fault" command, the master has to reset this bit. The "Reset Fault" command reset all the bit from the MER (Motion Error Register), but if the error persist, immediately the bits will be set back and the drive will stay in the "Fault" state. If the error condition it disappeared the drive will transition into "Switch On Disabled" state without clearing the bit. Anyway, when you send the "Shutdown" command the bit will be reset.

If you forget to clear the bit nothing will happen, but when you try to send again the "Reset Fault" command you need first to reset the bit and to set again. The fault command is sent when the transition of this bit from 0 to 1 happens. The slow loop of the drive are working at 1 ms, if you sent two messages in less than 1 ms it is possible the drive to not interpreted the transition.

PeterBowman commented 4 years ago

Follow-up from https://github.com/roboticslab-uc3m/yarp-devices/issues/242: