Beam Bots Logo

Beam Bots UFactory xArm control

License: Apache 2.0Hex version badge

BB.Ufactory

BB integration for UFactory xArm robotic arms.

This library provides controller, actuator, and sensor modules for integrating UFactory xArm arms with the Beam Bots robotics framework. The arm is commanded over two TCP connections using UFactory's custom Modbus-TCP protocol: a command socket (port 502) and a real-time report socket (port 30003) that pushes joint state at ~100Hz.

Features

Supported Arms

Installation

Add bb_ufactory to your list of dependencies in mix.exs:

def deps do
[
{:bb_ufactory, "~> 0.1.0"}
]
end

Requirements

Usage

Quick Start with the Pre-Built xArm6 Robot

BB.Ufactory.Robots.XArm6 provides a ready-made robot definition with correct joint limits, effort values, and actuator wiring. Use it as a base and override the controller host:

defmodule MyRobot do
use BB.Ufactory.Robots.XArm6
controllers do
controller :xarm, {BB.Ufactory.Controller,
host: "192.168.1.111",
model: :xarm6,
loop_hz: 100
}
end
end

Custom Robot Definition

For custom topologies or additional accessories, define the robot manually in your BB DSL:

defmodule MyRobot do
use BB
controllers do
controller :xarm, {BB.Ufactory.Controller,
host: "192.168.1.111",
model: :xarm6,
loop_hz: 100
}
end
topology do
link :base do
joint :j1 do
type :revolute
limit do
lower ~u(-360 degree)
upper ~u(360 degree)
velocity ~u(180 degree_per_second)
end
actuator :j1_motor, {BB.Ufactory.Actuator.Joint, joint: 1, controller: :xarm}
# ... links and joints j2–j6 ...
end
end
end
sensors do
sensor :wrench, {BB.Ufactory.Sensor.ForceTorque, controller: :xarm}
sensor :collision, {BB.Ufactory.Sensor.Collision, controller: :xarm, sensitivity: 3}
end
end

Sending Commands

Joint-Space Motion

BB.Actuator.set_position(MyRobot, [:base, :j1, :j1_motor], 0.5)

Cartesian Motion

BB.Actuator.set_position(MyRobot, [:cartesian, :tcp], {300.0, 0.0, 400.0, 0.0, 0.0, 0.0})

Subscribing to State

# Joint angles + torques from every report frame
BB.subscribe(MyRobot, [:sensor, :xarm])
# TCP pose from every report frame
BB.subscribe(MyRobot, [:sensor, :xarm, :tcp_pose])
# Arm state/mode/fault changes
BB.subscribe(MyRobot, [:sensor, :xarm, :arm_status])
# F/T readings (when sensor is enabled)
BB.subscribe(MyRobot, [:sensor, :wrench])
# Collision events
BB.subscribe(MyRobot, [:sensor, :collision])

Components

Controller

BB.Ufactory.Controller manages both TCP connections and the 100Hz control loop.

OptionTypeDefaultDescription
hoststringrequiredArm IP address or hostname
portinteger502Command socket port
report_portinteger30003Real-time report socket port
modelatom:xarm6Arm model (:xarm5, :xarm6, :xarm7, :lite6, :xarm850)
loop_hzinteger100Control loop frequency in Hz
heartbeat_interval_msinteger1000Heartbeat interval in ms
disarm_actionatom:stopAction on disarm: :stop clears motion, :hold holds position
tcp_offsettuple or nilnilTCP offset {x_mm, y_mm, z_mm, roll_rad, pitch_rad, yaw_rad}
tcp_loadtuple or nilnilTool payload {mass_kg, com_x_mm, com_y_mm, com_z_mm}
reduced_modebooleanfalseEnable firmware reduced mode (lower speed limits + optional fence)
reduced_tcp_speedfloat or nilnilMax TCP linear speed in mm/s (reduced mode)
reduced_joint_speedfloat or nilnilMax joint speed in rad/s (reduced mode)
reduced_joint_rangeslist or nilnilPer-joint angle limits [{lower, upper}] × 7 (reduced mode)
tcp_boundarytuple or nilnilCartesian workspace fence {x_min, x_max, y_min, y_max, z_min, z_max} in mm
fence_onbooleanfalseActivate the TCP boundary fence

Actuators

ModuleDescription
BB.Ufactory.Actuator.JointJoint-space position (radians), via ETS + 100Hz loop
BB.Ufactory.Actuator.CartesianCartesian pose (mm + radians), direct command
BB.Ufactory.Actuator.GripperGripper G2 position (0–840 mm)
BB.Ufactory.Actuator.LinearTrackLinear track position (mm), RS485-proxied

Sensors

ModuleDescription
BB.Ufactory.Sensor.ForceTorque6-axis F/T streamed from report socket (Fx/Fy/Fz/Tx/Ty/Tz)
BB.Ufactory.Sensor.CollisionCollision detection with configurable sensitivity (0–5); publishes on error codes 22, 31, 35

Messages

MessagePublished toDescription
BB.Message.Sensor.JointState[:sensor, controller_name]Joint angles + torques, every report frame
BB.Ufactory.Message.CartesianPose[:sensor, controller_name, :tcp_pose]TCP position (mm) + orientation (rad RPY), every report frame
BB.Ufactory.Message.ArmStatus[:sensor, controller_name, :arm_status]Arm state, mode, error/warn codes; published on change
BB.Ufactory.Message.Wrench[:sensor, controller_name, :wrench]F/T reading; present only when F/T sensor is enabled

Protocol

UFactory uses a custom Modbus-TCP variant:

The real-time report socket (port 30003) pushes frames at ~100Hz containing joint angles, Cartesian pose, and joint torques. Force/torque data (ft_filtered) is present only in frames that are 135+ bytes, which requires the F/T sensor to be enabled via cmd_ft_sensor_enable.

Error codes are not included in real-time report frames; they are polled from the command socket (register 0x0F) once per second alongside the heartbeat.

Testing

Three tiers, from fastest to closest-to-production:

# 1. Unit + kinematic-sim tests (no hardware, no Docker) — the default
mix test
# 2. Integration tests against UFACTORY's firmware simulator in Docker.
# Runs the real controller and wire protocol against the real firmware —
# the closest thing to hardware without an arm. Studio UI for visual
# verification at http://127.0.0.1:18333.
mix bb_ufactory.sim start # defaults to xarm6
mix test --include simulator
mix bb_ufactory.sim stop
# The simulator ships firmware for every supported model; CI runs the
# suite against all five. Locally, pick one:
mix bb_ufactory.sim start lite6 # or xarm5 | xarm7 | xarm850
SIM_MODEL=lite6 mix test --include simulator
# 3. Hardware tests against a physical arm (clear the workspace first!)
XARM_HOST=192.168.1.224 mix test --include hardware

The simulator image (danielwang123321/uf-ubuntu-docker) is amd64-only and runs under emulation on Apple Silicon; mix bb_ufactory.sim handles the platform flag, firmware startup, and protocol-level readiness automatically.

Building simulator tests for your own robot application? This library ships BB.Ufactory.SimulatorCase (an ExUnit case template) and BB.Ufactory.Simulator (protocol-level helpers that also work against a physical arm) — see the Testing against the UFACTORY simulator tutorial on HexDocs.

Documentation

Full documentation is available at HexDocs.