Copper has been tested on:
Technical Overview
Copper is a deterministic and data-oriented Robot SDK with these key components:
-
Task Graph: Configures the system's topology, specifies inter-task communication paths, and sets types for nodes and messages. The Task Graph is generated in RON,
-
Runtime Generator: Creates an execution plan based on the Task Graph's metadata. It preallocates a "Copper List" to maximize sequential memory access during execution.
-
Zero-Copy Data Logging: Records all messages between tasks without copying data, ensuring efficient logging and perfect determinism.
-
Fast Structured Logging: Interns and indexes logging strings at compile time, avoiding runtime string construction and ensuring high-speed textual logging.
Blazing Fast
Our latency numbers are expressed in nanoseconds (ns) on commodity hardware.
You don't have a real robot yet? Try it in our minimalistic sim environment!
Here is a Copper-based robot in action in a Bevy simulation environment!
The realistic sim is created using Bevy (A Rust Game Engine)
and Avian3d (Physics Engine in Rust).
On your mac or linux machine (x86-64 or Arm) just run ...
... to try it locally.
The source code for this demo is available in the examples/cu_rp_balancebot directory.
Features
- Task interface and Lifecycle: Traits you can use to implement new algorithms, sensors, and actuators.
- Runtime generation: Generates a scheduling at compile time for your robot.
- Log reader: You can export the logs generated by Copper to any format supported by Rust Serde.
- Structured log reader: Debug logs are indexed and string interned at compile time for maximum efficiency.
- Components: We have a growing number of drivers, algorithms and standard interfaces. If you have implemented a new component, ping us and we will add it to the list below!
- log replay / resim: You can deterministically replay/resim a log. You will get the exact same result as a real log on the robot or from the sim.
- Simulation: We have a simple simulation environment to test your robot. Test your robot before the hardware is built and try out your robot the first time without risking a real crash.
Growing list of readily available Components
Kickstarting a Copper project for the impatient
You can generate a project from one of Copper's templates. The generator will ask you the name for your new project interactively:
Check out copper-templates for more info.
What does a Copper application look like?
Here is a simple example of a Task Graph in RON:
(
tasks: [
(
id: "src", // this is a friendly name
type: "FlippingSource", // This is a Rust struct name for this task see main below
),
(
id: "gpio", // another task, another name
type: "cu_rp_gpio::RPGpio", // This is the Rust struct name from another crate
config: { // You can attach config elements to your task
"pin": 4,
},
),
],
cnx: [
// Here we simply connect the tasks telling to the framework what type of messages we want to use.
(src: "src", dst: "gpio", msg: "cu_rp_gpio::RPGpioMsg"),
],
Then, on your main.rs:
// Import the prelude to get all the macros and traits you need.
use *;
// Your application will be a struct that will hold the runtime, loggers etc.
// This proc macro is where all the runtime generation happens. If you are curious about what code is generated by this macro
// you can activate the feature macro_debug and it will display it at compile time.
// this is the ron config we just created.
// Here we define our own Copper Task
// It will be a source flipping a boolean
// We implement the CuSrcTask trait for our task as it is a source / driver (with no internal input from Copper itself).
But this is a very minimal example for a task; please see lifecycle for a more complete explanation of a task lifecycle.
Modular Configuration
Copper supports modular configuration through file includes and parameter substitution, allowing you to:
- Split large configurations into manageable, reusable chunks
- Create configuration variations without duplicating the entire RON file
- Parameterize configurations for different deployment environments
Including Configuration Files
You can include other RON configuration files using the includes section:
(
tasks: [
// Your main configuration tasks...
],
cnx: [
// Your main configuration connections...
],
includes: [
(
path: "path/to/included_config.ron",
params: {}, // Optional parameter substitutions
),
],
)
Parameter Substitution
You can parameterize your included configurations using template variables:
// included_config.ron
(
tasks: [
(
id: "task_{{instance_id}}", // Will be replaced with the provided instance_id
type: "tasks::Task{{instance_id}}",
config: {
"param_value": {{param_value}}, // Will be replaced with the provided param_value
},
),
],
cnx: [],
)
// main_config.ron
(
tasks: [],
cnx: [],
includes: [
(
path: "included_config.ron",
params: {
"instance_id": "42", // Replaces {{instance_id}} with "42"
"param_value": 100, // Replaces {{param_value}} with 100
},
),
],
)
Use Cases
- Sharing common components across multiple robot configurations
- Creating environment-specific configurations (development, testing, production)
- Reusing task templates with different parameters (e.g., multiple motors with different pins)
For more details on modular configuration, see the Modular Configuration documentation.
Deployment of the application
Check out the deployment page for more information.
How is Copper better or different from the ROS (Robot Operating System)?
As explained above, Copper is a "user-friendly runtime engine" written in Rust which manages task execution, data flow, logging, and more.
In contrast, the ROS is an open-source set of software libraries and tools primarily written in C++ and Python.
Let's talk about some of the benefits and differences between the two.
🚀 Performance
In the example directory, we have 2 equivalent applications. One written in C++ for ROS and a port in Rust with Copper.
You can try them out by either just logging onto a desktop, or with GPIOs on a RPi. You should see a couple order of magnitude difference in performance.
Copper has been designed for performance first. Not unlike a game engine, we use a data-oriented approach to minimize latency and maximize throughput.
Safety
As Copper is written in Rust, it is memory safe and thread safe by design. It is also designed to be easy to use and avoid common pitfalls.
As we progress on this project we plan on implementing more and more early warnings to help you avoid "the death by a thousand cuts" that can happen in a complex system.
Release Notes
You can find the full release notes here.
Roadmap
[!NOTE] We are looking for contributors to help us build the best robotics framework possible. If you are interested, please join us on Discord or open an issue.
Here are some of the features we just release and some we plan to implement next, if you are interested in contributing on any of those, please let us know!:
- Buffer Pools: Implement a large buffer (Host or Device/GPU) pools for 0 copy large inter-task transfers.
- Missions: Implement a way to have multiple DAGS in the RON configuration file and have a centralized way to switch from one to another. This is useful for running the stack for a specific mission: for example Data acquisition missiom, Full autonomy mission, Charging, etc.
- Modular Configuration: As robots built with Copper gain complexity, users will need to build "variations" of their robots without duplicating their entire RON file.
- ROS2/DDS interfacing: Build a pair of sink and source to connect to existing ROS2 systems, helping users migrate their stack bit by bit.
- Log Compression & Selection: Implement a pluggable compression system for logs and its resim counterpart. For example to encode video from images. Selection is about NOT logging something if it is not needed.
- Microcontroller and RTOS support: Modify all necessary Copper code packages to remove dependencies on the standard library (std) to support "no_std" (#![no_std]) to support running the code on bare-metal on microcontrollers. This will allow a seamless environment for high level calls on a standard kernel (ML inference etc...) and low level tasks on MCUs (control, HW interfacing...).
- Parallel Copper Lists: allow Copper lists to be executed in a staggered and parallel way to improve throughput.
- Extensible scheduling: Enable a way to give hints to Copper to better schedule workloads at compile time.
- Swarm support: Implement Zenoh to allow a swarm of robots powered by Copper to cooperate.
- MCAP support: Allow the interfacing of Foxglove and ROS ecosystems at the logging level.
