Software Setup
SDK installation, CAN driver setup, ROS2 controller configuration, LeRobot integration for O6, Python API examples, and top troubleshooting issues. From a fresh Ubuntu install to a moving arm.
Jump to a section:
SDK Installation
The LinkerBot O6 SDK provides Python bindings to the arm's CAN bus interface. It is included in the RoboticsCenter platform package.
Create a virtual environment (recommended)
python3 -m venv ~/.venvs/linkerbot-o6
source ~/.venvs/linkerbot-o6/bin/activate
Install the SDK
pip install roboticscenter
Verify the installation
python3 -c "from linkerbot import LinkerBotO6; print('SDK ready')"
Install from source (optional)
git clone https://github.com/linkerbot/linkerbot_sdk.git
cd linkerbot_sdk
pip install -e .
CAN Driver Setup
The LinkerBot O6 uses the same SocketCAN architecture as the OpenArm 101. If you have set up CAN for OpenArm, this process is identical. The CAN bus drivers are built into the Linux kernel.
Load kernel modules
sudo modprobe can
sudo modprobe can_raw
sudo modprobe slcan # for USB CAN adapters (CANable)
Bring up the CAN interface
# Find the USB serial device
ls /dev/ttyACM*
# Bring up CAN interface at 1 Mbps
sudo slcand -o -c -s8 /dev/ttyACM0 can0
sudo ip link set up can0
Verify the interface is up
ip link show can0
# Expected: can0: <NOARP,UP,LOWER_UP> mtu 16 ...
Test CAN communication
sudo apt install can-utils -y
candump can0
# Power on the O6 and look for motor heartbeat packets
Make persistent across reboots
Create a systemd service or add to /etc/rc.local. See the SocketCAN Setup Guide — the procedure is identical for the O6.
ROS2 Controller Setup
The linkerbot_ros2 package provides a full ros2_control hardware interface for the O6. It includes fake hardware mode for testing without the arm.
Install ROS2 Humble
sudo apt update && sudo apt install software-properties-common curl -y
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | \
sudo apt-key add -
sudo sh -c 'echo "deb http://packages.ros.org/ros2/ubuntu jammy main" \
> /etc/apt/sources.list.d/ros2.list'
sudo apt update
sudo apt install ros-humble-desktop ros-humble-ros2-control \
ros-humble-ros2-controllers ros-humble-joint-state-publisher-gui -y
Clone and build linkerbot_ros2
mkdir -p ~/o6_ws/src && cd ~/o6_ws/src
git clone https://github.com/linkerbot/linkerbot_ros2.git
cd ~/o6_ws
source /opt/ros/humble/setup.bash
colcon build --symlink-install
Launch in fake hardware mode (no arm required)
source ~/o6_ws/install/setup.bash
ros2 launch linkerbot_ros2 o6.launch.py use_fake_hardware:=true
Launch with real hardware
ros2 launch linkerbot_ros2 o6.launch.py \
use_fake_hardware:=false \
can_interface:=can0
Verify joint states
ros2 topic echo /joint_states
LeRobot Integration for O6
LeRobot supports the LinkerBot O6 natively. Configure your robot type and follow the standard LeRobot workflow for recording and training.
Install LeRobot
pip install lerobot
Configure your O6 robot
# ~/.lerobot/robots/linkerbot_o6.yaml
robot_type: linkerbot_o6
can_interface: can0
num_joints: 6
camera_names:
- wrist_cam
- overhead_cam
Record a dataset
python -m lerobot.scripts.control_robot \
--robot.type=linkerbot_o6 \
--control.type=record \
--control.fps=30 \
--control.repo_id=your-username/o6-pick-place \
--control.num_episodes=50 \
--control.single_task="Pick up the red cube"
Upload to HuggingFace Hub
huggingface-cli login
python -m lerobot.scripts.push_dataset_to_hub \
--repo_id=your-username/o6-pick-place
See the Data Collection page for the complete workflow including quality checks.
Python API Examples
The LinkerBot Python SDK provides direct joint control without requiring ROS2. Same pattern as the OpenArm SDK.
Basic joint control
from linkerbot import LinkerBotO6
# Connect to the arm
arm = LinkerBotO6(can_interface="can0")
arm.connect()
arm.enable_all()
# Move joint 1 to 45 degrees (0.785 rad)
arm.set_position(joint_id=1, position=0.785, kp=50, kd=1)
# Read current state
state = arm.get_state()
print(f"Positions (rad): {state.positions}")
print(f"Velocities (rad/s): {state.velocities}")
print(f"Torques (Nm): {state.torques}")
# Safe shutdown
arm.disable_all()
arm.disconnect()
Read all joints in a control loop
import time
from linkerbot import LinkerBotO6
arm = LinkerBotO6(can_interface="can0", control_rate_hz=500)
arm.connect()
arm.enable_all()
for _ in range(500): # 1 second at 500 Hz
state = arm.get_state()
print(state.positions)
time.sleep(1 / 500)
arm.disable_all()
arm.disconnect()
Trajectory execution
from linkerbot import LinkerBotO6, JointTrajectory
import numpy as np
arm = LinkerBotO6(can_interface="can0")
arm.connect()
arm.enable_all()
# Define a waypoint trajectory
waypoints = [
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.5, -0.3, 0.8, 0.0, 0.4, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
]
durations = [2.0, 2.0, 2.0] # seconds per segment
traj = JointTrajectory(waypoints=waypoints, durations=durations)
arm.execute_trajectory(traj)
arm.disable_all()
arm.disconnect()
Top 3 Common Issues
no such device can0
The SocketCAN interface is not up. Almost always because the USB CAN adapter is not connected or kernel modules are not loaded.
Fix:
# 1. Verify USB adapter is detected
lsusb | grep -i "can\|serial"
# 2. Load the kernel modules
sudo modprobe can && sudo modprobe can_raw && sudo modprobe slcan
# 3. Bring up the interface
sudo slcand -o -c -s8 /dev/ttyACM0 can0
sudo ip link set up can0
# 4. Verify
ip link show can0
arm.enable_all()
Motors are not receiving commands. Most commonly caused by incorrect CAN IDs, CAN bus error frames, or insufficient power supply voltage.
Fix:
# 1. Check for CAN error frames
candump can0 | grep -i "error"
# 2. Check power supply — O6 requires 24V @ 150W minimum
# 3. Scan for motors and verify IDs
python3 -c "from linkerbot import LinkerBotO6; a=LinkerBotO6('can0'); a.scan_motors()"
# 4. Power cycle the arm and retry
robot not found
LeRobot cannot find the O6 robot configuration or the CAN interface is not up when LeRobot starts.
Fix:
# 1. Verify CAN interface is up before starting LeRobot
ip link show can0
# 2. Verify config file path and format
cat ~/.lerobot/robots/linkerbot_o6.yaml
# 3. Test direct SDK connection first
python3 -c "
from linkerbot import LinkerBotO6
a = LinkerBotO6(can_interface='can0')
a.connect()
print('Connected:', a.get_state())
a.disconnect()"
# 4. Then retry LeRobot
python -m lerobot.scripts.control_robot \
--robot.type=linkerbot_o6 \
--control.type=teleoperate
Still stuck? Post in the SVRC Forum or visit the O6 Wiki.