Skip to main content

franky-sim

A high-fidelity simulation server for the Franka FR3 robot that implements the libfranka network protocol and serves as a drop-in replacement for real hardware.

franky-sim pairs with franky — a Python interface for Franka robots — to give you a full simulation stack with no code changes needed when moving to real hardware.

How it works

franky-sim starts a local TCP/UDP server that speaks the same network protocol as a real Franka robot. Any libfranka-compatible client connects to this server instead of the real robot IP. The server forwards commands to a physics simulator (MuJoCo by default, Genesis optionally) and streams back robot state at 1 kHz.

franky-sim supports all control modes available on the real robot, including joint position, joint velocity, Cartesian position, Cartesian velocity, and gripper control.

Installation

pip install franky-sim

To run the examples below, install with the franky option:

pip install franky-sim[franky]

To use the Genesis physics backend instead of MuJoCo:

pip install franky-sim[genesis]

Quick start

Command-line server

franky-sim              # headless (no window)
franky-sim --render     # with visualisation
franky-sim --simulator genesis  # use Genesis backend

Connect your libfranka/franky client to the IP printed by the program (127.0.0.1 if the port is available).

Embedded server

from franky_sim import SimulationServer
from franky_sim.mujoco_simulator import MujocoSimulator

with MujocoSimulator(enable_visualization=True) as sim:
    robot = sim.add_robot()
    with SimulationServer(sim) as server:
        server.run_async()
        print(f"Server ready at {robot.hostname}")
        # connect your client here ...

Control mode examples

Joint position control

Move the robot through a series of joint-space waypoints.

import franky
from franky_sim import SimulationServer
from franky_sim.mujoco_simulator import MujocoSimulator

with MujocoSimulator(enable_visualization=True) as sim:
    robot_model = sim.add_robot()
    with SimulationServer(sim) as server:
        server.run_async()
        robot = franky.Robot(robot_model.hostname, realtime_config=franky.RealtimeConfig.Ignore)

        target = [-0.3, 0.1, 0.3, -1.4, 0.1, 1.8, 0.7]
        robot.move(franky.JointWaypointMotion([franky.JointWaypoint(target)]))
        print("Joint positions:", list(robot.current_joint_state.position))

Joint velocity control

Command joint velocities for a fixed duration.

import franky
from franky_sim import SimulationServer
from franky_sim.mujoco_simulator import MujocoSimulator

with MujocoSimulator(enable_visualization=True) as sim:
    robot_model = sim.add_robot()
    with SimulationServer(sim) as server:
        server.run_async()
        robot = franky.Robot(robot_model.hostname, realtime_config=franky.RealtimeConfig.Ignore)

        robot.move(
            franky.JointVelocityWaypointMotion([
                franky.JointVelocityWaypoint(
                    [0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                    hold_target_duration=franky.Duration(500),
                )
            ])
        )
        print("Joint positions:", list(robot.current_joint_state.position))

Cartesian position control

Move the end-effector to a target pose in Cartesian space.

import franky
from franky_sim import SimulationServer
from franky_sim.mujoco_simulator import MujocoSimulator

with MujocoSimulator(enable_visualization=True) as sim:
    robot_model = sim.add_robot()
    with SimulationServer(sim) as server:
        server.run_async()
        robot = franky.Robot(robot_model.hostname, realtime_config=franky.RealtimeConfig.Ignore)

        # Move 5 cm in the x direction (relative to current pose)
        robot.move(franky.CartesianMotion(franky.Affine([0.1, 0.0, 0.0]), franky.ReferenceType.Relative))
        print("End-effector pose:", robot.current_cartesian_state.pose.end_effector_pose)

Cartesian velocity control

Command end-effector velocity for a fixed duration.

import franky
from franky_sim import SimulationServer
from franky_sim.mujoco_simulator import MujocoSimulator

with MujocoSimulator(enable_visualization=True) as sim:
    robot_model = sim.add_robot()
    with SimulationServer(sim) as server:
        server.run_async()
        robot = franky.Robot(robot_model.hostname, realtime_config=franky.RealtimeConfig.Ignore)

        # Move at 2 cm/s in the x direction for 500 ms
        robot.move(
            franky.CartesianVelocityWaypointMotion([
                franky.CartesianVelocityWaypoint(
                    franky.Twist([0.1, 0.0, 0.0]),
                    hold_target_duration=franky.Duration(500),
                )
            ])
        )
        print("End-effector pose:", robot.current_cartesian_state.pose.end_effector_pose)

Gripper control

Home, move, and grasp with the simulated gripper.

import franky
from franky_sim import SimulationServer
from franky_sim.mujoco_simulator import MujocoSimulator

with MujocoSimulator(enable_visualization=True) as sim:
    robot_model = sim.add_robot()
    with SimulationServer(sim) as server:
        server.run_async()
        gripper = franky.Gripper(robot_model.hostname)

        # Home the gripper (opens to max width)
        gripper.homing()
        print(f"Width after homing: {gripper.width:.4f} m")

        # Move to a specific width at a given speed
        gripper.move(0.02, 0.05)  # 2 cm, 5 cm/s

        # Grasp at 2 cm with ±2 cm tolerance
        success = gripper.grasp(0.02, 0.02, 10.0, epsilon_inner=0.02, epsilon_outer=0.02)
        print(f"Grasp success: {success}, is_grasped: {gripper.is_grasped}")

More examples are available in the examples/ directory.

Limitations

franky-sim does not enforce safety limits on joint positions, velocities, or torques and generally does not produce control errors. Hence, it is not guaranteed that controllers that work in simulation will also work on real hardware.

Furthermore, franky-sim only supports Robot Server version 10 and Gripper Server version 3. No older versions are supported.

Credits

franky-sim was originally forked from libfranka-sim though it has been substantially altered. Still, many thanks to Baris Yazici for the original work and for making it open source.

License

Apache License 2.0 — see LICENSE for details.

Metadata

Release files for franky-sim 1.0.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for franky-sim 1.0.4
File Size Uploaded Provenance
franky_sim-1.0.4.tar.gz 25.9 MB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for franky-sim 1.0.4
File Interpreter ABI Platform
franky_sim-1.0.4-py3-none-any.whl Python 3 none any Details

Total release size: 45.2 MB

Release files / franky_sim-1.0.4.tar.gz

Download URL franky_sim-1.0.4.tar.gz
Size 25.9 MB
Tags Source
SHA-256 checksum
How to use checksums
5cc9a50f967d8d92c84b4da7bed9509fcebd71aa2d0c0f51177a5bff990f6b17
BLAKE2b-256 checksum
How to use checksums
5c6d85f794fb2afcd3b2d3e2bccd010fd570befc6175c10bcf521be4ed04502b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.

Transparency log

Release files / franky_sim-1.0.4-py3-none-any.whl

Download URL franky_sim-1.0.4-py3-none-any.whl
Size 19.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
5e54f3b69be883e0fa1cf17c42c84e61631cc2f5d70505ed8542749b2f107707
BLAKE2b-256 checksum
How to use checksums
812f8bafc9983753d973e09a72e6f6fdab618734610c8333dbffb4e6cc1ec6a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.

Transparency log

Security for franky-sim 1.0.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for franky_sim-1.0.4.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page