Skip to content

RCSP Specification

This document will specify everything needed to implement the Rokoko Command Server Protocol (RCSP).

The RCSP became necessary as a part of decoupling the higher layers of the SW stack from direct knowledge of the exact binary layout of the device commands. The protocol offers a binary agnostic way of presenting commands that can be run on both the driver and the devices.

Further, it also serves as a way of monitoring events in the driver based on a publisher-subscribe model.

Any piece of software can implement a RCSP server or client, but the protocol is specifically tailored to handle device commands, so only SW that interacts with devices should implement the server side. As of this writing, only the Rokoko Device Driver implements the server side.

The server side does the heavy lifting in that it converts the low-level binary details to a uniform interface (i.e., the RCSP).

It also abstracts away the physical communication, so that the client does not have to worry about various protocols, like USB, UART, UDP, etc., but can use a single, robust, protocol (TCP).

On the client side all the benefits of this abstraction is reaped. Any tool that wants to talk to devices in a uniform or wants to use some of the other features can implement RCSP and control devices, analyze recordings, do device configuration, upload firmware, etc.

This opens up for a convenient way of doing tooling.

  • The protocol is based on TCP
  • The server listens on port 45451
  • The server MUST be able to handle multiple clients simultaneously
  • The server MUST be able to queue commands
  • All commands MUST elicit a response
    • This MUST be either a valid response or an error response
  • The order of responses MUST follow the order of the commands
  • Events are allowed to come between commandresponse pair
  • The protocol is Case-Sensitive
  • Optional JSON values MAY be null

All messages consists of a binary header followed by a JSON payload.

struct header {
enum payload_type : uint8_t {
command = 1,
response_ok = 2,
response_error = 3,
event = 4,
};
static constexpr uint8_t marker_val{};
uint8_t marker{0xDC}; // 0xDC = DeviceCommands
uint8_t header_version{1};
uint8_t header_size{sizeof(*this)};
payload_type type;
uint32_t payload_size;
};

This header describes the payload type. The following rules applies to these types:

payload_typeDirection AllowedPayload Format
commandClient ⟹ ServerJSON
responseServer ⟹ ClientJSON
eventServer ⟹ ClientJSON

Payloads are JSON based. The payload_types each have an associated JSON object that they wrap their data in.

In the following, this syntax is used:

  • object_ref: A reference to another named JSON object
  • Optional values are prefixed with opt_
    • All values without opt_ prefixed are required
  • All objects in the JSON object trees all end in the basic JSON types:
    • "<string>", "<number>", "<boolean>", "<null>"
  • "<array>"s and "<object>"s containing a type are denoted:
    • "array<object_ref>" and "object<object_ref>"
"Command": "<string>"
"TrackId": "<string>"
"Version": "<number>"
"Arguments": "<opt_object>"

Where “Arguments” is a an object with key-value pairs, where the key SHALL be the argument’s Name.

The TrackId is SHALL be echoed in the same key in rcsp_response_payload.

Response Payload (Success) (rcsp_response_payload)

Section titled “Response Payload (Success) (rcsp_response_payload)”

A generic ok without payload:

"TrackId": "<string>"
"Status": "<string>"
"Version": "<number>"
"Response": "<opt_object>"

Some commands just have a simple “Ok” response, in which case the "Response": "<opt_object>" may be omitted. This response is named rcsp_response_ok.

Response Payload (Error) (rcsp_response_error)

Section titled “Response Payload (Error) (rcsp_response_error)”
"TrackId": "<string>"
"Status": "<string>"
"Version": "<number>"
"Error": "<rcsp_error>"

Where rcsp_error is:

"Code": "<string>"
"Message": "<opt_string>"

The available error codes are:

Code
Unknown error
Unknown command
Invalid marker
Wrong header type
Parse error
Missing required argument
Missing required key
Invalid argument
Invalid value type
Invalid value
Runtime error
Device not found
Device not available
Device command error
Sub-device not found
Unsupported command
Busy
Response too small
Device not updatable

