Skip to content

Robot Systems

Tom Tzook edited this page Nov 20, 2020 · 12 revisions

FlashLib recommends viewing robots as made up of several systems, each able to operate separately, and usually each has a different purpose.

Overview

Robot Systems

Each system contains the components it uses, such as actuators or sensors, thus allowing it to exist independently. Each exports a certain functionality, matching that system.

The following are examples for systems.

  • Driving System: The system which controls the driving mechanism of the robot. This may change depending on the robot structure, but generally this system controls motors and other actuators responsible for moving the robot around. Such system may export a functionality such as move to move the robot, or rotate to rotate it.
  • Elevator: A system which controls an elevator. May contain actuators which raise and lower the elevator. In addition, it is possible for this system to control and access sensors related to this system, such as an encoder or other sensors to measure the elevator height and much more. Such system may export a functionality such as 'lift' or 'lower' and more.

Implementing

A system is represented by a class which extends the Subsystem class. It should contain instance variables which are the components which make up the system (i.e. actuators, sensors) and should expose methods that allow controlling the system or getting information from it (i.e. move, rotate, getDistanceToTarget, etc). It is important that each system have only one instance in use.

Example

As mentioned before, an example for a system could be an elevator. We would need one or more actuators and maybe a position sensor like an encoder. Other then that, we would need to export some basic functionality to move the system.

Elevator System UML

The structure is pretty simple. Note that all the exposed functionalities are pretty rudimentary motions with no sophistication. That's the idea of a system. More complex actions, like moving to a specific position, would require an Action.

The following is an implementation example for the system. This is but one of many different ways the code might end up looking, it all depends about how the system is actually built and what components it's made up of.

public class ElevatorSystem extends Subsystem {

    private static final double SPEED_RAISE = 0.5;
    private static final double SPEED_LOWER = -0.3;
    
    private final SpeedController mSpeedController;
    private final Encoder mEncoder;

    public ElevatorSystem(SpeedController speedController, Encoder encoder) {
        mSpeedController = speedController;
        mEncoder = encoder;
    }

    public double getCurrentPosition() {
        return mEncoder.getDistance();
    }

    public void raise() {
        mSpeedController.set(SPEED_RAISE);
    }

    public void lower() {
        mSpeedController.set(SPEED_LOWER);
    }

    public void stop() {
        mSpeedController.stop();
    }
}

System Interfaces

FlashLib provides several interfaces which define the expected behavior of systems. Such interfaces may help define what control is needed to be implemented for your systems. Moreover, using these interfaces, will allow using several built-in Actions which are implemented to use them.

The following interfaces are available:

  • Stoppable: A system that can stop it's operation (should be applicable to all systems).
  • Rotatable: A system capable of rotating right and left. Like a shooter, for example.
  • Movable: A system capable of moving back and forth, like a simple single-axis drive system.
  • Movable2d: A system capable of moving in 2 dimensions at the same time. Like an holonomic drive.
  • TankDrive: A tank-drive system.
  • OmniDrive An omni-drive system.
  • HolonomicDrive: A system capable of holonomic motion, like mecanum.
  • Piston: A system based on a piston, capable of opening and closing.

Let's make a simple shooter which utilizes these interfaces. For a shooter, the best fit is likely Rotatable:

public class ShooterSystem extends Subsystem implements Rotatable {

    private final SpeedController mSpeedController;
    private final Encoder mEncoder;

    public ShooterSystem(SpeedController speedController, Encoder encoder) {
        mSpeedController = speedController;
        mEncoder = encoder;
    }

    public double getRotationSpeed() {
        return mEncoder.getRate();
    }

    @Override
    public void rotate(double speed) {
        mSpeedController.set(speed);
    }

    @Override
    public void stop() {
        mSpeedController.stop();
    }
}

This might not seem that much helpful at first. But first: stop and rotate are both required by Rotatable, so by implementing it, we knew some of the methods the system needed. Second: Rotatable actually has more methods which are already with an implementation (default implementation), meaning the system actually has more methods, providing further functionality. Third: Now we can use built-in Actions from FlashLib which support Rotatable, like RotateAction. So we don't have to write as much.

So using a system interface, can be pretty useful, and is quite simple to do.

System Implementations

FlashLib also provides several implementations for common systems, based on the interfaces mentioned above.

The following implementations are available:

  • SingleMotorSystem: A system which has a single motor. Can actually operate several if using SpeedControllerGroup.
  • TankDriveSystem: A tank-drive system.
  • OmniDriveSystem: An omni-drive system.
  • MecanumDriveSystem: A mecanum-drive system.
  • SingleSolenoidSystem: A system with a single-solenoid.
  • DoubleSolenoidSystem: A system with a double-solenoid.

Now, instead of having to create a full class, making a system can be done with a simple instance creation. Instead of creating the ShooterSystem from before, we can simply:

SpeedController motor = ...
SingleMotorSystem shooter = new SingleMotorSystem(motor);