The Franka Research 3 (FR3) is a 7-degree-of-freedom collaborative arm from Franka Robotics, built for research and light automation rather than high-speed industrial cycles. It is the successor to the original Panda, and it keeps Panda's defining trait: a link-side torque sensor at every joint, not only at the wrist. That gives the arm native force sensing along the whole kinematic chain, which is the property most robot-learning teams actually care about when they pick an arm to collect data on.
Teams end up recording on an FR3 for two overlapping reasons. First, the hardware genuinely supports contact-rich work — gravity compensation, hand-guiding, and torque-based compliance are first-class, not bolted on. Second, an unusually large fraction of published manipulation research and open robot datasets already target the Panda/FR3 kinematic family, so URDFs, simulation models, and ROS 2 drivers exist and are maintained. If your fleet already runs FR3s, connecting them to a data pipeline is a driver-and-sync problem, covered generically by Bring Your Own Rig; this page is the platform-specific detail underneath that.
Control interfaces that matter for data collection
Franka's research control stack has three layers, and which one you touch determines what your recorded data looks like.
- Franka Control Interface (FCI) is the low-level, direct Ethernet connection between a workstation PC and the Arm/Hand controller. On robots running system software 4.2.0 or newer, FCI mode has to be explicitly activated from Desk, Franka's web-based admin console, before an external program can command the robot.
- libfranka is the official C++ client library for FCI (Apache-2.0 licensed, with Python bindings available separately). It runs a 1 kHz real-time control loop and exposes five command types: joint torque (with optional gravity/friction compensation), joint position, joint velocity, Cartesian pose, and Cartesian velocity. Robot state — joint position, joint velocity, link-side torque, and an estimate of external force — comes back at the same 1 kHz.
- franka_ros2 is Franka Robotics' official ROS 2 integration. It wraps libfranka and exposes it through
ros2_control, with packages for the hardware interface (franka_hardware), message/service definitions (franka_msgs), the gripper (franka_gripper), example controllers, a Gazebo simulation target, and a MoveIt 2 configuration. It ships as two parallel tracks — a 2.x line for ROS 2 Humble and a 3.x line for Jazzy — and the maintainers state plainly that the package is in active development and users should expect breaking changes between minor versions, so pin a tagged release rather than tracking the default branch in anything you deploy for data collection.
A minimal libfranka control loop looks roughly like this — illustrative, not a full working program:
franka::Robot robot("172.16.0.2");
robot.setCollisionBehavior(/* joint + cartesian force/torque thresholds */);
franka::Model model(robot);
robot.control([&model](const franka::RobotState& state,
franka::Duration period) -> franka::Torques {
// state.q, state.dq, state.O_T_EE arrive here at 1 kHz
std::array<double, 7> tau_d = compute_torques(state, model);
return tau_d;
});Teleoperation options
Nothing about the FR3 forces a specific input device — the choice depends on what task you're demonstrating and what the FCI's five command modes give you access to.
- Leader-follower (bilateral) arms. Franka does not sell a matched leader device, so labs pairing an FR3 with a leader arm either build one or use a kinematically distinct third-party leader and retarget joint targets across the FCI's joint-position or joint-velocity interface. This is the bilateral teleoperation pattern; it gives clean joint-space correspondence at the cost of building or buying the leader hardware.
- VR and hand-tracking retargeting. An operator's tracked hand pose maps to a target end-effector pose sent through the Cartesian pose or velocity interface. Cheap to set up and morphology-independent, but retargeting error compounds and, without a force-feedback device, the operator has no haptic sense of contact — which matters more on an arm whose whole appeal is torque sensing.
- Space mouse. A rate-control input mapped to Cartesian velocity commands. Reasonable for coarse repositioning between contact events; imprecise for the fine, force-modulated motion the FR3's torque sensing is meant to capture.
- Hand-guiding / gravity compensation. Because every joint reports torque, the FR3 supports genuine kinesthetic teaching: put it into a zero-torque or compliant mode, physically move the arm through the task, and record the resulting trajectory. This is the one option that is specific to torque-sensed arms rather than a generic teleoperation pattern, and it captures force interaction the other three approaches only approximate. The trade-off is that the operator stands at the robot rather than at a station, which complicates running a synced multi-camera capture rig around them and rules out any latency-sensitive remote setup — see teleoperation for how that constraint plays out more generally.
Which one you pick changes what's in the dataset: leader-follower and hand-guiding both produce joint-space demonstrations with a real physical arm in the loop, while VR retargeting and space-mouse control produce Cartesian targets that a lower-level controller then converts to joint torques — a layer of interpretation between what the operator did and what got recorded.
What a clean dataset looks like on this platform
At minimum, record: joint positions and velocities, link-side joint torques, the estimated external wrench, end-effector pose, gripper state (width and grasp force if you're using the Franka Hand), and every camera stream in use. FCI state updates at 1 kHz, but most imitation-learning pipelines don't train at that rate — a common pattern is to log the full-rate proprioceptive stream and downsample to whatever your camera frame rate supports (commonly 10–30 Hz) at ingestion time, rather than throwing away the high-rate torque signal at capture.
Two platform-specific gotchas matter more here than on a position-controlled arm:
- Load parameters have to be correct before torque data means anything. libfranka's gravity compensation and external-force estimate depend on the mass, center of mass, and inertia of whatever is attached past the flange. If you've mounted a non-Franka gripper or a camera bracket and never set those load parameters, every torque and force reading downstream is systematically wrong — not noisy, wrong — which is a bad property to discover after a week of collection.
- End-effector pose depends on your calibration entry in Desk.
O_T_EEis computed from the flange kinematic model plus whatever end-effector transform you've configured. If a third-party gripper's offset was never entered, or was entered once and the gripper was later swapped, your recorded end-effector pose is consistently offset from the true grasp point — this shows up as a policy that reaches slightly wrong, not as an obvious data corruption.
Because the FCI control loop and your camera capture are almost always separate processes — and often separate machines — time synchronization between the two has to be explicit. Treat the robot's 1 kHz state stream and the camera timestamps as two clocks that need reconciling, not one clock you can assume for free.
Common pitfalls
No real-time kernel, robot won't hold the loop. This is the single most common first-day failure: a control program built against libfranka runs fine on a standard kernel until load increases, then trips the 20-cycle communication timeout. There is no software workaround that substitutes for PREEMPT_RT on the control PC.
Firmware and driver version drift. libfranka pins compatibility to a range of robot system-software versions, and franka_ros2 pins compatibility to a libfranka range in turn. Upgrading one layer without checking the other two is a reliable way to get a robot that refuses to connect, or connects but rejects commands with an unhelpful error.
Collision-behavior thresholds set once and forgotten. setCollisionBehavior defines the joint and Cartesian force/torque thresholds that trigger a reflex stop. Set too loose, and a real collision goes unnoticed; set too tight for a torque-mode task like hand-guided contact-rich manipulation, and the arm reflex-stops mid-demonstration, which both loses the episode and requires a manual re-enable from Desk before you can continue — expensive when it happens repeatedly across a long collection session.
Tracking franka_ros2's default branch in production. The maintainers' own rapid-development warning is not boilerplate. Pin a tagged release that matches your robot's system version and your ROS 2 distro, and re-validate before bumping it mid-collection-campaign.