They can also be listed with the “ListErrorCodes” command.

"Publisher": "<string>",
"Topic": "<string>",
"EventData": "<publisher dependent (see below)>"

The possible available Publishers and their EventData can be seen in the table below:

NOTE

This list may not be exhaustive. Use the “ListPublishers” command for a list of actual supported Publishers and their Topics

Non-device publishers (subscribed via “Subscribe”):

PublisherTopicEventData
”DeviceEvents""Seen"
"Connected"
"Initialized"
"Mapped"
"Disconnected"
"Destroyed"
"Calibrated"
"FlipDecided"
"EmfSaturated"
"GyrSaturated"
"AccSaturated"
"CoilDetected"
"BootloaderConnected"
"BootloaderDisconnected”
rcsp_device_event_data
”Logs""Error"
"Warning"
"Info”
rcsp_log_event_data
”UpdateFwEvents""Progress"
"Failure"
"Done”
rcsp_update_fw_event_data

Device-specific publishers (subscribed via “DeviceSubscribe”, requires DeviceId):

PublisherTopicEventData
”DeviceLogs""Error"
"Warning"
"Info"
"Debug”
rcsp_device_log_event_data
”DeviceEvents""ButtonPushed”rcsp_device_event_data
"EventSuccess": "<opt_string>",
"DeviceId": "<opt_number>",
"IsBootloader": "<opt_boolean>",
"ButtonPushType":"<opt_string>"

“EventSuccess” can be either “Success” or “Failure”.

“DeviceId” corresponds to the “DeviceId” in the “ListDevices” response.

“ButtonPushType” is only present for the “ButtonPushed” topic and can be one of:

  • “SinglePress”
  • “DoublePress”
  • “LongPress”
"LogMsg": "<string>"
"LogMsg": "<string>",
"DeviceId": "<number>",
"TimestampNs": "<number>",
"SrcLocation": "<string>"

“TimestampNs” is the device-local timestamp in nanoseconds.

“SrcLocation” is the source location string (e.g., module or function name) of the log message origin on the device.

"PercentComplete": "<opt_number>",
"ErrorMsg": "<opt_string>"

For all the command tables below, the following holds:

  • Each command is the value of “Command” in rcsp_cmd.
  • All the arguments given in Arguments are key-value pairs in the “Response” object in rcsp_cmd.
    • If Arguments in the table is null, it is not needed.
  • Each response object is the “Response” in rcsp_response_payload.

IMPORTANT

The Response shows the expected response on success. On failure, all commands will get the same rcsp_response_error.

Some commands use the same objects or object arguments. To highlight when this is the case, these will be presented separately here and referred to below by name (given in the header):

"DeviceId": "<number>"

A general description of an argument.

"Name": "<string>",
"Info": "<string>",
"Type": "<string>",
"Optional": "<boolean>"

The Name refers to the key used in the key-value pairs in the argument dictionary. The “Type” can be one of:

  • “String”
  • “Number”
  • “Array”
  • “Object”
  • “Boolean”

“Optional” determines if the argument is optional or required.

A general description of a command.

"Command": "<string>"
"Version": "<number>"
"Info": "<string>"
"Args": "array<rcsp_arg_description>"

An array of bytes that might be printable. The “Raw” field holds the numbers (decimal format) while the string shows the printable version (this is context specific) and could be fx “0xabcd” or, if the context calls for characters, “some_string”.

NOTE

The printable ("Str") will only show the characters until the first non-printable character.

"Raw": "array<number>",
"Str": "<string>"

RCSP’s general representation of a version.

