-
Notifications
You must be signed in to change notification settings - Fork 28
Copper Release Log
-
Deterministic Log Replay: Copper can now replay a log through your code in a deterministic fashion ie. if your tasks are deterministic, it will always output the same output from the same input! See the balancebot-resim for example.
-
Aligner Task #114: Added an aligner task that synchronizes multiple inputs by aligning matching time windows, facilitating coordinated data processing. This is particularly useful for sensor fusion.
-
Breaking Change: Lifecycle Trait Removal #115: Removed the lifecycle trait to simplify task implementation and decouple passed types, streamlining the codebase. To build a minimum task a user needed to implement one method from the CuTaskLifecycle trait (new) and at least the process method from they flavor of tasks. This was forcing the implementation of 2 mandatory traits which is not necessary or useful for the user. Now we moved all the lifecycle methods in the tasks trait to only have to implement 2 traits (the task and Freezable, the serialization of its state)
-
Named Output Mapping on CopperLists #121: Implemented mapping of Copperlist indices to named outputs from tasks, allowing users to access task outputs symbolically without relying on execution order.
-
CuTimeRange Introduction #106: Introduced
CuTimeRange
to represent messages containing multiple Time of Validity (TOV) instances, such as sequences of images or IMU measurements. -
Windows Compatibility #110: Enhanced compatibility by adding a mock for
cu_ads7883
, enabling compilation on Windows platforms. -
Dependency Updates #104: Performed a general dependency bump post-release to incorporate the latest improvements and fixes.
-
BalanceBot Simulation Stability #118: Resolved a core dump issue on exit for
balancebot-sim
by enforcing specific graphics backends, ensuring clean termination. -
CuCompactStr Serialization #119: Fixed serialization and deserialization issues with
CuCompactStr
to ensure correct data handling. -
Project Generation Fix #120: Addressed issues in project generation by adding
crate::
forcumsgs
generation, ensuring correct module resolution. -
Unused Code Cleanup #121: Removed unused imports and methods to maintain code cleanliness and reduce potential maintenance overhead.
-
Test Stability #107: Ignored hardware-dependent tests and added
test --workspace
to CI/CD to enhance test reliability across different environments.
- Iceoryx2 Support #87: Introduced Iceoryx2 support. Iceoryx2 is the successor to Iceoryx in pure Rust. The Copper support included a source component to receive messages, a sink component to send messages.
- Hesai XT32 Support #101: Added the preliminary support for the Hesai XT32. If you have the actual HW handy, feel free to provide us the feedback!
- First standard Lidar Message Design #99: For now in SOA out or the lidar sensors it allows SIMD optimizations for the first operations that are usually a frame transform.
-
Variable-Length SoAs #100: Improved
SoA
(Structure of Arrays) to support variable lengths on top of their fixed size in the Copper List. - CI Improvements #98: Integrated clippy warnings into CI, thanks to makeecat
-
BalanceBot Simulation Reset #86: Improved the
reset_sim
functionality for the balance bot. Thanks to makeecat. - Publishing Fixes #103: Resolved various publishing issues and added dry-run validations to avoid disruptions.
- Simulation API Support: With sim-mode=true in the main Copper macro, Copper will generate for you all the callbacks at all the tasks states it is going through (Start, Preprocess, Process, etc...). Combined with the already mockable Clock it allows a very easy integration with a virtual environment.
- BalanceBot Simulation #69: Built on that and leveraging Bevy and Avian3D for realistic motion dynamics, we made a little demo of our little real world demonstrator. The real world code and the sim code are 100% identical.
-
Config Embedding #78: Embedded the default
copperconfig.ron
directly into the Copper executable, simplifying deployment for the main case (just one executable to copy and that's it!!). If the file is present, it will take precedence over the embedded version. We also do log the actual config used in the logs so you can come back to it in doubt.
- Cross-Platform Compatibility for Mocking #75: Enhanced feature flags to better support various platforms, particularly macOS, enabling testing with mocked hardware dependencies. The full repo now compile under CI/CD on MacOS and Linux (previously it we could only compile and test the Core)
- Terminal Restoration #73: Fixed issues with terminal states not restoring properly upon exit, preventing corruption and enhancing the overall stability of simulator sessions.
- Print Output Cleanup #80: Streamlined console logging to minimize redundant or unnecessary print statements, making debugging output more manageable.
- Git LFS Migration #76: Moved heavy assets to a CDN to mitigate GitHub LFS limitations, reducing operational overhead and streamlining asset distribution.
- Asset CDN Integration #35: Transitioned assets to a content delivery network to avoid the super costly Github LFS.
- Improved Documentation #82: Expanded and refined documentation across modules, enhancing clarity for new users and developers.
- Logging Value Enhancements #80: Fine-tuned value logging to increase logging granularity and simplify troubleshooting in complex simulation states.
- Feature Flag Revamp #75: Restructured feature flags to better support debugging and cross-platform configurations, especially for macOS compatibility.
A Minor release with 2 new components and some fixes.
-
New cu-pid task: this is the first algorithm we publish. It is from the balancebot, a generalized PID controller logic you can reuse in your projects, see the readme in the crate.
-
New cu-consolemon monitoring: this is a TUI for Copper showing the information exposed by the new monitoring interface released in 0.3.0.
- Added
Mul
toCuDuration
for easy time offset computations.
-
Tree Reorganization:
- Major reorganization of the repository structure for improved clarity and maintainability.
-
Logging Fixes:
- Resolved an issue where
OnceLock
was not releasing the unified logger, preventing a clean shutdown of the logger. - Addressed an issue with a double close in the logger during shutdown.
- Resolved an issue where
This alpha release introduces substantial improvements to the Copper framework's monitoring capabilities and API flexibility.
- New multisource and optional input API: The Copper engine now supports multiple and optional inputs/outputs (see PR #44).
This is a breaking change.
Now you can link 2 tasks to one in the RON file like this:
tasks: [
(
id: "balpos",
type: "cu_ads7883::ADS7883",
),
(
id: "railpos",
type: "cu_rp_encoder::Encoder",
),
(
id: "pidctrl",
type: "pidtask::PIDTask",
config: {
[...]
},
),
(
id: "motor",
type: "cu_rp_sn754410::SN754410",
[...]
),
],
cnx: [
// vvvvvvvvvv same dest!
(src: "balpos", dst: "pidctrl", msg: "cu_ads7883::ADSReadingPayload"),
(src: "railpos", dst: "pidctrl", msg: "cu_rp_encoder::EncoderPayload"),
(src: "pidctrl", dst: "motor", msg: "cu_rp_sn754410::MotorPayload"),
],
)
To help you manage the types that are generated, we are giving a set of macros to help you matching the correct input / output types:
impl<'cl> CuTask<'cl> for PIDTask {
// This tasks takes 2 inputs!
// They are given in the order of task declaration
// the input_msg! macro build a (&CuMsg<ADSReadingPayload>, &CuMsg<EncoderPayload>) tuple under the hood.
// it also works with 1 input and then you will get a straight &CuMsg<> immutable ref.
// For technical Rust reasons, you need to explicitely tie the lifetime ('cl means copperlist if you are curious: the internal structure of copper for messages)
type Input = input_msg!('cl, ADSReadingPayload, EncoderPayload);
// same thing but as an output this is a &mut CuMsg<MotorPayload>
type Output = output_msg!('cl, MotorPayload);
fn process(
&mut self,
clock: &RobotClock,
input: Self::Input, // here this is now straight the input type, it is a little simpler.
output: Self::Output,
) -> CuResult<()> {
let (bal_pos, rail_pos) = input; // you can unpack the tuple directly those are resp. &CuMsg<ADSReadingPayload> and &CuMsg<EncoderPayload>
let bal_tov = bal_pos.metadata.tov.expect("we should have had a message here!"); // the messages are now optional depending on the context they could be expected or really optional.
// we have a new method called set_payload for the output
output.set_payload(MotorPayload { power: 0.0 }); // If you don't do that it will send away a message with a None payload
- Monitoring System: The monitoring framework is now fully integrated, allowing real-time stats collection and cumulative statistics (see PRs #49, #50, and #51). We can imagine complex decision trees happening at that stage for complex robots and various degraded modes.
The monitoring component is really similar to a task, but with specialized callbacks:
// This is in the RON file, just add a monitor entry like this:
tasks: [
(
id: "task0",
type: "tasks::ExampleSrc",
),
[...]
],
cnx: [
(src: "task0", dst: "task1", msg: "i32"),
[...]
],
monitor: (type: "ExampleMonitor") // here, add a config entry if necessary
)
struct ExampleMonitor {
tasks: &'static [&'static str], // We give you the task ordinal to task id mapping (so it is stable as long as you don't change your task ids.
}
impl CuMonitor for ExampleMonitor {
// We pass you the config you gave in the RON file exactly like for the tasks.
fn new(_config: Option<&ComponentConfig>, taskids: &'static [&str]) -> CuResult<Self> {
Ok(ExampleMonitor { tasks: taskids })
}
fn start(&mut self, clock: &_RobotClock) -> CuResult<()> {
// callbacked when all the tasks, start called.
}
fn process_copperlist(&self, msgs: &[&CuMsgMetadata]) -> CuResult<()> {
// This is callbacked at the end of the processing of a copper list (basically near when the CL is getting serialized to disk after a success.
// The metadata gives you all the timings you need to check if your robot is still behaving nominally.
for t in msgs.iter().enumerate() {
let (taskid, metadata) = t;
debug!("Task: {} -> {}", taskid, metadata);
}
Ok(())
}
fn process_error(&self, taskid: usize, step: CuTaskState, error: &CuError) -> Decision {
// This is called back if any task reports an error at any step (start, process, ...)
// You can then match that taskid and compute a decision for your robot: Abort, Ignore, Shutdown (see the cu28/monitoring.rs file for semantic details.
Decision::Ignore
}
fn stop(&mut self, clock: &_RobotClock) -> CuResult<()> {
// call when the stack is stopping
Ok(())
}
}
- Real-time cumulative stats for
CuDurations
. See cu29/monitoring.rs we built an histogramming feature for timings this is super useful for monitoring components. Here is the list of everything you get it is not only pretty comprehensive but it is fixed size on memory so it should be pretty swift for any real time monitoring needs or UIs.
// on the CuDurationStatistics struct
pub fn min(&self) -> CuDuration;
pub fn max(&self) -> CuDuration;
pub fn mean(&self) -> CuDuration
pub fn percentile(&self, percentile: f64) -> CuDuration;
pub fn stddev(&self) -> CuDuration;
pub fn jitter_min(&self) -> CuDuration;
pub fn jitter_max(&self) -> CuDuration;
pub fn jitter_mean(&self) -> CuDuration;
pub fn jitter_stddev(&self) -> CuDuration;
pub fn jitter_percentile(&self, percentile: f64) -> CuDuration;
- Serialization / Deserialization Bug on Value (#42). A code reformat shuffled the serialization IDs Oo.
-
Virtual Output for Sinks (#53):
- before that there was no mean to monitor sinks (or hacks you might have seen on the incoming message). Now the stack behind the scene generates a () empty message for each sink you you get the perf number cleanly for them even if they don't output anything.
-
Balance Bot Demo (#46):
- a more complete example of a real robot demo we will bring at conferences.
- And a bunch of cleanup / doc improments.
We are pleased to announce the release of Copper v0.2.3, which includes several new features, enhancements, and bug fixes. Below is a summary of the key changes in this release:
- SN754410 Driver Support #40: Added a new driver for the SN754410 motor driver. This driver allows easy integration with motor control applications, providing robust support for H-bridge motor control on a wide range of systems. This driver is fully compatible with the BalanceHAT.
- ADS7883 Driver #39: Introduced a driver for the ADS7883, a 12-bit SPI ADC. This addition includes comprehensive documentation in the README to facilitate setup and integration. The ADS7883 driver is also compatible with the BalanceHAT.
- macOS Development Support #25: Copper can now be developed on macOS! The CI/CD pipeline has been updated to support macOS, ensuring cross-platform compatibility for all users.
- cu29_clock Enhancements #32: Added a division feature to the cu29_clock, allowing more granular time management and synchronization within the Copper runtime.
- Structured Log Index File in Debug Mode #30: Removed the requirement for an index file in debug mode within struct_log, simplifying the debugging process ie. only the config and the executable needs to be deployed for the debug build and you get a standard debug text logging.
- Logging Slabs Addition #24: The current unified logger works with big memory mapped files. Initially we thought we could rely on the mmap resize feature of the kernel api but it just doesn't work. We are reverting into building "slabs", ie dividing the data logger into large files. Those files can be concatenated and read or directly read from the log exporter.
- Compilation Feedback Adjustments #33: Moved compilation feedback from standard output to standard error to better align with conventional logging practices.
- Flush and Core Dump Fixes #29: Resolved issues where changes after a section flush could cause a core dump, improving the stability of the logging system.
- CI/CD Pipeline Enhancements #25: Added macOS support to the CI/CD pipeline, ensuring better cross-platform compatibility.
- Removed 'Continue on Error' in CI/CD #36: Addressed a CI/CD issue where the pipeline was green while failing Oo.
-
Unified Logger Refactor #27: Refactored the Unified Logger to introduce a dual-slab logging system, improving performance and eliminating the need for remap/resize operations.
-
Runtime Loop Enhancements #21: Added a new notion of loops in the runtime plan, setting the stage for more flexible and powerful runtime behavior.
If you're looking to build your own interfacing with the SN754410 or ADS7883 drivers, we share detailed connectivity schematics with a Raspberry Pi to help you get started.
We recommend updating to this latest version to take advantage of these improvements. As always, please refer to the updated documentation and release notes for detailed information on how to integrate these changes into your projects.
If you have any questions or need further assistance, feel free to reach out to our support team.