{"id":23902412,"url":"https://github.com/copper-project/copper-rs","last_synced_at":"2025-05-14T04:07:42.989Z","repository":{"id":250485483,"uuid":"290790298","full_name":"copper-project/copper-rs","owner":"copper-project","description":"Purpose-built, Rust-native software engine for robotics","archived":false,"fork":false,"pushed_at":"2025-05-07T17:47:49.000Z","size":100440,"stargazers_count":750,"open_issues_count":21,"forks_count":44,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-07T18:45:37.455Z","etag":null,"topics":["robotics","ros","rust"],"latest_commit_sha":null,"homepage":"https://www.copper-robotics.com","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/copper-project.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"support/README.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-08-27T13:59:54.000Z","updated_at":"2025-05-05T21:49:25.000Z","dependencies_parsed_at":"2024-08-28T21:30:57.456Z","dependency_job_id":"37222c3c-c5e8-4c16-a179-46e05840b96e","html_url":"https://github.com/copper-project/copper-rs","commit_stats":null,"previous_names":["copper-project/copper-rs"],"tags_count":192,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/copper-project%2Fcopper-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/copper-project%2Fcopper-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/copper-project%2Fcopper-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/copper-project%2Fcopper-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/copper-project","download_url":"https://codeload.github.com/copper-project/copper-rs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254069220,"owners_count":22009513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["robotics","ros","rust"],"created_at":"2025-01-04T22:29:31.953Z","updated_at":"2025-05-14T04:07:42.942Z","avatar_url":"https://github.com/copper-project.png","language":"Rust","funding_links":[],"categories":["Library, Framework, SDK","Rust","Middleware"],"sub_categories":["Robots","SLAM"],"readme":"\u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/doc/static/cu29.png?raw=true\" alt=\"logo\"/\u003e\n\n#\n\n# Copper\n\n[![copper](https://github.com/gbin/copper-project/actions/workflows/general.yml/badge.svg)](https://github.com/gbin/copper-project/actions/workflows/general.yml)\n![GitHub last commit](https://img.shields.io/github/last-commit/copper-project/copper-rs)\n![](https://img.shields.io/badge/Rust-1.80+-orange.svg)\n[![dependency status](https://deps.rs/repo/github/copper-project/copper-rs/status.svg)](https://deps.rs/repo/github/copper-project/copper-rs)\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Discord](https://img.shields.io/discord/1305916875741597826?logo=discord)](https://discord.gg/VkCG7Sb9Kw)\n[\u003cimg src=\"https://devin.ai/assets/askdeepwiki.png\" alt=\"Ask http://DeepWiki.com\" height=\"20\"/\u003e](https://deepwiki.com/copper-project/copper-rs)\n\nCopper is a user-friendly runtime engine for creating fast and reliable robots. Copper is to robots what a\ngame engine is to games.\n\n* **Easy**: Copper offers a high-level configuration system and a natural Rust-first API.\n\n* **Fast**: Copper uses Rust's zero-cost abstractions and a data-oriented approach to achieve sub-microsecond latency on\n  commodity hardware, avoiding heap allocation during execution.\n\n* **Reliable**: Copper leverages Rust's ownership, type system, and concurrency model to minimize bugs and ensure thread\n  safety.\n\n* **Product Oriented**: Copper aims to avoid late-stage infra integration issues by generating a very predictable\n  runtime.\n\nCopper has been tested on: \n* **Linux** (x86_64, armv7, aarch64 \u0026 riskv64)\n* **MacOS** (arm64)\n* **Windows** (x86_64)\n\n### Technical Overview\n\nCopper is a data-oriented Robot SDK with these key components:\n\n* **Task Graph**:\n  \u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/doc/graph.png?raw=true\" alt=\"graph\"/\u003e\n  Configures the system's topology, specifies inter-task communication paths, and sets types for nodes and messages. The Task Graph is generated in [RON](https://github.com/ron-rs/ron), \n\n* **Runtime Generator**: Creates an execution plan based on the Task Graph's metadata. It preallocates a\n  \"Copper List\" to maximize sequential memory access during execution.\n\n* **Zero-Copy Data Logging**: Records all messages between tasks without copying data, ensuring efficient logging.\n\n* **Fast Structured Logging**: Interns and indexes logging strings at compile time, avoiding runtime string construction\n  and ensuring high-speed textual logging.\n\n### You don't have a real robot yet? Try it in our minimalistic sim environment!\n\n[![Copper in virtual action](https://img.youtube.com/vi/kC6sGRZUxLE/maxresdefault.jpg)](https://youtu.be/kC6sGRZUxLE)\n\nHere is a Copper-based robot in action in a Bevy simulation environment!  \nThe realistic sim is created using [Bevy](https://crates.io/crates/bevy) (A Rust Game Engine) and [Avian3d](https://crates.io/crates/avian3d) (Physics Engine in Rust).\n\nOn your mac or linux machine (x86-64 or Arm) just run ...\n\n```bash\n$ cargo install cu-rp-balancebot\n$ balancebot-sim \n```\n\n... to try it locally.\n\nThe source code for this demo is available in the [examples/cu_rp_balancebot](examples/cu_rp_balancebot) directory.\n\n### Implemented Features So Far\n\n1. **Task interface and Lifecycle**: These are stable traits you can use to implement new algorithms,\n   sensors, and actuators.\n2. **Runtime generation**: The current implementation works for up to mid-size robot (~a couple dozen of tasks).\n3. **Log reader**: You can reread the logs generated by Copper from your robot, sim or resim.\n4. **Structured log reader**: Debug logs are indexed and string interned at compile time for maximum efficiency.\n5. **Components**: We have a growing number of drivers, algorithms and standard interfaces. If you have implemented a\n   new\n   component, ping us and we will add it to the list!\n6. **log replay / resim**: You can deterministically replay/resim a log. If all you tasks are deterministic, you will\n   get the exact same result as a real log on the robot or from the sim.\n7. **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.\n\n### Components\n\n| **Category** | **Type**        |                                                                                                                                                                           | **Description**                                                                                               | **Crate Name**                        |\n|--------------|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|---------------------------------------|\n| Sensors      | Lidar           | \u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/components/sources/cu_vlp16/doc/vlp16.jpg?raw=true\" alt=\"vlp16\"/\u003e             | [Velodyne/Ouster VLP16](components/sources/cu_vlp16)                                                          | cu-vlp16                              |\n|              | Lidar           | \u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/components/sources/cu_hesai/doc/XT32-16.png?raw=true\" alt=\"xt32\"/\u003e            | [Hesai/XT32](components/sources/cu_hesai)                                                                     | cu-hesai                              |\n|              | IMU             | \u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/components/sources/cu_wt901/doc/wt901.jpg?raw=true\" alt=\"wt901\"/\u003e             | [WitMotion WT901](components/sources/cu_wt901)                                                                | cu-wt901                              |\n|              | ADC/Position    | \u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/components/sources/cu_ads7883/doc/ads7883-scale.jpg?raw=true\" alt=\"ads7883\"/\u003e | [ADS 7883 3MPSPS SPI ADC](components/sources/cu_ads7883)                                                      | cu-ads7883                            |\n|              | Encoder         | \u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/components/sources/cu_rp_encoder/doc/encoder.jpg?raw=true\" alt=\"ads7883\"/\u003e    | [Generic Directional Wheel encoder](components/sources/cu_rp_encoder)                                         | cu-rp-encoder                         |\n| Actuators    | GPIO            | \u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/components/sinks/cu_rp_gpio/doc/rp.jpg?raw=true\" alt=\"gpio\"/\u003e                 | [Raspberry Pi](components/sinks/cu_rp_gpio)                                                                   | cu-rp-gpio                            |\n|              | Servo           | \u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/components/sinks/cu_lewansoul/doc/lewansoul.jpg?raw=true\" alt=\"lewansoul\"/\u003e   | [Lewansoul Servo Bus (LX-16A, etc.)](components/sinks/cu_lewansoul)                                           | cu-lewansoul                          |\n|              | DC Motor Driver | \u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/components/sinks/cu_rp_sn754410/doc/sn754410.jpeg?raw=true\" alt=\"sn754410\"/\u003e  | [Half-H Driver for CD Motors](components/sinks/cu_rp_sn754410)                                                | cu-rp-sn754410                        |\n| Monitors     | TUI Monitor     | \u003cimg align=\"right\" width=\"100\" src=\"https://github.com/copper-project/copper-rs/blob/master/components/monitors/cu_consolemon/doc/tasks.png?raw=true\" alt=\"monitor\"/\u003e     | [Console based monitor](components/monitors/cu_consolemon)                                                    | cu-consolemon                         |\n| Algorithms   | PID Controller  |                                                                                                                                                                           | [PID Controller](components/tasks/cu_pid)                                                                     | cu-pid                                |\n| Middleware   | Shared Mem IPC  | \u003cimg align=\"right\" width=\"100\" src=\"https://user-images.githubusercontent.com/8661268/114321508-64a6b000-9b1b-11eb-95ef-b84c91387cff.png\"/\u003e                               | [Iceoryx2 source](components/sources/cu_iceoryx2_src) \u003cBR\u003e [Iceoryx2 sink](components/sinks/cu_iceoryx2_sink) | cu-iceoryx2-src \u003cBR\u003e cu-iceoryx2-sink |\n\n### Kickstarting a copper project for the impatient\n\nYou can generate a project from one of Copper's templates.\nThe generator will ask you the name for your new project interactively:\n\n```bash\ncargo install cargo-generate\ngit clone https://github.com/copper-project/copper-rs\ncd copper-rs/templates\ncargo cunew [path_where_you_want_your_project_created]\n    🤷   Project Name:\n```\n\nCheck out [copper-templates](templates/README.md) for more info.\n\n### What does a Copper application look like?\n\nHere is a simple example of a Task Graph in RON:\n\n```RON\n(\n    tasks: [\n        (\n            id: \"src\",                   // this is a friendly name\n            type: \"FlippingSource\",      // This is a Rust struct name for this task see main below\n        ),\n        (\n            id: \"gpio\",                  // another task, another name\n            type: \"cu_rp_gpio::RPGpio\",  // This is the Rust struct name from another crate\n            config: {                    // You can attach config elements to your task\n                \"pin\": 4,\n            },\n        ),\n    ],\n     cnx: [\n        // Here we simply connect the tasks telling to the framework what type of messages we want to use. \n        (src: \"src\",  dst: \"gpio\",   msg: \"cu_rp_gpio::RPGpioMsg\"),\n    ],    \n```\n\nThen, on your main.rs:\n\n```rust,ignore\n\n// Import the prelude to get all the macros and traits you need.\nuse cu29::prelude::*;\n\n// Your application will be a struct that will hold the runtime, loggers etc.\n// This proc macro is where all the runtime generation happens. If you are curious about what code is generated by this macro\n// you can activate the feature macro_debug and it will display it at compile time.\n#[copper_runtime(config = \"copperconfig.ron\")]  // this is the ron config we just created.\nstruct MyApplication {}\n\n// Here we define our own Copper Task\n// It will be a source flipping a boolean\npub struct FlippingSource {\n    state: bool,\n}\n\n// We implement the CuSrcTask trait for our task as it is a source / driver (with no internal input from Copper itself).\nimpl\u003c'cl\u003e CuSrcTask\u003c'cl\u003e for FlippingSource {\n    type Output = output_msg!('cl, RPGpioPayload);\n\n    // You need to provide at least \"new\" out of the lifecycle methods.\n    // But you have other hooks in to the Lifecycle you can leverage to maximize your opportunity \n    // to not use resources outside of the critical execution path: for example start, stop, \n    // pre_process, post_process etc...\n    fn new(config: Option\u003c\u0026copper::config::ComponentConfig\u003e) -\u003e CuResult\u003cSelf\u003e\n    where\n        Self: Sized,\n    {\n        // the config is passed from the RON config file as a Map.\n        Ok(Self { state: true })\n    }\n    \n    // Process is called by the runtime at each cycle. It will give:\n    // 1. the reference to a monotonic clock\n    // 2. a mutable reference to the output message (so no need to allocate of copy anything)\n    // 3. a CuResult to handle errors\n    fn process(\u0026mut self, clock: \u0026RobotClock, output: Self::Output) -\u003e CuResult\u003c()\u003e {\n        self.state = !self.state;   // Flip our internal state and send the message in our output.\n        output.set_payload(RPGpioPayload {\n            on: self.state,\n            creation: Some(clock.now()).into(),\n            actuation: Some(clock.now()).into(),\n        });\n        Ok(())\n    }\n}\n\n\nfn main() {\n\n    // Copper uses a special log format called \"unified logger\" that is optimized for writing. It stores the messages between tasks \n    // but also the structured logs and telemetry.\n    // A log reader can be generated at the same time as the application to convert this format for post processing.\n  \n    let logger_path = \"/tmp/mylogfile.copper\";\n    \n    // This basic setup is a shortcut to get you running. If needed you can check out the content of it and customize it. \n    let copper_ctx =\n        basic_copper_setup(\u0026PathBuf::from(logger_path), true).expect(\"Failed to setup logger.\");\n        \n    // This is the struct logging implementation tailored for Copper.\n    // It will store the string away from the application in an index format at compile time.\n    // and will store the parameter as an actual field.\n    // You can even name those: debug!(\"This string will not be constructed at runtime at all: my_parameter: {} \u003c- but this will be logged as 1 byte.\", my_parameter = 42);  \n    debug!(\"Logger created at {}.\", logger_path); \n    \n    // A high precision monotonic clock is provided. It can be mocked for testing. \n    // Cloning the clock is cheap and gives you the exact same clock.\n    let clock = copper_ctx.clock;  \n    \n    debug!(\"Creating application... \");\n    let mut application =\n        MyApplication::new(clock.clone(), copper_ctx.unified_logger.clone())\n            .expect(\"Failed to create runtime.\");\n    debug!(\"Running... starting clock: {}.\", clock.now());  // The clock will be displayed with units etc. \n    application.run().expect(\"Failed to run application.\");\n    debug!(\"End of program: {}.\", clock.now());\n}\n\n```\n\nBut this is a very minimal example for a task; please see [lifecycle](doc/lifecycle.md) for a more complete explanation\nof a task lifecycle.\n\n## Deployment of the application\n\nCheck out the [deployment](doc/deploy.md) page for more information.\n\n## How is Copper better or different from the ROS (Robot Operating System)?\n\nAs explained above, Copper is a \"user-friendly runtime engine\" written in Rust which manages task execution, data flow, logging, and more.\n\nIn contrast, the [ROS](https://github.com/ros) is an open-source set of software libraries and tools primarily written in C++ and Python. \n\nLet's talk about some of the benefits and differences between the two.\n\n### Performance\n\nIn the example directory, we have 2 equivalent applications. One written in C++ for ROS and a port in Rust with Copper.\n\n```bash\nexamples/cu_caterpillar\nexamples/ros_caterpillar\n```\n\nYou can try them out by either just logging onto a desktop, or with GPIOs on a RPi.\nYou should see a couple order of magnitude difference in performance.\n\nCopper has been designed for performance first. Not unlike a game engine,\n we use a data-oriented approach to minimize latency\n and maximize throughput.\n\n### Safety\n\nAs Copper is written in Rust, it is memory safe and thread safe by design. It is also designed to be easy to use and\n avoid common pitfalls.\n\nAs we progress on this project we plan on implementing more and more early warnings to help you avoid \"the death by a\nthousand cuts\" that can happen in a complex system.\n\n### Release Notes\n\nYou can find the release notes [here](https://github.com/copper-project/copper-rs/wiki/Copper-Release-Log).\n\n### Roadmap\n\n\u003e [!NOTE]\n\u003e We are looking for contributors to help us build the best robotics framework possible. If you are interested, please\n\u003e join us on [Discord](https://discord.gg/VkCG7Sb9Kw) or open an issue.\n\nHere are some of the features we plan to implement next, if you are interested in contributing\non any of those, please let us know!:\n\n- [x] **Buffer Pools**: Implement a large buffer (Host or Device/GPU) pools for 0 copy large inter-task transfers.\n- [ ] **Log Compression \u0026 Selection**: Implement a pluggable compression system for logs and its resim counterpart.\n  For example to encode video from images. Selection is about NOT logging something if it is not needed.\n- [ ] **Modes**: Implement a way to have multiple DAGS in the RON configuration file and have a centralized way to\n  switch from one to another. This is useful for running the stack in predeterministic modes: for example Data acquisition,\n  Full autonomy, Charging, etc.\n- [ ] **Microcontroller and RTOS support**: Modify all necessary Copper code packages to remove dependencies on the standard library (std) to support \"no_std\" (#![no_std])\n  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...)\n  and low level tasks on MCUs (control, HW interfacing...).\n- [ ] **Parallel Copper Lists**: allow Copper lists to be executed in a staggered and parallel way to improve\n  throughput.\n- [ ] **ROS2/DDS interfacing**: Build a pair of sink and source to connect to existing [ROS2](https://github.com/ros2) systems, helping users\n  migrate their stack bit by bit.\n- [ ] **Modular Configuration**: As robots built with Copper gain complexity, users will need to build \"variations\" of\n  their robots without duplicating their entire RON file.\n- [ ] **Extensible scheduling**: Enable a way to give hints to Copper to better schedule workloads at compile time.\n- [ ] **Swarm support**: Implement Zenoh to allow a swarm of robots powered by Copper to cooperate.\n- [ ] **MCAP support**: Allow the interfacing of Foxglove and [ROS](https://github.com/ros) ecosystems at the logging level.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcopper-project%2Fcopper-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcopper-project%2Fcopper-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcopper-project%2Fcopper-rs/lists"}