"Major": "<number>",
"Minor": "<number>",
"Patch": "<opt_number>",
"Build": "<opt_number>"
"X": "<number>",
"Y": "<number>",
"Z": "<number>"
[
["<number>", "<number>", "<number>"],
["<number>", "<number>", "<number>"],
["<number>", "<number>", "<number>"]
]
CommandArgumentsResponseDescription
”Info”nullrcsp_infoGet basic info
”GracefulExit”nullrcsp_response_okStop the entire application
”ListCommands”nullrcsp_cmd_listList available Top-level commands
”ListDevices”nullrcsp_device_listList connected devices
”ListErrorCodesnullrcsp_error_code_listList all error codes
”ListDeviceCommands”device_id_argrcsp_device_cmd_listList available commands for a given device. Details here.
"UpTimeSecs": "<number>",
"SupportedHeaderVersions": "array<number>",
"AppVersion": "<rcsp_version_obj>",
"GitSha": "<string>",
"SystemName": "<string>"

NOTE

The “SupportedHeaderVersions” refers to the binary header supported versions.

The “SystemName” value contains the OS name.

"Commands": "array<rcsp_cmd_description>"
"Devices": "array<rcsp_device>"

Where rcsp_device is:

"DeviceId": "<number>",
"DeviceType": "<string>",
"ConnectionType": "<string>",
"Updatable": "<boolean>",
"IsBootloader": "<boolean>",

Where “DeviceType” can be:

  • “SmartSuitPro”
  • “Smartgloves”
  • “CoilPro”
  • “Unknown”

and “ConnectionType” can be:

  • “Serial”
  • “UDP”
  • “Emulated”
  • “Unknown”
"ErrorCodes": "array<string>"
"DeviceCommands": "array<rcsp_cmd_description>"
CommandArgumentsResponseDescription
”ListPublishers”opt_device_id_argrcsp_publisher_listList available publishers. With DeviceId, lists device publishers
”Subscribe”rcsp_subscription_argrcsp_response_okSubscribe to non-device publishers along with their topics
”Unsubscribe”rcsp_subscription_argrcsp_response_okUnsubscribe from non-device publishers
”DeviceSubscribe”rcsp_device_subscribe_argrcsp_response_okSubscribe to device-specific publishers (requires DeviceId)
“DeviceUnsubscribe”rcsp_device_subscribe_argrcsp_response_okUnsubscribe from device-specific publishers (requires DeviceId)
"DeviceId": "<opt_number>"
"Publishers": "array<rcsp_publisher>",

where rcsp_publisher is:

"Publisher": "<string>",
"Topics": "array<string>"
"Publishers": "array<rcsp_publisher>"
"DeviceId": "<number>",
"Publishers": "array<rcsp_publisher>"

See Events or run the ListPublishers cmd for possible values.

Not all commands are supported by all devices. The supported commands can be polled. The potential supported device commands are:

CommandArgumentsResponseDescription
”SetEmfChannel”rcsp_set_emf_ch_argrcsp_response_okSet EMF channel
”GetEmfChannel”device_id_argrcsp_response_emf_chGet EMF channel
”ReadSensorFwInfo”device_id_argrcsp_response_fw_infoGet Sensor FW information
”SetDeviceName”rcsp_device_name_argrcsp_response_okSet the name of the device
”GetDeviceName”device_id_argrcsp_response_device_nameGet the name of the device
”SetFrameRate”rcsp_frame_rate_argrcsp_response_okSet the device’s (desired) frame rate
”GetFrameRate”device_id_argrcsp_response_frame_rateGet the device’s (expected) frame rate
”GetDeviceInfo”device_id_argrcsp_response_glove_info
rcsp_response_ssp_info
Get various information from the device
”CalibrateStaticPose”device_id_argrcsp_response_okCalibrate device with a static (non-moving) pose
”ReinitAlgo”device_id_argrcsp_response_okReinitialize the device’s algorithm
”GetWifiVersion”device_id_argrcsp_response_wifi_verGet the version of the wifi module
”SetNetworkConfiguration”rcsp_net_settings_argrcsp_response_okSet the devices network configuration
”GetNetworkConfiguration”device_id_argrcsp_response_net_settingsGet the devices network configuration
”ScanNetwork”rcsp_net_scan_argrcsp_response_scan_resultScan the network in the given band / channel
”StartWifi”rcsp_start_wifi_argrcsp_response_okStart the wifi module with the latest settings. Optionally set a connection timeout.
”PostProcess”rcsp_postprocess_argrcsp_response_okControl postprocessing
”UpdateFirmware”rcsp_fw_update_arg rcsp_response_okUpdate FW. Will update progress through events.
”UpdateSensorFirmware”rcsp_sensor_fw_update_arg rcsp_response_okUpdate sensor FW. Will update progress through events.
”UpdateWifiModule”rcsp_update_wifi_module_arg rcsp_response_okUpdate WiFi Module FW. Will update progress through events.
”SetColorLed”rcsp_set_color_led_arg rcsp_response_okSet the given clor LED.
”SetLedBehavior”rcsp_set_led_behavior_arg rcsp_response_okSet the LED behavior.
”SetMagnetometerCalOffset”rcsp_set_mag_offset_argrcsp_response_okSet the magnetometer calibration offset [mG].
”GetMagnetometerCalOffset”device_id_argrcsp_3df_vecGet the magnetometer calibration offset [mG].
”RunSelfTest”device_id_argrcsp_response_self_test_resultsRun self test and get the results
”SubscribeToData”device_id_argrcsp_response_okSubscribe to sensor data from the device
”UnsubscribeFromData”device_id_argrcsp_response_okUnsubscribe from sensor data from the device

