Control System Internals

When using any method in the FTC SDK that accesses hardware, be that setting motor power, reading an encoder, a sensor, etc., a LynxCommand is sent.

Note

LynxCommands are not sent directly from the Robot Controller to an Expansion Hub through USB; they are sent through USB to an FTDI, which bridges to UART.

Warning

LynxCommands being blocking (and more specifically a per-bus master lock being present) means that multithreading hardware calls is at best not helpful and typically harmful to performance.

If an Android phone and Expansion Hub is used, LynxCommands are sent over USB; however if a Control Hub is used, LynxCommands are sent over UART. This is very important, not just because of the increased reliability with UART instead of USB, but also because LynxCommands take approximately 3 milliseconds over USB and approximately 2 milliseconds over UART.

Note

Interacting with I2C devices takes significantly longer; upwards of 7 milliseconds over USB. However, this is not because each LynxCommand takes longer, but because multiple LynxCommands must be sent to interact with I2C.

Please note that since version 5.5 of the SDK, I2C calls on the Control Hub are much faster than those on the Expansion Hub.

Bulk Reads

Bulk reads are a LynxCommand that reads all sensor values (except I2C) on a hub at once. This takes the same amount of time to execute as any other LynxCommand, and can therefore save a lot of time in the execution loop; with a bulk read, reading ten sensors takes as much time as reading one sensor (if they are not I2C and are on the same hub).

This became much simpler to do with SDK versions 5.4 and above, with a built-in way to easily access it. There are 3 modes available: OFF mode, AUTO mode, and MANUAL mode. Here is the official example on how to use bulk reads.

Warning

On SDK version 5.4, AUTO and MANUAL bulk read modes will occasionally throw a NullPointerException (see this GitHub issue). Note this has since been rectified in SDK version 5.5. Also note that the minimum legal SDK version for Ultimate Goal is 6.0, meaning that this is no longer be an issue on a device with legal software.

Off Mode

This is the default, and the most boring; it means bulk reads are not used by the sdk when calling normal hardware-access methods.

Note

Bulk reads can still be accessed by calling the LynxModule.getBulkInputData() method, however if one wishes to use bulk reads (which we highly recommend) using AUTO or MANUAL modes is simpler.

To manually set OFF mode, you need to run

List<LynxModule> allHubs = hardwareMap.getAll(LynxModule.class);

for (LynxModule hub : allHubs) {
    hub.setBulkCachingMode(LynxModule.BulkCaching.OFF);
}

Auto Mode

This is the simplest mode to use that utilizes bulk reads; a new bulk read is done when a hardware read is repeated. As an example of this

List<LynxModule> allHubs = hardwareMap.getAll(LynxModule.class);

for (LynxModule hub : allHubs) {
    hub.setBulkCachingMode(LynxModule.BulkCaching.AUTO);
}

while (opModeIsActive()) {
    // Will run one bulk read per cycle; however, if e.g.
    // frontLeftMotor.getPosition() was called again,
    // a new bulk read would be issued
    int frontLeftEncoderPos = frontLeftMotor.getPosition();
    int frontRightEncoderPos = frontRightMotor.getPosition();
    int backLeftEncoderPos = backLeftMotor.getPosition();
    int backRightEncoderPos = backRightMotor.getPosition();
}

However, this can be problematic, if the same hardware read is called more than once in a given loop; an example of this

List<LynxModule> allHubs = hardwareMap.getAll(LynxModule.class);

for (LynxModule hub : allHubs) {
    hub.setBulkCachingMode(LynxModule.BulkCaching.AUTO);
}

while (opModeIsActive()) {
    // Will run two bulk read per cycles,
    // as frontLeftMotor.getPosition() is called twice
    int frontLeftEncoderPos = frontLeftMotor.getPosition();
    int frontLeftEncoderPos2 = frontLeftMotor.getPosition();
}

Overall, this is recommended, as it is very unlikely to mess anything up and can give significant performance improvements for little effort. On the user side, one does not need to manually flush the bulk read cache; however, this means you lose some control.

Manual Mode

In manual mode the cache for bulk reads is only reset once manually reset. This can be useful, as it is the way to absolutely minimize extraneous reads, however if the cache is not reset, stale values will be returned. That being said, here’s a proper implementation of MANUAL mode

List<LynxModule> allHubs = hardwareMap.getAll(LynxModule.class);

for (LynxModule hub : allHubs) {
    hub.setBulkCachingMode(LynxModule.BulkCaching.MANUAL);
}

while (opModeIsActive()) {
    // Will run one bulk read per cycle,
    // even as frontLeftMotor.getPosition() is called twice
    // because the caches are being handled manually and cleared
    // once a loop
    for (LynxModule hub : allHubs) {
        hub.clearBulkCache();
    }

    int frontLeftEncoderPos = frontLeftMotor.getPosition();
    int frontLeftEncoderPos2 = frontLeftMotor.getPosition();
}

Warning

When in MANUAL mode, if the cache is not cleared appropriately, stale values will be returned. For that reason, if you are not quite sure what you are doing, we recommend AUTO mode; while MANUAL mode can have some performance improvements if AUTO mode is not used optimally, it has less room for catastrophic error.

Control System Internals Glossary

Control Hub

The Control Hub is an Expansion Hub with an embedded Android single-board computer daughterboard connected to it. This enables it to not need a separate Robot Controller phone, as the daughterboard functions as the Robot Controller. Internally, LynxCommands are sent over from the daughterboard to the Lynx board over an internal UART connection.

For more information, see the official REV Control Hub documentation.

Warning

Don’t take apart a Control Hub unless you really know what you are doing. They can be damaged in the process, especially if one does not know how to properly reassemble it.

The single board computer and :term:`Lynx` board from a Control Hub
Expansion Hub

The Expansion Hub contains a Lynx board. It can be controlled by an Android device running the FTC SDK. This will send it LynxCommands, which will cause the Expansion Hub to respond accordingly.

For more information, see the official REV Expansion Hub documentation.

Lynx

“Lynx” is the codename of the board within the Expansion Hub and Control Hub that interacts with hardware. References to “Lynx” are made in the FTC SDK refer to this board.

Warning

Don’t take apart a Control or Expansion Hub unless you really know what you are doing. They can be damaged in the process, especially if one does not know how to properly reassemble it.

A Lynx board that was removed from its case

A Lynx board that was removed from its case

LynxCommand

A LynxCommand represents a command that can be sent to a Lynx module; it can send and receive information.