Skip to content

feat(payloads): add typed dynamic camera calibration model - #1253

Draft
Daniiiil1 wants to merge 2 commits into
copper-project:masterfrom
Daniiiil1:daniil/feature/camera-calibration
Draft

feat(payloads): add typed dynamic camera calibration model#1253
Daniiiil1 wants to merge 2 commits into
copper-project:masterfrom
Daniiiil1:daniil/feature/camera-calibration

Conversation

@Daniiiil1

@Daniiiil1 Daniiiil1 commented Aug 4, 2026

Copy link
Copy Markdown

Summary

Adds a standard, fixed-size camera model for image and depth-map pipelines, framed specifically as dynamic calibration. The distortion family is selected at compile time with CuCameraModel<D>; a running robot can update intrinsics and coefficients, but cannot change the mathematical distortion model at runtime.

The propagation path uses the existing latched-state primitive: a source emits the full calibration only when it appears or changes, consumers cache it locally, and later cycles carry NoChange. This keeps dynamic calibration deterministic under unified logging and replay without introducing mutable global state on the realtime path.

Related issues

Changes

  • Add CuCameraIntrinsics with an explicit pixel-center convention, validated pinhole parameters, FOV calculations, and rectified pixel-ray conversion including skew.
  • Add compile-time distortion types for no distortion, plumb-bob, rational-polynomial, and equidistant models.
  • Encode each coefficient count in the constructor type, so invalid counts fail to compile rather than being rejected at runtime.
  • Add generic CuCameraModel<D>, CuCameraModelUpdate<D>, and CuCameraModelState<D> for typed dynamic-calibration propagation.
  • Support cropped cameras whose principal point lies outside the delivered image.
  • Keep the model available under no_std; libm provides portable atan calculations.
  • Document the dedicated-output propagation pattern.

Verification

  • cargo test -p cu-sensor-payloads: 43 unit tests, integration tests, and doc tests pass, including a compile-fail coefficient-count test.
  • cargo check -p cu-sensor-payloads --no-default-features: pass.
  • cargo check -p cu-sensor-payloads --features reflect: pass.
  • cargo clippy -p cu-sensor-payloads --all-targets -- -D warnings: pass.
  • cargo clippy -p cu-sensor-payloads --no-default-features --lib -- -D warnings: pass.
  • cargo fmt --all -- --check and git diff --check: pass.

Design questions

This remains a draft because issue #1230 raises a topology decision. I chose a dedicated latched output over runtime-global state so calibration changes remain visible to record/replay. Maintainer feedback would be especially useful on whether Copper should keep this contract or eventually generate a typed graph-level side-data channel.

Local environment note

The root justfile could not be evaluated from this checkout because the absolute path contains a space and its ROOT shell argument is unquoted. The focused CI-equivalent checks above all passed.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Hi! Thanks for opening this pull request.

Because this is your first time contributing to this repository, please read our contributor guide:
https://github.com/copper-project/copper-rs/blob/master/CONTRIBUTING.md

@gbin

gbin commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Thanks for your contribution. We definitely need to standardize calibration in the stack.

Note: today in the examples etc we only have some form of static calibration (in the RON files), and the pattern we encourage our users to use is to use the composition of ron files to make the configuration of any instance of a robot specialized with a static calibration: ie robot #3, get that calibration, robot #4, another one etc...

Your PR adds some kind of dynamic calibration to the system, which does exist in some kind of robots, one classic example are Tesla cars when you drive around and the calibration is picked up from known straight lines on the road.

So maybe first step would be to reframe that in that context: ie. dynamic calibration.

Then ... why is the TYPE of calibration dynamic? this, to be clear, will never happen in real life, you will never have a robot suddenly deciding to change the type of calibration for a camera live (maybe in some kind of lab obscure condition or research but this would be our of scope).

The second fix would be to hardcode the type of calibration as a type parameter in for the rust struct.

Hopefully it makes sense.

Thanks

@Daniiiil1 Daniiiil1 changed the title feat(payloads): add latched camera calibration model feat(payloads): add typed dynamic camera calibration model Aug 4, 2026

Copy link
Copy Markdown
Author

Thanks, that distinction makes sense. I’ve reframed the feature as dynamic calibration and moved the distortion family into the Rust type: CuCameraModel<D>. The robot may update intrinsics or coefficients, but changing from, say, plumb-bob to equidistant now requires a different compiled type. Each model also takes a fixed-size coefficient array, so the wrong count is a compile-time error. The package tests, no_std check, reflect check, and clippy all pass on the updated branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants