Controller Interface
Hardware controller abstraction
Controller Interface
Reference for the OctoMY™ controller abstraction layer that communicates with robot hardware.
Design Note
The
IControllerinterface abstracts away hardware differences so your Plans and Lobes work identically whether you're using an Arduino Uno, Arduino Mega, or Servotor32 board. The simplest controller only needs to support a few actuators - sensors, lobes, and advanced features are all opt-in.
Overview
The controller hardware stack in OctoMY™ is composed as follows:
The controller hardware can vary. Implementation only requires that the driver software in Agent implements the IController interface.
IController Interface
The IController interface supports the following feature areas:
| Area | Description |
|---|---|
| Actuator Control | Control actuators connected to the controller |
| User Input Control | Accept data from user inputs (mouse, touch, joystick, etc.) |
| Sensor Control | Accept data from sensors connected to the controller |
| Lobe Control | Real-time processing of sensor/input data to generate actuator signals |
The simplest controller only supports a few actuators with no sensors or processing. Features are opt-in.
General interface
Controller identification
class IController {
public:
// Identity
QString controllerTitle() const;
QString controllerDescription() const;
QString controllerIcon() const;
QString controllerVersion();
};
Debug mode
class IController {
public:
bool isDebug();
void setDebug(bool debug);
};
Configuration widget
class IController {
public:
// UI for configuring this controller
bool hasConfigurationWidget() const;
QWidget* configurationWidget();
};
Serial interface
class IController {
public:
bool usesSerial() const;
void setSerialDevice(QSerialPort& port);
};
Configuration processing
class IController {
public:
// Load/store internal configuration
QVariantMap configuration();
void setConfiguration(const QVariantMap& map);
signals:
void configurationChanged();
};
Connection management
class IController {
public:
void setConnected(bool connected);
bool isConnected();
};
Controller handle subsystem
The controller handle subsystem adds per-actuator management:
| Feature | Description |
|---|---|
| Enable/Disable | Each actuator can be independently enabled or disabled |
| Limp/Active | Each actuator can be set to limp (unpowered) or active |
| Reverse | Each actuator can have its direction reversed |
| Trim | Each actuator can have low and high trim values set |
| Center | Each actuator can be "centered" to a default position |
Future features
| Feature | Description |
|---|---|
| Pose Targeting | Set a pose as target, making all actuators move in unison |
| Position Recording | Record poses by reading servo positions (requires special servos) |
Controller types
ArduMY controller
The default OctoMY™ controller using Arduino hardware:
{
"type": "ardumy",
"actuators": [
{"id": 0, "type": "DC_MOTOR", "name": "Left"},
{"id": 1, "type": "DC_MOTOR", "name": "Right"}
]
}
See: ArduMY Reference
Servotor32 controller
Support for Servotor32 servo controller boards:
{
"type": "servotor32",
"actuators": [
{"id": 0, "type": "SERVO", "name": "Pan"},
{"id": 1, "type": "SERVO", "name": "Tilt"}
]
}
User inputs
User inputs are artificial sensor-like values generated from the OctoMY™ user interface.
Example
A GUI presents a car steering wheel and throttle. When the user interacts using touch:
- Steering angle is generated and streamed to controller
- Throttle position is generated and streamed to controller
User input classification
Sample rate
How often is the input sampled? Usually limited by GUI refresh rate and/or input devices.
| Rate | Source |
|---|---|
| 60 Hz | Baseline (standard displays) |
| 240 Hz | High-refresh displays |
| 1000 Hz | High-performance mice |
Latency and stability are limited by UI engine performance.
Sample acquisition
| Type | Description | Example |
|---|---|---|
| Pull | Controller asks for value when needed | On-demand |
| Event | Controller receives value when available | Button press |
| Push | Controller receives steady stream of values | Joystick position |
Configuration sections
Controller section (Plan)
{
"type": "ardumy",
"actuators": [/* actuator list */]
}
| Field | Description |
|---|---|
| Type | Controller type: ardumy, servotor32 |
| Controller-specific | Remaining fields are controller-specific |
Actuator reference section
{
"controller": "main",
"actuator": "throttle",
"flags": ["reverse"]
}
| Field | Description |
|---|---|
| Controller | Reference to controller containing the actuator |
| Actuator | The actuator identifier |
| Flags | Active flags: reverse, etc. |
Lobe section
{
"type": "wheeled",
"throttle": {"controller": "main", "actuator": "throttle"},
"steering": {"controller": "main", "actuator": "steering"}
}
| Field | Description |
|---|---|
| Type | Lobe type: tracked, wheeled, hovering, legged |
| Lobe-specific | Remaining fields are lobe-type-specific |
Wheeled lobe
| Field | Description |
|---|---|
| Throttle | Actuator reference for throttle |
| Steering | Actuator reference for steering |
Legged lobe
| Field | Description |
|---|---|
| Hip (Coxa) | Actuator reference for hip joint |
| Thigh (Femur) | Actuator reference for thigh joint |
| Shin (Tibia) | Actuator reference for shin joint |
| Foot (Tarsus) | Optional actuator reference for foot joint |
Puppet and pose
Puppet section
{
"actuators": [/* puppet actuator list */]
}
Pose section
{
"puppet": "main_puppet",
"values": [
{"id": 0, "mode": "move", "value": 90},
{"id": 1, "mode": "limp"},
{"id": 2, "mode": "freeze"}
]
}
| Actuator Mode | Description |
|---|---|
| limp | Actuator is unpowered |
| freeze | Actuator holds position |
| train | Record position from servo |
| move | Move to specified value |
Animation section
{
"poses": [
{"time_ns": 0, "pose": "start"},
{"time_ns": 1000000000, "pose": "middle"},
{"time_ns": 2000000000, "pose": "end"}
]
}
Animations are sequences of poses with nanosecond timestamps. Only poses for one puppet are allowed per animation.