Skip to content

Copper Release Log

Guillaume Binet edited this page Oct 12, 2024 · 30 revisions

Copper Release Notes - v0.3.1 - 2023-10-12

A Minor release with 2 new components and some fixes.

New Components

  • 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.

API improvements

  • Added Mul to CuDuration for easy time offset computations.

Various

  • Tree Reorganization:
    • Major reorganization of the repository structure for improved clarity and maintainability.

Bug Fixes

  • 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.

Release Notes - v0.3.0 - 2024-09-30

This alpha release introduces substantial improvements to the Copper framework's monitoring capabilities and API flexibility.

Highlights

  • 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(())
    }
}

Other Notable Changes

New Features

  • 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;

Fixes

  • Serialization / Deserialization Bug on Value (#42). A code reformat shuffled the serialization IDs Oo.

Enhancements

  • 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.

Miscellaneous

  • And a bunch of cleanup / doc improments.

Copper - v0.2.3 - 2024-09-11

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:

New Features

  • 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.

Enhancements

  • 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.

Bug Fixes

  • 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.

Infrastructure and CI/CD

  • 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.

Refactoring and Internal Changes

  • 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.

Clone this wiki locally