Skip to main content

cu29/
lib.rs

1//! # Copper Runtime & SDK
2//!
3//! Think of Copper as a robotics game engine: define a task graph, compile once,
4//! and get deterministic execution, unified logging, and sub-microsecond
5//! latency from Linux workstations all the way down to bare-metal MPU builds.
6//!
7//! ## Quick start
8//!
9//! ```bash
10//! cargo install cargo-generate
11//! git clone https://github.com/copper-project/copper-rs
12//! cd copper-rs/templates
13//! cargo cunew /path/to/my_robot   # scaffolds a full Copper project
14//! ```
15//!
16//! It will generate a minimal Copper robot project at `/path/to/my_robot`. `cargo build` should
17//! compile it out of the box.
18//!
19//! ## Feature flags
20//!
21//! - `default` = `["std", "signal-handler", "textlogs", "units"]`
22//! - `units`: exposes `cu29::units` (re-export of `cu29-units`)
23//! - `std`: host/runtime support that is also safe to compile for browser targets
24//! - `signal-handler`: desktop Ctrl-C integration for generated `run()` loops
25//! - `reflect`: reflection support for runtime and units types
26//! - `textlogs`: text logging derive support
27//! - `remote-debug`: remote debug transport support
28//! - `sysclock-perf`: use a host/system clock for runtime perf timing while keeping robot time for `tov` and `rate_target_hz`
29//! - `high-precision-limiter`: std-only hybrid sleep/spin loop limiter for tighter `rate_target_hz` cadence
30//! - `async-cl-io`: offload CopperList serialization/logging to a dedicated std thread
31//! - `parallel-rt`: prepare the runtime for a future multi-threaded deterministic executor
32//!
33//! ## Concepts behind Copper
34//!
35//! Check out the [Copper Wiki](https://github.com/copper-project/copper-rs/wiki) to understand the
36//! deployments concepts, task lifecycle, available components, etc ...
37//!
38//! ## More examples to get you started
39//!
40//! - `examples/cu_caterpillar`: a minimal running example passing around booleans.
41//! - `examples/cu_rp_balancebot`: a more complete example try Copper without hardware via
42//!   `cargo install cu-rp-balancebot` + `balancebot-sim` (Bevy + Avian3d).
43//!
44//! ## Key traits and structs to check out
45//!
46//! - `cu29_runtime::app::CuApp`: the main trait the copper runtime will expose to run your application. (when run() etc .. is coming from)
47//! - `cu29_runtime::config::CuConfig`: the configuration of your runtime
48//! - `cu29_runtime::cutask::CuTask`: the core trait and helpers to implement your own tasks.
49//! - `cu29_runtime::cubridge::CuBridge`: the trait to implement bridges to hardware or other software.
50//! - `cu29_runtime::curuntime::CuRuntime`: the runtime that manages task execution.
51//! - `cu29_runtime::simulation`: This will explain how to hook up your tasks to a simulation environment.
52//!
53//! Need help or want to show what you're building? Join
54//! [Discord](https://discord.gg/VkCG7Sb9Kw) and hop into the #general channel.
55//!
56
57#![cfg_attr(not(feature = "std"), no_std)]
58#[cfg(all(feature = "parallel-rt", not(feature = "std")))]
59compile_error!("feature `parallel-rt` requires `std`");
60#[cfg(not(feature = "std"))]
61extern crate alloc;
62
63pub use cu29_derive::{bundle_resources, resources};
64pub use cu29_runtime::app;
65pub use cu29_runtime::config;
66pub use cu29_runtime::context;
67pub use cu29_runtime::copperlist;
68#[cfg(feature = "std")]
69pub use cu29_runtime::cuasynctask;
70pub use cu29_runtime::cubridge;
71pub use cu29_runtime::curuntime;
72pub use cu29_runtime::cutask;
73#[cfg(feature = "std")]
74pub use cu29_runtime::debug;
75#[cfg(feature = "std")]
76pub use cu29_runtime::distributed_replay;
77pub use cu29_runtime::input_msg;
78pub use cu29_runtime::logcodec;
79pub use cu29_runtime::monitoring;
80pub use cu29_runtime::output_msg;
81#[cfg(all(feature = "std", feature = "parallel-rt"))]
82pub use cu29_runtime::parallel_queue;
83#[cfg(all(feature = "std", feature = "parallel-rt"))]
84pub use cu29_runtime::parallel_rt;
85pub use cu29_runtime::payload;
86pub use cu29_runtime::reflect;
87pub use cu29_runtime::reflect as bevy_reflect;
88#[cfg(feature = "remote-debug")]
89pub use cu29_runtime::remote_debug;
90#[cfg(feature = "std")]
91pub use cu29_runtime::replay;
92pub use cu29_runtime::resource;
93pub use cu29_runtime::rx_channels;
94#[cfg(feature = "std")]
95pub use cu29_runtime::simulation;
96pub use cu29_runtime::tx_channels;
97
98#[cfg(feature = "rtsan")]
99pub mod rtsan {
100    pub use rtsan_standalone::*;
101}
102
103#[cfg(not(feature = "rtsan"))]
104pub mod rtsan {
105    use core::ffi::CStr;
106
107    #[derive(Default)]
108    pub struct ScopedSanitizeRealtime;
109
110    #[derive(Default)]
111    pub struct ScopedDisabler;
112
113    #[inline]
114    pub fn realtime_enter() {}
115
116    #[inline]
117    pub fn realtime_exit() {}
118
119    #[inline]
120    pub fn disable() {}
121
122    #[inline]
123    pub fn enable() {}
124
125    #[inline]
126    pub fn ensure_initialized() {}
127
128    #[allow(unused_variables)]
129    pub fn notify_blocking_call(_function_name: &'static CStr) {}
130}
131
132pub use bincode;
133pub use cu29_clock as clock;
134#[cfg(feature = "units")]
135pub use cu29_units as units;
136#[cfg(feature = "defmt")]
137pub mod defmt {
138    pub use defmt::{debug, error, info, warn};
139}
140#[cfg(feature = "std")]
141pub use cu29_runtime::config::read_configuration;
142#[cfg(feature = "std")]
143pub use cu29_runtime::config::read_multi_configuration;
144pub use cu29_traits::*;
145
146#[cfg(feature = "std")]
147pub use rayon;
148
149// defmt shims re-exported for proc-macro call sites
150#[cfg(all(feature = "defmt", not(feature = "std")))]
151#[macro_export]
152macro_rules! defmt_debug {
153    ($fmt:literal $(, $arg:expr)* $(,)?) => {
154        $crate::defmt::debug!($fmt $(, $arg)*);
155    }
156}
157#[cfg(not(all(feature = "defmt", not(feature = "std"))))]
158#[macro_export]
159macro_rules! defmt_debug {
160    ($($tt:tt)*) => {{}};
161}
162
163#[cfg(all(feature = "defmt", not(feature = "std")))]
164#[macro_export]
165macro_rules! defmt_info {
166    ($fmt:literal $(, $arg:expr)* $(,)?) => {
167        $crate::defmt::info!($fmt $(, $arg)*);
168    }
169}
170#[cfg(not(all(feature = "defmt", not(feature = "std"))))]
171#[macro_export]
172macro_rules! defmt_info {
173    ($($tt:tt)*) => {{}};
174}
175
176#[cfg(all(feature = "defmt", not(feature = "std")))]
177#[macro_export]
178macro_rules! defmt_warn {
179    ($fmt:literal $(, $arg:expr)* $(,)?) => {
180        $crate::defmt::warn!($fmt $(, $arg)*);
181    }
182}
183#[cfg(not(all(feature = "defmt", not(feature = "std"))))]
184#[macro_export]
185macro_rules! defmt_warn {
186    ($($tt:tt)*) => {{}};
187}
188
189#[cfg(all(feature = "defmt", not(feature = "std")))]
190#[macro_export]
191macro_rules! defmt_error {
192    ($fmt:literal $(, $arg:expr)* $(,)?) => {
193        $crate::defmt::error!($fmt $(, $arg)*);
194    }
195}
196#[cfg(not(all(feature = "defmt", not(feature = "std"))))]
197#[macro_export]
198macro_rules! defmt_error {
199    ($($tt:tt)*) => {{}};
200}
201
202pub mod prelude {
203    pub use crate::bevy_reflect;
204    #[cfg(feature = "units")]
205    pub use crate::units;
206    pub use crate::{defmt_debug, defmt_error, defmt_info, defmt_warn};
207    #[cfg(feature = "signal-handler")]
208    pub use ctrlc;
209    pub use cu29_clock::*;
210    pub use cu29_derive::*; // includes resources! proc macro
211    pub use cu29_log::*;
212    pub use cu29_log::{
213        __cu29_defmt_debug, __cu29_defmt_error, __cu29_defmt_info, __cu29_defmt_warn,
214    };
215    pub use cu29_log_derive::*;
216    pub use cu29_log_runtime::*;
217    pub use cu29_runtime::app::*;
218    pub use cu29_runtime::config::*;
219    pub use cu29_runtime::context::*;
220    pub use cu29_runtime::copperlist::*;
221    pub use cu29_runtime::cubridge::*;
222    pub use cu29_runtime::curuntime::*;
223    pub use cu29_runtime::cutask::*;
224    #[cfg(feature = "std")]
225    pub use cu29_runtime::debug::*;
226    pub use cu29_runtime::input_msg;
227    pub use cu29_runtime::logcodec::*;
228    pub use cu29_runtime::monitoring::*;
229    pub use cu29_runtime::output_msg;
230    pub use cu29_runtime::payload::*;
231    #[cfg(feature = "reflect")]
232    pub use cu29_runtime::reflect::serde as reflect_serde;
233    #[cfg(feature = "reflect")]
234    pub use cu29_runtime::reflect::serde::{
235        ReflectSerializer, SerializationData, TypedReflectSerializer,
236    };
237    pub use cu29_runtime::reflect::{
238        GetTypeRegistration, Reflect, ReflectTaskIntrospection, ReflectTypePath, TypeInfo,
239        TypePath, TypeRegistry, dump_type_registry_schema,
240    };
241    #[cfg(feature = "remote-debug")]
242    pub use cu29_runtime::remote_debug::*;
243    pub use cu29_runtime::resource::*;
244    pub use cu29_runtime::rx_channels;
245    #[cfg(feature = "std")]
246    pub use cu29_runtime::simulation::*;
247    pub use cu29_runtime::tx_channels;
248    pub use cu29_runtime::*;
249    pub use cu29_traits::*;
250    pub use cu29_unifiedlog::*;
251    pub use cu29_value::Value;
252    pub use cu29_value::to_value;
253    #[cfg(feature = "std")]
254    pub use pool::*;
255    pub use serde::Serialize;
256}