Skip to content

BaseRobot

from arpirobot.core.robot import BaseRobot
#include <arpirobot/core/robot/BaseRobot.hpp>

BaseRobot is the foundation of any ArPiRobot program. Each program must have exactly one instance of a child class of BaseRobot (the child class is generally called Robot). The functions in this child class are used to define the robot's behavior.

Overridden Functions

The following functions must be overridden in the child class. These are run at different times and are used to define a robot's behavior. Their use will be explained in more detail later.

def robot_started(self):
    pass

def robot_enabled(self):
    pass

def robot_disabled(self):
    pass

def enabled_periodic(self):
    pass

def disabled_periodic(self):
    pass

def periodic(self):
    pass
void robotStarted();

void robotEnabled();

void robotDisabled();

void enabledPeriodic();

void disabledPeriodic();

void periodic();

There are two types of functions listed above. The periodic functions run once every x milliseconds. By default this is configured for 50 milliseconds. The other functions run when some specific event occurs.

Robot States

A robot has two basic states. The state is tracked by the underlying BaseRobot implementation. When stared, a robot is in the "Disabled" state. In this state the robot is unable to perform any "potentially dangerous" actions and will just sit idle. The other state is the "Enabled" state. In this state the robot is able to perform tasks.

While disabled some devices will become disabled. For example, motor controllers will become disabled when the robot is disabled and become enabled when the robot is enabled. While a motor controller is disabled, it can be configured but is unable to move its motor. Once the robot is enabled (and the motor controller becomes enabled) the motor controller is able to move its motor.

In addition to controlling the state of "potentially dangerous" devices, the state of the robot is useful for defining core robot functionality. Some of the functions listed above run only if the robot is in a specific state. Others run regardless of state. - robot_started / robotStarted runs when the robot program is started. This will always occur while the robot is disabled. This function will only ever run once. - robot_enabled / robotEnabled runs when the robot switches from the disabled state to the enabled state. - robot_disabled / robotDisabled runs when the robot switches from the enabled state to the disabled state. It also runs after robot_started / robotStarted runs when the program first starts (as the robot first becomes disabled on startup). - There are also three periodic functions. The generic periodic function will run regardless of state. The enabled_periodic / enabledPeriodic and disabled_periodic / disabledPeriodic functions run only in the corresponding state. - This makes enabledPeriodic a common location for the bulk of the robot program's logic (unless the Action system is used as it commonly is for more complex robot programs).

Once a robot program is running its state is only able to be changed by the Drive Station. After the Drive Station connects to a running robot program it is able to change the state of the program. The "Enable" and "Disable" buttons in the Drive Station UI send commands to the robot to change its state. Furthermore, if a drive station becomes disconnected the robot program will detect this and automatically disable itself. This behavior is not intended to be user modifiable, however if a fully autonomous robot is required it is trivial to implement a "virtual Drive Station" that connects to the robot program and sends an enabled command. This "virtual Drive Station" could even be part of the robot program itself. The network commination protocol is documented in the comments in the CoreLib's NetworkManager source files.

Watchdog

In addition to robot states there is one more feature to ensure safe operation of the robot, the watchdog. The watchdog is used to automatically disable "potentially dangerous" devices if the robot program is frozen or running too slowly to safely manage devices.

If the watchdog is not "fed" for 500* milliseconds, all "potentially dangerous" devices become disabled. They will be automatically re-enabled when the watchdog is next "fed".

This helps avoid scenarios where the CPU is overloaded and the robot is unable to respond to inputs in time to avoid bad scenarios. Additionally, if user code ever causes the robot program to freeze (eg infinite loops) this ensures the motors will be able to be stopped without relaunching the robot program to take control back of the motors.

*This duration can be configured in the RobotProfile

The watchdog should be fed in the periodic function by calling the feed_watchdog / feedWatchdog function (member of BaseRobot).

The periodic functions are run by an internal scheduler thread pool, the same thread pool which runs user code such as actions. Feeding the watchdog in periodic ensures that if user code ever slows down the program too much (which also slows down periodic) devices are disabled. Note that the watchdog is not run on the scheduler and thus is not directly able to be delayed by user code. The watchdog runs on the program's main thread in an infinite loop with a sleep to keep CPU usage from being too high. This sleep is short enough, however, that the task should not be slowed down too much by kernel scheduling.

RobotProfile

from arpirobot.core.robot import RobotProfile
#include <arpirobot/core/robot/RobotProfile.hpp>

The RobotProfile is a class containing only static members. The variables are used to configure various settings about how the robot is run including:

  • How many threads are in the main scheduler's thread pool (used for running actions, periodic functions, etc). Defaults to 10.
  • How frequently periodic functions should run (in milliseconds). Defaults to 50.
  • How old gamepad data is allowed to be (in milliseconds). Data older than this age will be discarded (this prevents scenarios where network slowdowns prevent the robot from being controllable). Defaults to 100.
  • How frequently action's periodic functions are run (in milliseconds). Defaults to 50.
  • Duration before BaseRobot watchdog disables motors and other devices (in milliseconds). Defaults to 500.
  • Which IO provider is used when the program runs. An IO provider is an underlying library which allows using GPIO pins and communication busses. Which ones are available / used by default is platform specific. Setting this to an empty string will use the default provider for the platform.

Any variables in RobotProfile must be modified before the BaseRobot instance is started. In a typical project, this means that variables must either be changed in the main source file (before it calls start on the Robot class instance) or they must be changed in the constructor of the Robot class (where Robot is the class derived from BaseRobot).