NOTE

Whether “SubscribeToData” is required depends on the transport:

  • USB-connected devices: data streaming is off by default. Call “SubscribeToData” to start receiving sensor data, and “UnsubscribeFromData” to stop.
  • TCP-connected devices: data streaming is on by default. No explicit subscription is required to start receiving data.

These are sensible defaults for the most common use cases of each transport, but either behavior can be toggled at runtime with “SubscribeToData” / “UnsubscribeFromData”.

"DeviceId": "<number>",
"Channel": "<number>"
"Channel": "<number>",
"FreqX": "<opt_number>",
"FreqY": "<opt_number>",
"FreqZ": "<opt_number>"

The frequency values are in Hz. They are only available in version 2 of the command.

"DeviceId": "<number>",
"DeviceName": "<string>"
"DeviceId": "<number>",
"FrameRate": "<number>"
"DeviceId": "<number>",
"Settings": "<rcsp_net_settings>"
"DeviceId": "<number>",
"Band": "<number>",
"ChannelNo": "<number>"
"DeviceId": "<number>",
"TimeoutMs": "<opt_number>"
  • TimeoutMs”: Connection timeout in milliseconds. If omitted, no timeout is used.

where rcsp_net_settings:

"HubAddr": "<number>",
"DhcpMode": "<number>",
"ChannelNo": "<number>",
"SecurityType": "<string>",
"ServerIp": "<string>",
"ServerPort": "<number>",
"DeviceIp": "<string>",
"Gateway": "<string>",
"Band": "<number>",
"Ssid": "<rcsp_printable_byte_array>",
"Psk": "<rcsp_printable_byte_array>",

FrameRate” is in Hz. If the arg does not match with an available option, it will be rounded to nearest available.

Band” can be:

  • 0: 2.4 GHz
  • 1: 5 GHz
  • 2: Dual Band

SecurityType” can be:

  • “Open”
  • “WPA2”
  • “WPA3_Personal”
"DeviceId": "<number>",
"ProcessType": "<string>"

where "ProcessType" should be one of:

  • StartSmoothing
  • StopSmoothing

Note that “StopSmoothing” can only be called after start “StartSmoothing”.

When “StopSmoothing” is called, the processing of all the data will commence and will be delivered via the output of the driver.

This will happen through a new device that will present itself in the output (via a new definition frame). All the processed output will be linked to the device_id of this special device. The definition frame for this special device will be tagged with a special key to denote it is postproccesed data, so the user can handle it in a special way, like filter it out from display or save it to a recording.

"DeviceId": "<number>",
"FwPath": "<string>",
"ForceUpdate": "<opt_bool>",
  • ForceUpdate”: Updates will try to force update a device, even if some discrepancies have been found. For example if the header of the FW file does not match the device type or the magic number is wrong. (Default: false)
