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:

Step 1 — SDK Installation

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 .
Step 2 — CAN Driver Setup

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.

Step 3 — ROS2 Controllers

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
Step 4 — LeRobot for O6

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.

Step 5 — Python API

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()
Troubleshooting

Top 3 Common Issues

Error 1 CAN interface not found: 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
Error 2 Joints not responding after 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
Error 3 LeRobot fails to connect: 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.

Software Working? Start Collecting Data.

Once the O6 is moving, the next step is teleoperation and dataset recording with LeRobot.