β οΈ DEPRECATED: This folder is deprecated and will be removed in future versions. Please use the unified cross-platformc/folder instead: C++ Development Guide
Complete C++ SDK and examples for BrainCo RevoHand devices on Linux/Ubuntu platforms.
- System Requirements
- Installation
- Quick Start
- Communication Protocols
- API Reference
- Examples
- Build System
- Operating System: Ubuntu 20.04/22.04 LTS (x86_64/aarch64), glibc β₯ 2.31
- Compiler: GCC with C++11 support
- Build Tools: make, pkg-config
- Dependencies: Stark SDK libraries (auto-downloaded)
First, download the required Stark SDK libraries:
# From project root directory
rm VERSION
./download-lib.shThis script will download the latest SDK libraries to the dist/ directory.
# Check if libraries are downloaded
ls dist/
# Should see: libstark-sdk.so and other library files#include "stark-sdk.h"
#include "stark_common.h"
#include <unistd.h>
int main() {
// Auto-detect and connect to device
auto cfg = auto_detect_modbus_revo1(NULL, true);
if (cfg == NULL) return -1;
auto handle = modbus_open(cfg->port_name, cfg->baudrate);
uint8_t slave_id = cfg->slave_id;
free_device_config(cfg);
// Control fingers - close grip
uint16_t positions_fist[] = {500, 500, 1000, 1000, 1000, 1000};
stark_set_finger_positions(handle, slave_id, positions_fist, 6);
usleep(1000 * 1000); // Wait 1 second
// Open fingers
uint16_t positions_open[] = {0, 0, 0, 0, 0, 0};
stark_set_finger_positions(handle, slave_id, positions_open, 6);
return 0;
}#include "stark-sdk.h"
#include "stark_common.h"
#include <unistd.h>
int main() {
// Initialize logging
init_logging(LOG_LEVEL_INFO);
// Auto-detect and connect to device
auto cfg = auto_detect_modbus_revo2("/dev/ttyUSB0", true);
if (cfg == NULL) return -1;
auto handle = modbus_open(cfg->port_name, cfg->baudrate);
uint8_t slave_id = cfg->slave_id;
free_device_config(cfg);
// Control fingers
uint16_t positions[] = {400, 400, 1000, 1000, 1000, 1000};
stark_set_finger_positions(handle, slave_id, positions, 6);
return 0;
}| Protocol | Description | Example Directory | Hardware Required |
|---|---|---|---|
| RS-485 (Modbus) | Serial communication | revo1/ | USB-to-RS485 adapter |
| CAN | Controller Area Network | revo1/ | ZLG USB-CAN device or SocketCAN |
| Protocol | Description | Example Directory | Hardware Required |
|---|---|---|---|
| RS-485 (Modbus) | Serial communication | revo2/ | USB-to-RS485 adapter |
| CAN | Controller Area Network | revo2/ | ZLG USB-CAN device or SocketCAN |
| CANFD | CAN with Flexible Data-Rate | revo2/ | ZLG USB-CANFD device or SocketCAN |
Include the SDK in your code:
#include "stark-sdk.h"Initialize SDK logging.
Parameters:
log_level(LogLevel): Logging levelLOG_LEVEL_DEBUGLOG_LEVEL_INFOLOG_LEVEL_WARNLOG_LEVEL_ERROR
Example:
init_logging(LOG_LEVEL_INFO);Initialize device handler for CAN/CANFD/EtherCAT protocols.
Parameters:
protocol_type(StarkProtocolType): Protocol typeSTARK_PROTOCOL_TYPE_MODBUSSTARK_PROTOCOL_TYPE_CANSTARK_PROTOCOL_TYPE_CAN_FDSTARK_PROTOCOL_TYPE_ETHER_CAT
master_id(uint8_t): Master ID (default: 0)
Returns: DeviceHandler* - Device handler instance
Example:
auto handle = init_device_handler(STARK_PROTOCOL_TYPE_CAN_FD, 0);Auto-detect and connect to Revo1 device via Modbus.
Parameters:
port_name(const char*): Serial port name.NULLfor auto-detection.quick(bool): Quick detection mode.true= faster,false= comprehensive.
Returns: DeviceConfig* - Configuration structure (must be freed with free_device_config)
Example:
auto cfg = auto_detect_modbus_revo1(NULL, true);
if (cfg != NULL) {
auto handle = modbus_open(cfg->port_name, cfg->baudrate);
uint8_t slave_id = cfg->slave_id;
free_device_config(cfg);
}Auto-detect and connect to Revo2 device via Modbus.
Parameters: Same as auto_detect_modbus_revo1
Open Modbus connection with specified parameters.
Parameters:
port_name(const char*): Serial port name (e.g., "/dev/ttyUSB0")baudrate(int): Communication baud rate
Returns: DeviceHandler* - Device handler instance
Example:
auto handle = modbus_open("/dev/ttyUSB0", 115200);Free device configuration structure.
Parameters:
config(DeviceConfig*): Configuration to free
Get device information and configuration.
Returns: DeviceInfo* - Device information structure (must be freed with free_device_info)
DeviceInfo Structure:
serial_number(char*): Device serial numberfirmware_version(char*): Firmware version stringhardware_type(StarkHardwareType): Hardware type enumSTARK_HARDWARE_TYPE_REVO1STARK_HARDWARE_TYPE_REVO1_TOUCHSTARK_HARDWARE_TYPE_REVO2STARK_HARDWARE_TYPE_REVO2_TOUCH
sku_type(StarkSkuType): SKU type
Example:
auto info = stark_get_device_info(handle, slave_id);
if (info != NULL) {
printf("Serial: %s, Firmware: %s\n",
info->serial_number, info->firmware_version);
if (info->hardware_type == STARK_HARDWARE_TYPE_REVO2_TOUCH) {
printf("Touch-enabled device\n");
}
free_device_info(info);
}Get device battery voltage.
Returns: uint16_t - Voltage in millivolts (mV)
Example:
uint16_t voltage = stark_get_voltage(handle, slave_id);
printf("Battery: %hu mV\n", voltage);Get current RS-485 baud rate.
Returns: uint32_t - Baud rate value
Get current CANFD baud rate.
Returns: uint32_t - Baud rate value
typedef enum {
STARK_FINGER_ID_THUMB = 0, // Thumb
STARK_FINGER_ID_THUMB_AUX = 1, // Thumb Auxiliary
STARK_FINGER_ID_INDEX = 2, // Index Finger
STARK_FINGER_ID_MIDDLE = 3, // Middle Finger
STARK_FINGER_ID_RING = 4, // Ring Finger
STARK_FINGER_ID_PINKY = 5 // Pinky Finger
} StarkFingerId;Set target positions for all fingers.
Parameters:
handle(DeviceHandler*): Device handlerslave_id(uint8_t): Device IDpositions(uint16_t[]): Position values for 6 joints [0-1000]count(size_t): Number of positions (should be 6)
Position Range: 0 (fully open) to 1000 (fully closed)
Example:
// Close grip
uint16_t positions_fist[] = {600, 600, 1000, 1000, 1000, 1000};
stark_set_finger_positions(handle, slave_id, positions_fist, 6);
// Open all fingers
uint16_t positions_open[] = {0, 0, 0, 0, 0, 0};
stark_set_finger_positions(handle, slave_id, positions_open, 6);Set position for a single finger.
Parameters:
handle(DeviceHandler*): Device handlerslave_id(uint8_t): Device IDfinger_id(StarkFingerId): Finger identifierposition(uint16_t): Target position [0-1000]
Example:
// Close pinky finger only
stark_set_finger_position(handle, slave_id, STARK_FINGER_ID_PINKY, 1000);Set movement speeds for all fingers.
Parameters:
speeds(int16_t[]): Speed values for 6 joints- Positive: Close direction
- Negative: Open direction
- Range: -1000 to 1000
Example:
int16_t speeds[] = {100, 100, 100, 100, 100, 100};
stark_set_finger_speeds(handle, slave_id, speeds, 6);Set movement speed for a single finger.
Parameters:
speed(int16_t): Speed value [-1000 to 1000]
Example:
stark_set_finger_speed(handle, slave_id, STARK_FINGER_ID_MIDDLE, 500);Set current for a single finger (current control mode).
Parameters:
current(int16_t): Current value [-1000 to 1000]
Example:
stark_set_finger_current(handle, slave_id, STARK_FINGER_ID_INDEX, -300);Set currents for all fingers.
Parameters:
currents(int16_t[]): Current values for 6 joints [-1000 to 1000]
Example:
int16_t currents[] = {-300, -300, -300, -300, -300, -300};
stark_set_finger_currents(handle, slave_id, currents, 6);Set PWM for a single finger (PWM control mode).
Parameters:
pwm(int16_t): PWM value [-1000 to 1000]
Set PWMs for all fingers.
Parameters:
pwms(int16_t[]): PWM values for 6 joints [-1000 to 1000]
Set position with specified speed for a single finger.
Parameters:
position(uint16_t): Target position [0-1000]speed(uint16_t): Movement speed [0-1000]
Example:
stark_set_finger_position_with_speed(handle, slave_id,
STARK_FINGER_ID_MIDDLE, 1000, 50);Set positions with speeds for all fingers.
Parameters:
positions(uint16_t[]): Target positions for 6 jointsspeeds(uint16_t[]): Movement speeds for 6 joints
Example:
uint16_t positions[] = {300, 300, 500, 500, 500, 500};
uint16_t speeds[] = {500, 500, 500, 500, 500, 500};
stark_set_finger_positions_and_speeds(handle, slave_id, positions, speeds, 6);Set position with specified duration for a single finger.
Parameters:
position(uint16_t): Target position [0-1000]duration(uint16_t): Movement duration in milliseconds
Example:
stark_set_finger_position_with_millis(handle, slave_id,
STARK_FINGER_ID_THUMB, 1000, 1000);Set positions with durations for all fingers.
Parameters:
positions(uint16_t[]): Target positions for 6 jointsdurations(uint16_t[]): Movement durations in milliseconds
Get current motor status including positions, speeds, currents, and states.
Returns: MotorStatusData* - Motor status structure (must be freed with free_motor_status_data)
MotorStatusData Structure:
positions[6](uint16_t): Current positions [0-1000]speeds[6](int16_t): Current speedscurrents[6](int16_t): Current valuesstates[6](uint8_t): Motor state flags
Example:
auto status = stark_get_motor_status(handle, slave_id);
if (status != NULL) {
printf("Positions: %hu, %hu, %hu, %hu, %hu, %hu\n",
status->positions[0], status->positions[1],
status->positions[2], status->positions[3],
status->positions[4], status->positions[5]);
printf("Currents: %hd, %hd, %hd, %hd, %hd, %hd\n",
status->currents[0], status->currents[1],
status->currents[2], status->currents[3],
status->currents[4], status->currents[5]);
free_motor_status_data(status);
}Set unit mode for finger control parameters.
Parameters:
mode(FingerUnitMode):FINGER_UNIT_MODE_NORMALIZED- Normalized values [0-1000]FINGER_UNIT_MODE_PHYSICAL- Physical units (degrees, mm/s, mA)
Get current unit mode.
Returns: FingerUnitMode
Set minimum position limit for a finger.
Get minimum position limit.
Returns: uint16_t - Minimum position value
Set maximum position limit for a finger.
Get maximum position limit.
Set maximum speed limit for a finger.
Get maximum speed limit.
Set maximum current limit for a finger.
Get maximum current limit.
Set protection current threshold for a finger.
Get protection current threshold.
Enable touch sensors.
Parameters:
mask(uint8_t): Bitmask for enabling sensors- Bit 0: Thumb
- Bit 1: Index
- Bit 2: Middle
- Bit 3: Ring
- Bit 4: Pinky
0x1F: Enable all sensors
Example:
// Enable all touch sensors
stark_enable_touch_sensor(handle, slave_id, 0x1F);Get LED status information.
Returns: LedInfo* - LED information structure (must be freed with free_led_info)
LedInfo Structure:
mode(uint8_t): LED modecolor(uint8_t): LED color
Get button event information.
Returns: ButtonEvent* - Button event structure (must be freed with free_button_event)
ButtonEvent Structure:
timestamp(int32_t): Event timestampbutton_id(int32_t): Button identifierpress_state(uint8_t): Press state
Setup signal handlers for crash debugging.
Example:
setup_signal_handlers();Verify device is Revo1 and print device info.
Returns: bool - true if device is Revo1
Verify device is Revo2 and print device info.
Returns: bool - true if device is Revo2
Get and print device information.
Returns: bool - true if successful
Get and print extended device information (baudrate, voltage, LED, button).
| Example | Description | File |
|---|---|---|
| Basic Control | Get device info, control fingers | revo1_ctrl.cpp |
| Multi Hand | Control multiple hands | revo1_ctrl_multi.cpp |
| CAN Control | Control via CAN protocol | revo1_can.cpp |
| Custom CAN | Custom CAN implementation | revo1_can_customed.cpp |
| Custom Modbus | Custom Modbus implementation | revo1_customed_modbus.cpp |
| Async Modbus | Asynchronous Modbus control | revo1_customed_modbus_async.cpp |
| Touch Sensors | Touch sensor data reading | revo1_touch.cpp |
Detailed Guide: Revo1 README
| Example | Description | File |
|---|---|---|
| Basic Control | Get device info, control fingers | revo2_ctrl.cpp |
| Multi Hand | Control multiple hands | revo2_ctrl_multi.cpp |
| CAN Control | Control via CAN protocol | revo2_can_ctrl.cpp |
| CANFD Control | Control via CANFD protocol | revo2_canfd.cpp |
| CANFD Touch | Touch control via CANFD | revo2_canfd_touch.cpp |
| Custom CANFD | Custom CANFD implementation | revo2_canfd_customed.cpp |
| Custom Modbus | Custom Modbus implementation | revo2_customed_modbus.cpp |
| Async Modbus | Asynchronous Modbus control | revo2_customed_modbus_async.cpp |
| Touch Sensors | Touch sensor data reading | revo2_touch.cpp |
Detailed Guide: Revo2 README
The Makefile provides intelligent build commands that auto-detect the correct mode:
# Smart compile + run (auto-detects MODE)
make run revo1_ctrl # Modbus programs (default)
make run revo1_can # Auto-detects CAN mode
make run revo2_ctrl # Modbus programs
make run revo2_canfd # Auto-detects CANFD mode
# Show available targets
make run # Shows usage help# Clean build artifacts
make clean
# Build with specific modes
make # Build with default mode (Modbus)
make MODE=can # Build with CAN interface mode
# Run only (must be compiled first)
make run_revo1_ctrl # Run revo1_ctrl example
make run_revo2_ctrl # Run revo2_ctrl example| Mode | Description | Required Hardware |
|---|---|---|
| (default) | Modbus/RS-485 | USB-to-RS485 adapter |
MODE=can |
CAN/CANFD | ZLG USB-CAN(FD) device or SocketCAN adapter |
For ZLG USB-CAN(FD), ensure libusbcanfd.so is installed. If missing, run ./download-lib.sh
to populate dist/shared/linux or set ZLG_LIB_DIR=/path/to/lib.
The build system automatically includes:
-I../../dist/include- SDK headers-L../../dist/lib- SDK libraries-lstark-sdk- Stark SDK library-ldl- Dynamic loading library (for ZLG runtime loading)-std=c++11- C++11 standard
All CAN backends are compiled by default. Select at runtime via environment variables:
# Build (all backends compiled by default)
make MODE=can
# Disable CAN support entirely
make STARK_NO_CAN=1Runtime backend selection:
# SocketCAN (Linux default, no 3rd party deps)
export STARK_CAN_BACKEND=socketcan
export STARK_SOCKETCAN_IFACE=can0
# ZLG USB-CANFD (dynamic loading, no compile-time dependency)
export STARK_CAN_BACKEND=zlg
export STARK_ZLG_LIB_PATH=/path/to/libusbcanfd.so # Optional custom pathTypical CANFD interface setup (example only):
sudo ip link set can0 down
sudo ip link set can0 type can bitrate 1000000 dbitrate 5000000 fd on
sudo ip link set can0 upRun examples:
# SocketCAN (default on Linux)
STARK_SOCKETCAN_IFACE=can0 make run revo1_can
STARK_SOCKETCAN_IFACE=can0 make run revo2_can_ctrl
STARK_SOCKETCAN_IFACE=can0 make run revo2_canfd
# ZLG backend
STARK_CAN_BACKEND=zlg make run revo2_canfdFor technical support:
- Check example code in subdirectories
- Review API documentation above
- Contact BrainCo technical support
- Always call
setup_signal_handlers()at the start of your program for better debugging - Remember to free allocated structures (
free_device_config,free_device_info,free_motor_status_data, etc.) - Position values range from 0 (open) to 1000 (closed) for all devices
- For Revo2, use
init_cfg()before connecting to the device - Touch-enabled devices require
stark_enable_touch_sensor()before reading sensor datads
Version: Compatible with Stark SDK v1.1.9