"DeviceId": "<number>",
"FwPath": "<string>",
"ForceUpdate": "<opt_bool>",
"SensorsInBoot": "<opt_bool>",

Same as rcsp_fw_update_arg, but for sensor FW updates.

  • SensorsInBoot”: If sensors are already in bootloader, sometimes the RCSP Server must know to take appropriate action when updating. (Default: false)
"DeviceId": "<number>",
"FwPath": "<string>",
"DeviceId": "<number>",
"LedId": "<string>",
"Red": "<number>",
"Green": "<number>",
"Blue": "<number>",

All numbers color components are between 0-255.

And the “LedId” for Smartgloves II can be:

  • RingLed
"DeviceId": "<number>",
"LedId": "<string>",
"BehaviorType": "<string>",

The “BehaviorType” can be one of:

  • “On”
  • “Off”

The “LedId” for Smartgloves II can be:

  • StatusLed
"DeviceId": "<number>",
"Offset": "object<rcsp_3df_vec>",
"Sensors": "array<sensor_info>"

Where "sensor_info" is:

"Addr": "<number>",
"RawHeading": "<number>",
"Signature": "<number>",
"FwVersion": "<rcsp_version_obj>",
"BootVersion": "<rcsp_version_obj>",
"BootStatus": "<number>",
"BootStatusStr": "<string>",
"IsCalibrated": "<number>",
"ValidCalib" "<boolean>"
"Epoch": "<number>",
"CalibrationID": "<number>",
"IdUnique": "<rcsp_printable_byte_array>",
"SensorSetupStatus": "<number>",
"BuildNumber": "<number>",
"ProdAssyRaw": "<number>",
"HwVersion": "<rcsp_version_obj>",
"Vendor" "<string>",
"InBootloader" "<boolean>",

Note that “Addr”, “Data”, “Module” and “Command” are decomposed from the “RawHeading”.

rcsp_response_glove_info / rcsp_response_ssp_info (common)

Section titled “rcsp_response_glove_info / rcsp_response_ssp_info (common)”

The response differs, depending on whether the command is sent to a SSP, a Smartglove, or a Coil Pro. The common part is:

"Header": "<string>",
"IdUnique": "<rcsp_printable_byte_array>",
"FwVersion": "<rcsp_version_obj>",
"BootVersion": "<rcsp_version_obj>",
"UsbApiVersion": "<rcsp_version_obj>",
"WifiApiVersion": "<rcsp_version_obj>",
"BtApiVersion": "<rcsp_version_obj>",
"HubSerialNumber": "<rcsp_printable_byte_array>",
"ProdAssyRaw": "<number>",
"DeviceType": "<string>",
"HwVersion": "<rcsp_version_obj>",
"ProdBoardId": "<number>",
"ProdDate": "<number>",
"ProdEpoch": "<number>",
"BuildEpoch": "<number>",
"<DEVICE_SPECIFIC>": "see below"

Where "<DEVICE_SPECIFIC>" is device specifc.

For rcsp_response_glove_info, "<DEVICE_SPECIFIC>" = "Smartgloves" and the value is:

"IsLeft": "<boolean>",

For rcsp_response_ssp_info, "<DEVICE_SPECIFIC>" = "SmartSuitPro" and the value is:

"Features": {
"Bitmask": "<number>",
"IsGloveReady": "<boolean>",
"HasLeftGlove": "<boolean>",
"HasRightGlove": "<boolean>",
"HasSTSensor": "<boolean>"
},

For rcsp_response_ssp_info, "<DEVICE_SPECIFIC>" = "CoilPro", no extra values.

"WifiFwVersion": "<string>"

Same as rcsp_net_settings.

"ScanResults": "array<rcsp_scan_result>"

Where rcsp_scan_result is:

"ChannelNo": "<number>",
"SecurityMode": "<string>",
"Rssi": "<number>",
"Ssid": "<rcsp_printable_byte_array>",
"Bssid": "<rcsp_printable_byte_array>"
"FrameRate": "<number>"
"DeviceName": "<string>"
"DeviceId": "<number>",
"HwVersion": "<rcsp_version_obj>",
"DeviceType": "<string>",
"ProdBoardId": "<number>",
"ProdDate": "<number>",
"ProdEpoch": "<number>",
"Password": "<string>",
"SmartglovesInfo": "<opt_rcsp_smartgloves_prod_info>"

NOTE

The “Password” is a 4 character string and is required for the command to succeed.

NOTE

The HwVersion only contains Major and Minor - Patch and Build are ignored.

TODO: units of ProdDate and ProdEpoch

The “DeviceType” can be:

  • “Smartgloves”
  • “SmartSuitPro”
  • “CoilPro”

Each has a required device specific production info object, where only one will be filled based on the “DeviceType”:

For Smartgloves, rcsp_smartgloves_prod_info:

"IsLeftGlove": "<boolean>"

For SmartSuitPro, rcsp_ssp_prod_info:

TODO:

For CoilPro, no extra info.

"HubMagnetometerData_Gauss": "<opt_rcsp_3df_vec>",
"AmpCtrlSignal_Percent": "<opt_rcsp_3df_vec>",
"ImuAccData_g": "array<rcsp_3df_vec>",
"ImuGyrData_Rad_s": "array<rcsp_3df_vec>",
"ArmSignedMagGainSwitchOn": "<opt_rcsp_3x3_mat>",
"ArmSignedMagGainSwitchOff": "<opt_rcsp_3x3_mat>",
"SensorsSignedMag": "array<rcsp_3x3_mat>",
"AdcMeanInternalAdc_V": "array<rcsp_3df_vec>",
"AdcStdDevInternalAdc_V": "array<rcsp_3df_vec>",
"AdcMeanExternalAdc_V": "<opt_rcsp_3df_vec>",
"AdcStdDevExternalAdc_V": "<opt_rcsp_3df_vec>",
"IndexToSmartglovesSensorLoc": "array<string>"

For all the arrays, the name of the sensor can be retrieved via the IndexToSmartglovesSensorLoc array, where the index corresponds to the index in the data arrays.

Commands for interfacing with recording / playback.

CommandArgumentsResponseDescription
”SaveUserData”rcsp_user_json_data_argrcsp_response_okSave the specified JSON data to the current recording with the given tag (Requires a started recording).
”LoadJsonData”rcsp_load_user_json_data_argrcsp_load_user_json_data_arg_responseLoad JSON data with the given tag (Requires a loaded recording, i.e., playback).
”ListJsonDataTags”nullrcsp_list_user_data_tags_responseList all tags for saved JSON data
"Tag": "<number>",
"UserData": "<object>"

Note that the UserData is JSON formatted, so it can be any struct the user wants. The Tag can be used to save various different structs. The Tag must be > 0.

"Tag": "<number>"

Tag corresponds to the tag that was saved.

Same as rcsp_user_json_data_arg

"Tags": "array<number>"
CommandArgumentsResponseDescription
”TestEvent”rcsp_test_event_argrcsp_response_okThe specified event will be sent as a side-effect, if response is ok.
"Publisher": "<string>",
"Topic": "<string>"

We want to subscribe to device events, specifically we want to know when devices Connected and Disconnected. We are also interested in getting “Warning” logs. To do this, we use the “Subcribe” command. It needs the argument rcsp_subscription_arg. We fill out the rcsp_cmd object:

"Command": "Subscribe",
"TrackId": "MyTrackId42",
"Version": 1,
"Arguments": {
"Subscriptions": [
{
"Publisher": "DeviceEvents",
"Topics": [
"Connected",
"Disconnected"
]
},
{
"Publisher": "Logs",
"Topics": [
"Warning"
]
}
]
}

As noted above in the table, if this command was succesful it will respond with a rcsp_response_ok:

"Status": "Ok",
"TrackId": "MyTrackId42"