From cf2c9c28675e90659119106d4e0a2d97402a1a08 Mon Sep 17 00:00:00 2001 From: cc Date: Tue, 20 Oct 2026 22:29:46 -0700 Subject: [PATCH 01/15] docs(cdr): restack WIP cleanup audit with current boundaries --- docs/development/cdr-cutover-status.md | 38 ++++++++ scripts/audit_cdr_boundaries.py | 125 +++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 docs/development/cdr-cutover-status.md create mode 100644 scripts/audit_cdr_boundaries.py diff --git a/docs/development/cdr-cutover-status.md b/docs/development/cdr-cutover-status.md new file mode 100644 index 00000000000..352fe3daff1 --- /dev/null +++ b/docs/development/cdr-cutover-status.md @@ -0,0 +1,38 @@ +# CDR cutover and legacy cleanup status + +**WIP.** The shared factory supports generated CDR types and legacy LCM types. +The repository migration is incomplete. Keep legacy schemas, decoders and value +wrappers until their callers are migrated and verified. + +## Inspect remaining boundaries + +Run the static audit from this checkout. It does not import runtime modules or +contact hardware: + +```sh +python scripts/audit_cdr_boundaries.py --output /tmp/cdr-boundaries.json +python scripts/audit_cdr_boundaries.py --check +``` + +`--check` returns nonzero while candidates remain. This snapshot has **312 legacy +In/Out declarations** and **997 legacy imports**. These are syntax matches, not +validated runtime failures. Internal driver values can be valid conversion +boundaries. Inspect complete blueprint port pairs before changing them. + +## Current validation limits + +The default-layer check has 37 passing tests and four failures: + +- The Python `TransportRecorder` skips generated values on LCM and Zenoh. The new + Rust recording path is separate; this does not prove Python capture cutover. +- The XArm and Piper collection graphs do not expose the expected generated + aggregate `coordinator_joint_state` input on their recorder. + +Agent, drone, Habitat and other legacy graphs still need migration. Original +work and prior heads remain in the consolidation backups. This restack does not +complete or discard those migrations. + +Before deleting an API, migrate its callers and verify the selected graph, +capture/replay, source timestamps and schema identity on an installed package. +Keep the converter's explicit historical decode boundary for old recordings. +Nix hardware packaging and physical robot behavior are not verified here. diff --git a/scripts/audit_cdr_boundaries.py b/scripts/audit_cdr_boundaries.py new file mode 100644 index 00000000000..43ede95b5fa --- /dev/null +++ b/scripts/audit_cdr_boundaries.py @@ -0,0 +1,125 @@ +# Copyright 2026 Dimensional Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""Inventory legacy runtime imports and typed ports without importing robot modules.""" + +from __future__ import annotations + +import argparse +import ast +from collections import Counter +import json +from pathlib import Path + + +def qualified(node: ast.expr, imports: dict[str, str]) -> str: + if isinstance(node, ast.Name): + return imports.get(node.id, node.id) + if isinstance(node, ast.Attribute): + return qualified(node.value, imports) + "." + node.attr + return ast.unparse(node) + + +def legacy(name: str) -> bool: + if name == "dimos_lcm" or name.startswith("dimos_lcm."): + return True + parts = name.split(".") + return len(parts) >= 3 and parts[:2] == ["dimos", "msgs"] and parts[2].endswith("_msgs") + + +def audit(root: Path) -> dict: + imports_found = [] + ports = [] + for path in sorted((root / "dimos").rglob("*.py")): + relative = path.relative_to(root) + if path.name.startswith(("test_", "demo_", "tool_")) or path.name == "conftest.py": + continue + if relative.parts[:2] == ("dimos", "msgs"): + continue + tree = ast.parse(path.read_text(), filename=str(relative)) + imports = {} + for node in ast.walk(tree): + if isinstance(node, ast.ImportFrom): + for alias in node.names: + full = f"{node.module}.{alias.name}" + imports[alias.asname or alias.name] = full + if legacy(full): + imports_found.append( + {"file": str(relative), "line": node.lineno, "symbol": full} + ) + elif isinstance(node, ast.Import): + for alias in node.names: + imports[alias.asname or alias.name.split(".")[0]] = ( + alias.name if alias.asname else alias.name.split(".")[0] + ) + if legacy(alias.name): + imports_found.append( + {"file": str(relative), "line": node.lineno, "symbol": alias.name} + ) + for node in ast.walk(tree): + if not isinstance(node, ast.AnnAssign) or not isinstance( + node.annotation, ast.Subscript + ): + continue + annotation = node.annotation + direction = qualified(annotation.value, imports) + if direction not in {"dimos.core.stream.In", "dimos.core.stream.Out"}: + continue + candidates = [ + qualified(n, imports) + for n in ast.walk(annotation.slice) + if isinstance(n, (ast.Name, ast.Attribute)) + ] + types = sorted({name for name in candidates if legacy(name)}) + if types: + ports.append( + { + "file": str(relative), + "line": node.lineno, + "port": ast.unparse(node.target), + "direction": direction.rsplit(".", 1)[1], + "legacy_types": types, + } + ) + return { + "status": "unfinished" if ports or imports_found else "clear", + "method": "Static Python import and typed In/Out scan; no runtime graph or hardware imports. Internal driver values are not automatically wire defects.", + "legacy_port_count": len(ports), + "legacy_import_count": len(imports_found), + "ports_by_subsystem": dict(sorted(Counter(p["file"].split("/")[1] for p in ports).items())), + "legacy_ports": ports, + "legacy_imports": imports_found, + } + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1]) + parser.add_argument("--output", type=Path) + parser.add_argument( + "--check", action="store_true", help="Fail while any legacy imports or ports remain." + ) + args = parser.parse_args() + report = audit(args.root.resolve()) + text = json.dumps(report, indent=2) + "\n" + if args.output: + args.output.write_text(text) + else: + print(text, end="") + return int(args.check and report["status"] != "clear") + + +if __name__ == "__main__": + raise SystemExit(main()) From 71c08893f7a770990f8c3bb7d8c95b2da6f624b5 Mon Sep 17 00:00:00 2001 From: cc Date: Wed, 21 Oct 2026 19:32:30 -0700 Subject: [PATCH 02/15] docs(cdr): refresh the remaining legacy import audit count --- docs/development/cdr-cutover-status.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/cdr-cutover-status.md b/docs/development/cdr-cutover-status.md index 352fe3daff1..4c96d1509b0 100644 --- a/docs/development/cdr-cutover-status.md +++ b/docs/development/cdr-cutover-status.md @@ -15,7 +15,7 @@ python scripts/audit_cdr_boundaries.py --check ``` `--check` returns nonzero while candidates remain. This snapshot has **312 legacy -In/Out declarations** and **997 legacy imports**. These are syntax matches, not +In/Out declarations** and **998 legacy imports**. These are syntax matches, not validated runtime failures. Internal driver values can be valid conversion boundaries. Inspect complete blueprint port pairs before changing them. From c9a13b72c31bf2d7ebc80b6789cb64ebb2b1d9f8 Mon Sep 17 00:00:00 2001 From: cc Date: Thu, 22 Oct 2026 15:18:49 -0700 Subject: [PATCH 03/15] Use standard ROS TF messages and library-backed frame queries --- .github/workflows/cdr-native.yml | 6 +- bin/generate-native-tf-messages | 39 + .../sensors/camera/realsense/camera.py | 3 +- .../sensors/camera/realsense/rust/Cargo.lock | 40 +- .../sensors/camera/realsense/rust/Cargo.toml | 7 +- .../sensors/camera/realsense/rust/build.rs | 3 + .../camera/realsense/rust/crate-hashes.json | 1 + .../sensors/camera/realsense/rust/flake.nix | 4 +- .../sensors/camera/realsense/rust/src/main.rs | 64 +- .../sensors/camera/v4l2/rust/Cargo.lock | 30 + .../sensors/camera/v4l2/rust/Cargo.toml | 2 +- .../camera/v4l2/rust/crate-hashes.json | 1 + .../sensors/camera/v4l2/rust/flake.nix | 1 + dimos/mapping/ray_tracing/module.py | 1 + dimos/mapping/ray_tracing/rust/Cargo.lock | 40 +- dimos/mapping/ray_tracing/rust/Cargo.toml | 4 +- .../ray_tracing/rust/crate-hashes.json | 1 + dimos/mapping/ray_tracing/rust/flake.nix | 9 +- dimos/mapping/ray_tracing/rust/src/module.rs | 47 +- dimos/mapping/ray_tracing/rust/src/wire.rs | 23 - .../ray_tracing/test_generated_native.py | 17 +- .../mls_planner/mls_planner_native.py | 1 + .../mls_planner/rust/Cargo.lock | 40 +- .../mls_planner/rust/Cargo.toml | 4 +- .../mls_planner/rust/crate-hashes.json | 1 + .../global_planner/mls_planner/rust/flake.nix | 9 +- .../mls_planner/rust/src/module.rs | 7 +- .../mls_planner/test_generated_native.py | 2 + dimos/navigation/local_planner/native.py | 1 + .../navigation/local_planner/rust/Cargo.lock | 40 +- .../navigation/local_planner/rust/Cargo.toml | 6 +- .../local_planner/rust/crate-hashes.json | 1 + dimos/navigation/local_planner/rust/flake.nix | 7 +- .../local_planner/rust/src/module/msg.rs | 44 +- .../local_planner/rust/src/module/planner.rs | 2 +- .../local_planner/rust/src/module/tf_pose.rs | 26 +- .../local_planner/test_generated_native.py | 2 +- .../trajectory_follower/fancy/native.py | 1 + .../trajectory_follower/fancy/rust/Cargo.lock | 41 +- .../trajectory_follower/fancy/rust/Cargo.toml | 6 +- .../fancy/rust/crate-hashes.json | 1 + .../trajectory_follower/fancy/rust/flake.nix | 10 +- .../fancy/rust/src/module/follower.rs | 2 +- dimos/perception/depth2depth_cloud/module.py | 2 +- .../depth2depth_cloud/rust/Cargo.lock | 40 +- .../depth2depth_cloud/rust/Cargo.toml | 4 +- .../depth2depth_cloud/rust/crate-hashes.json | 1 + .../depth2depth_cloud/rust/flake.nix | 9 +- .../depth2depth_cloud/rust/src/module.rs | 105 +- native/rust/dimos-message-adapters/Cargo.lock | 4447 ----------------- native/rust/dimos-message-adapters/Cargo.toml | 13 - native/rust/dimos-message-adapters/src/lib.rs | 17 - native/rust/dimos-message-adapters/src/tf.rs | 202 - native/rust/dimos-module-macros/src/lib.rs | 94 +- native/rust/dimos-module/Cargo.lock | 92 + native/rust/dimos-module/Cargo.toml | 7 +- native/rust/dimos-module/README.md | 28 + native/rust/dimos-module/src/lib.rs | 3 +- native/rust/dimos-module/src/module.rs | 120 +- native/rust/dimos-module/src/tf.rs | 1741 ++----- native/rust/dimos-module/src/time.rs | 12 +- native/rust/dimos-tf-messages/Cargo.toml | 13 + native/rust/dimos-tf-messages/README.md | 13 + native/rust/dimos-tf-messages/build.rs | 57 + .../builtin_interfaces/msg/Time.msg | 11 + .../geometry_msgs/msg/Quaternion.msg | 6 + .../geometry_msgs/msg/Transform.msg | 4 + .../geometry_msgs/msg/TransformStamped.msg | 19 + .../interfaces/geometry_msgs/msg/Vector3.msg | 9 + .../interfaces/std_msgs/msg/Header.msg | 9 + .../interfaces/tf2_msgs/msg/TFMessage.msg | 1 + native/rust/dimos-tf-messages/schemas.json | 9 + native/rust/dimos-tf-messages/src/lib.rs | 2 + 73 files changed, 1231 insertions(+), 6456 deletions(-) create mode 100755 bin/generate-native-tf-messages delete mode 100644 native/rust/dimos-message-adapters/Cargo.lock delete mode 100644 native/rust/dimos-message-adapters/Cargo.toml delete mode 100644 native/rust/dimos-message-adapters/src/lib.rs delete mode 100644 native/rust/dimos-message-adapters/src/tf.rs create mode 100644 native/rust/dimos-module/README.md create mode 100644 native/rust/dimos-tf-messages/Cargo.toml create mode 100644 native/rust/dimos-tf-messages/README.md create mode 100644 native/rust/dimos-tf-messages/build.rs create mode 100644 native/rust/dimos-tf-messages/interfaces/builtin_interfaces/msg/Time.msg create mode 100644 native/rust/dimos-tf-messages/interfaces/geometry_msgs/msg/Quaternion.msg create mode 100644 native/rust/dimos-tf-messages/interfaces/geometry_msgs/msg/Transform.msg create mode 100644 native/rust/dimos-tf-messages/interfaces/geometry_msgs/msg/TransformStamped.msg create mode 100644 native/rust/dimos-tf-messages/interfaces/geometry_msgs/msg/Vector3.msg create mode 100644 native/rust/dimos-tf-messages/interfaces/std_msgs/msg/Header.msg create mode 100644 native/rust/dimos-tf-messages/interfaces/tf2_msgs/msg/TFMessage.msg create mode 100644 native/rust/dimos-tf-messages/schemas.json create mode 100644 native/rust/dimos-tf-messages/src/lib.rs diff --git a/.github/workflows/cdr-native.yml b/.github/workflows/cdr-native.yml index 650b9c07a64..fe89b04da0c 100644 --- a/.github/workflows/cdr-native.yml +++ b/.github/workflows/cdr-native.yml @@ -36,13 +36,15 @@ jobs: run: uv sync --frozen --group tests - name: Test SDK and build native consumers run: | - cargo test --locked --manifest-path native/rust/dimos-module/Cargo.toml --features cdr - cargo test --locked --manifest-path native/rust/dimos-message-adapters/Cargo.toml + cargo test --locked --manifest-path native/rust/dimos-module/Cargo.toml + cargo test --locked --manifest-path native/rust/dimos-module-macros/Cargo.toml cargo test --locked --manifest-path dimos/mapping/ray_tracing/rust/Cargo.toml --lib cargo test --locked --manifest-path dimos/navigation/global_planner/mls_planner/rust/Cargo.toml --lib cargo test --locked --manifest-path dimos/navigation/local_planner/rust/Cargo.toml --features module,test-bodies cargo test --locked --manifest-path dimos/navigation/trajectory_follower/fancy/rust/Cargo.toml --features module cargo test --locked --manifest-path dimos/hardware/sensors/camera/v4l2/rust/Cargo.toml --lib + cargo check --locked --manifest-path dimos/perception/depth2depth_cloud/rust/Cargo.toml --lib + cargo check --locked --manifest-path dimos/hardware/sensors/camera/realsense/rust/Cargo.toml --all-targets --features docs-only cargo build --locked --manifest-path dimos/mapping/ray_tracing/rust/Cargo.toml --bin voxel_ray_tracing cargo build --locked --manifest-path dimos/navigation/global_planner/mls_planner/rust/Cargo.toml --bin mls_planner cargo build --locked --manifest-path dimos/navigation/local_planner/rust/Cargo.toml --features module --bin local_planner diff --git a/bin/generate-native-tf-messages b/bin/generate-native-tf-messages new file mode 100755 index 00000000000..abca25c155d --- /dev/null +++ b/bin/generate-native-tf-messages @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# Copyright 2026 Dimensional Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Regenerate the SDK's standard TF message crate with dimos-cdrgen 0.1.2.""" + +from importlib.metadata import version +from pathlib import Path +import shutil +from tempfile import TemporaryDirectory + +from dimos_cdrgen.generate import generate + +root = Path(__file__).resolve().parents[1] +crate = root / "native/rust/dimos-tf-messages" +if version("dimos-cdrgen") != "0.1.2": + raise RuntimeError("Install dimos-cdrgen==0.1.2 before regenerating TF messages") +with TemporaryDirectory() as temporary: + output = Path(temporary) / "generated" + generate( + [crate / "interfaces"], + output, + ["tf2_msgs/msg/TFMessage"], + module="dimos_tf", + version="0.1.0", + languages=("rust",), + ) + shutil.copytree(output / "rust", crate, dirs_exist_ok=True) diff --git a/dimos/hardware/sensors/camera/realsense/camera.py b/dimos/hardware/sensors/camera/realsense/camera.py index 5571b5fc4f8..91cd5f5df16 100644 --- a/dimos/hardware/sensors/camera/realsense/camera.py +++ b/dimos/hardware/sensors/camera/realsense/camera.py @@ -22,7 +22,7 @@ from pydantic import Field, InstanceOf from dimos.core.native_module import NativeModule, NativeModuleConfig -from dimos.core.stream import Out +from dimos.core.stream import In, Out from dimos.hardware.sensors.camera.spec import DepthCameraConfig from dimos.messages.builtin_interfaces.msg import Time from dimos.messages.dimos_msgs.msg import ImuInfo @@ -111,6 +111,7 @@ class RealSenseCamera(NativeModule, perception.DepthCamera): infrared_left_camera_info: Out[CameraInfo] infrared_right_camera_info: Out[CameraInfo] tf: Out[TFMessage] + tf_static: In[TFMessage] if TYPE_CHECKING: diff --git a/dimos/hardware/sensors/camera/realsense/rust/Cargo.lock b/dimos/hardware/sensors/camera/realsense/rust/Cargo.lock index aa22e6b5c13..8c9d89cdea2 100644 --- a/dimos/hardware/sensors/camera/realsense/rust/Cargo.lock +++ b/dimos/hardware/sensors/camera/realsense/rust/Cargo.lock @@ -569,15 +569,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "dimos-message-adapters" -version = "0.1.0" -dependencies = [ - "dimos-generated-messages", - "dimos-module", - "nalgebra", -] - [[package]] name = "dimos-module" version = "0.2.0" @@ -585,6 +576,7 @@ dependencies = [ "cdr", "dimos-lcm", "dimos-module-macros", + "dimos-tf-messages", "lcm-msgs", "nalgebra", "rayon", @@ -593,6 +585,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "transforms", "url", "validator", "zenoh", @@ -613,7 +606,6 @@ name = "dimos-realsense" version = "0.1.0" dependencies = [ "dimos-generated-messages", - "dimos-message-adapters", "dimos-module", "pkg-config", "realsense-rust", @@ -624,6 +616,17 @@ dependencies = [ "validator", ] +[[package]] +name = "dimos-tf-messages" +version = "0.1.0" +dependencies = [ + "cdr", + "heapless", + "ros2msg", + "serde", + "serde-big-array", +] + [[package]] name = "dirs" version = "6.0.0" @@ -1005,6 +1008,11 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "heapless" @@ -3318,6 +3326,18 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "transforms" +version = "2.2.0" +source = "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#76cf9022173d5764814544082f2b518a9df1934b" +dependencies = [ + "approx", + "hashbrown 0.17.1", + "libm", + "serde", + "thiserror 2.0.20", +] + [[package]] name = "twox-hash" version = "1.6.3" diff --git a/dimos/hardware/sensors/camera/realsense/rust/Cargo.toml b/dimos/hardware/sensors/camera/realsense/rust/Cargo.toml index 71d096d0e7f..70a886b5f9e 100644 --- a/dimos/hardware/sensors/camera/realsense/rust/Cargo.toml +++ b/dimos/hardware/sensors/camera/realsense/rust/Cargo.toml @@ -18,6 +18,7 @@ python = "dimos.hardware.sensors.camera.realsense.camera:RealSenseCamera" [package.metadata.dimos.module.realsense.inputs] tf = "tf2_msgs/msg/TFMessage" +tf_static = "tf2_msgs/msg/TFMessage" [package.metadata.dimos.module.realsense.outputs] color_image = "sensor_msgs/msg/Image" @@ -32,9 +33,11 @@ depth_camera_info = "sensor_msgs/msg/CameraInfo" infrared_left_camera_info = "sensor_msgs/msg/CameraInfo" infrared_right_camera_info = "sensor_msgs/msg/CameraInfo" +[features] +docs-only = ["realsense-rust/docs-only"] + [dependencies] -dimos-module = { path = "../../../../../../native/rust/dimos-module", features = ["cdr"] } -dimos-message-adapters = { path = "../../../../../../native/rust/dimos-message-adapters" } +dimos-module = { path = "../../../../../../native/rust/dimos-module" } dimos-generated-messages = { path = "../../../../../../build/message-source/rust" } realsense-rust = "1.3" realsense-sys = "2.56" diff --git a/dimos/hardware/sensors/camera/realsense/rust/build.rs b/dimos/hardware/sensors/camera/realsense/rust/build.rs index d0deae698cd..934e8ab9e4e 100644 --- a/dimos/hardware/sensors/camera/realsense/rust/build.rs +++ b/dimos/hardware/sensors/camera/realsense/rust/build.rs @@ -17,6 +17,9 @@ // names lib/x86_64-linux-gnu while the .so sits in lib/, so walk up to it -- // for the linker too, or `-lrealsense2` is not found at all. fn main() { + if std::env::var_os("CARGO_FEATURE_DOCS_ONLY").is_some() { + return; + } let lib = pkg_config::probe_library("realsense2").expect("librealsense2 via pkg-config"); for path in lib.link_paths { let dir = path diff --git a/dimos/hardware/sensors/camera/realsense/rust/crate-hashes.json b/dimos/hardware/sensors/camera/realsense/rust/crate-hashes.json index ab24c6fabdc..6b69cda334e 100644 --- a/dimos/hardware/sensors/camera/realsense/rust/crate-hashes.json +++ b/dimos/hardware/sensors/camera/realsense/rust/crate-hashes.json @@ -1,5 +1,6 @@ { "git+https://github.com/TomCC7/cdr-rs?rev=38a4368255d408faf374726653b39d4a4e9735cb#cdr@0.2.4": "sha256-akg/bLBY3wQ1YRr2bijE5ZqB211Cst5lKjELLrgiG6o=", + "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#transforms@2.2.0": "sha256-8TdIhfkDahcX5MkLYMbCqaODp0+HHUqJNzyk8K7MEBU=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#dimos-lcm@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#lcm-msgs@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=" } \ No newline at end of file diff --git a/dimos/hardware/sensors/camera/realsense/rust/flake.nix b/dimos/hardware/sensors/camera/realsense/rust/flake.nix index 2fc39a41b77..1037c80e4d0 100644 --- a/dimos/hardware/sensors/camera/realsense/rust/flake.nix +++ b/dimos/hardware/sensors/camera/realsense/rust/flake.nix @@ -33,7 +33,7 @@ mkdir -p $out/native/rust $out/build/message-source $out/dimos/hardware/sensors/camera/realsense/rust cp -r ${sharedSource}/native/rust/dimos-module $out/native/rust/ cp -r ${sharedSource}/native/rust/dimos-module-macros $out/native/rust/ - cp -r ${sharedSource}/native/rust/dimos-message-adapters $out/native/rust/ + cp -r ${sharedSource}/native/rust/dimos-tf-messages $out/native/rust/ cp -r ${messages.source}/rust $out/build/message-source/rust cp -r ${cameraSource}/. $out/dimos/hardware/sensors/camera/realsense/rust/ ''; @@ -51,7 +51,7 @@ dimos-realsense = needsLibrealsense; }; - ours = [ name "dimos-module" "dimos-module-macros" "dimos-message-adapters" ]; + ours = [ name "dimos-module" "dimos-module-macros" "dimos-tf-messages" ]; callWith = mode: import generated { inherit pkgs; buildRustCrateForPkgs = cratePkgs: diff --git a/dimos/hardware/sensors/camera/realsense/rust/src/main.rs b/dimos/hardware/sensors/camera/realsense/rust/src/main.rs index 939f1e27782..84a161134ea 100644 --- a/dimos/hardware/sensors/camera/realsense/rust/src/main.rs +++ b/dimos/hardware/sensors/camera/realsense/rust/src/main.rs @@ -34,13 +34,12 @@ use dimos_generated_messages::sensor_msgs::msg::{ point_field::PointField, region_of_interest::RegionOfInterest, }; use dimos_generated_messages::std_msgs::msg::header::Header; -use dimos_generated_messages::tf2_msgs::msg::tf_message::TFMessage; -use dimos_message_adapters::tf::{decode as decode_cdr_tf, encode as encode_cdr_tf}; + use dimos_module::cdr; use dimos_module::nalgebra::{ Isometry3, Matrix3, Quaternion, Rotation3, Translation3, UnitQuaternion, Vector3, }; -use dimos_module::{native_config, run_with_transport, Module, Output, Tf, Transform}; +use dimos_module::{native_config, run_with_transport, Module, Output, Tf}; use realsense_rust::base::{Rs2Extrinsics, Rs2Intrinsics}; use realsense_rust::config::Config as RsConfig; use realsense_rust::context::Context; @@ -248,7 +247,7 @@ struct RealSense { infrared_left_camera_info: Output, #[output(encode = cdr::encode)] infrared_right_camera_info: Output, - #[tf(decode = decode_cdr_tf, encode = encode_cdr_tf)] + #[tf] tf: Tf, #[config] config: Config, @@ -822,7 +821,16 @@ fn capture_thread(cfg: &Config, shared: &Shared, handle: &Handle, outs: &Outs) { if let Some(ts) = latest { let mut transforms = Vec::with_capacity(mount_edges.len()); for (parent, child, iso) in &mount_edges { - transforms.push(Transform::new(parent.clone(), child.clone(), ts, *iso)); + let stamp = header(parent, ts).stamp; + transforms.push(dimos_module::tf::from_isometry( + parent.clone(), + child.clone(), + dimos_module::tf::Time { + sec: stamp.sec, + nanosec: stamp.nanosec, + }, + *iso, + )); } let _ = handle.block_on(outs.tf.publish(&transforms)); } @@ -1368,52 +1376,6 @@ mod tests { } } - #[test] - fn canonical_tf_preserves_frames_math_and_normalized_time_in_both_endians() { - for ts in [3.25, -0.25, 1.0 - 1e-12] { - let transform = - Transform::new("map", "camera", ts, Isometry3::translation(1.0, 2.0, 3.0)); - let bytes = encode_cdr_tf(&[transform]).unwrap(); - assert_eq!(&bytes[..4], &[0, 1, 0, 0]); - let message: TFMessage = cdr::decode(&bytes).unwrap(); - assert!(message.transforms[0].header.stamp.nanosec < 1_000_000_000); - for payload in [bytes, cdr::encode_endian(&message, false).unwrap()] { - let decoded = decode_cdr_tf(&payload).unwrap(); - assert_eq!(decoded.len(), 1); - assert_eq!(decoded[0].parent, "map"); - assert_eq!(decoded[0].child, "camera"); - assert!((decoded[0].ts - ts).abs() <= 1e-9); - assert_eq!(decoded[0].translation(), Vector3::new(1.0, 2.0, 3.0)); - } - } - let bytes = - encode_cdr_tf(&[Transform::new("map", "camera", 3.25, Isometry3::identity())]).unwrap(); - export_fixture("tf.cdr", &cdr::decode::(&bytes).unwrap()); - assert!(decode_cdr_tf(b"legacy or malformed bytes").is_err()); - } - - #[test] - fn canonical_tf_rejects_message_when_one_quaternion_is_invalid() { - let bytes = - encode_cdr_tf(&[Transform::new("map", "camera", 3.25, Isometry3::identity())]).unwrap(); - let mut message: TFMessage = cdr::decode(&bytes).unwrap(); - let mut invalid = message.transforms[0].clone(); - invalid.child_frame_id = "invalid".into(); - invalid.transform.rotation = QuaternionMsg { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, - }; - message.transforms.push(invalid); - assert_eq!( - decode_cdr_tf(&cdr::encode(&message).unwrap()) - .unwrap_err() - .kind(), - std::io::ErrorKind::InvalidData - ); - } - #[test] fn generated_calibration_and_rgbd_cloud_keep_source_stamp_and_matching_colors() { let intrinsics = Rs2Intrinsics(sys::rs2_intrinsics { diff --git a/dimos/hardware/sensors/camera/v4l2/rust/Cargo.lock b/dimos/hardware/sensors/camera/v4l2/rust/Cargo.lock index 8af50b1d9c1..5a6d78613fa 100644 --- a/dimos/hardware/sensors/camera/v4l2/rust/Cargo.lock +++ b/dimos/hardware/sensors/camera/v4l2/rust/Cargo.lock @@ -591,6 +591,7 @@ dependencies = [ "cdr", "dimos-lcm", "dimos-module-macros", + "dimos-tf-messages", "lcm-msgs", "nalgebra", "rayon", @@ -599,6 +600,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "transforms", "url", "validator", "zenoh", @@ -614,6 +616,17 @@ dependencies = [ "toml 1.1.4+spec-1.1.0", ] +[[package]] +name = "dimos-tf-messages" +version = "0.1.0" +dependencies = [ + "cdr", + "heapless", + "ros2msg", + "serde", + "serde-big-array", +] + [[package]] name = "dimos-v4l2-camera" version = "0.1.0" @@ -1016,6 +1029,11 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "heapless" @@ -3290,6 +3308,18 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "transforms" +version = "2.2.0" +source = "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#76cf9022173d5764814544082f2b518a9df1934b" +dependencies = [ + "approx", + "hashbrown 0.17.1", + "libm", + "serde", + "thiserror 2.0.20", +] + [[package]] name = "turbojpeg" version = "1.5.1" diff --git a/dimos/hardware/sensors/camera/v4l2/rust/Cargo.toml b/dimos/hardware/sensors/camera/v4l2/rust/Cargo.toml index a42c8adf6b1..ef5a92263f4 100644 --- a/dimos/hardware/sensors/camera/v4l2/rust/Cargo.toml +++ b/dimos/hardware/sensors/camera/v4l2/rust/Cargo.toml @@ -21,7 +21,7 @@ python = "dimos.hardware.sensors.camera.v4l2.module:V4L2Camera" jpeg_out = "sensor_msgs/msg/CompressedImage" [dependencies] -dimos-module = { path = "../../../../../../native/rust/dimos-module", features = ["cdr"] } +dimos-module = { path = "../../../../../../native/rust/dimos-module" } dimos-generated-messages = { path = "../../../../../../build/message-source/rust" } tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal"] } serde = { version = "1", features = ["derive"] } diff --git a/dimos/hardware/sensors/camera/v4l2/rust/crate-hashes.json b/dimos/hardware/sensors/camera/v4l2/rust/crate-hashes.json index ab24c6fabdc..6b69cda334e 100644 --- a/dimos/hardware/sensors/camera/v4l2/rust/crate-hashes.json +++ b/dimos/hardware/sensors/camera/v4l2/rust/crate-hashes.json @@ -1,5 +1,6 @@ { "git+https://github.com/TomCC7/cdr-rs?rev=38a4368255d408faf374726653b39d4a4e9735cb#cdr@0.2.4": "sha256-akg/bLBY3wQ1YRr2bijE5ZqB211Cst5lKjELLrgiG6o=", + "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#transforms@2.2.0": "sha256-8TdIhfkDahcX5MkLYMbCqaODp0+HHUqJNzyk8K7MEBU=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#dimos-lcm@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#lcm-msgs@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=" } \ No newline at end of file diff --git a/dimos/hardware/sensors/camera/v4l2/rust/flake.nix b/dimos/hardware/sensors/camera/v4l2/rust/flake.nix index 9e9e1c74099..6090a0e0715 100644 --- a/dimos/hardware/sensors/camera/v4l2/rust/flake.nix +++ b/dimos/hardware/sensors/camera/v4l2/rust/flake.nix @@ -35,6 +35,7 @@ mkdir -p $out/native/rust $out/build/message-source $out/dimos/hardware/sensors/camera/v4l2/rust cp -r ${sharedSource}/native/rust/dimos-module $out/native/rust/ cp -r ${sharedSource}/native/rust/dimos-module-macros $out/native/rust/ + cp -r ${sharedSource}/native/rust/dimos-tf-messages $out/native/rust/ cp -r ${messages.source}/rust $out/build/message-source/rust cp -r ${cameraSource}/. $out/dimos/hardware/sensors/camera/v4l2/rust/ ''; diff --git a/dimos/mapping/ray_tracing/module.py b/dimos/mapping/ray_tracing/module.py index 80d14374d9e..190bcae2147 100644 --- a/dimos/mapping/ray_tracing/module.py +++ b/dimos/mapping/ray_tracing/module.py @@ -98,6 +98,7 @@ class RayTracingVoxelMap(NativeModule, mapping.GlobalPointcloud): # cloud frame_id. Only the first cloud seeds the map. loaded_map: In[PointCloud2] tf: IO[TFMessage] + tf_static: In[TFMessage] global_map: Out[PointCloud2] local_map: Out[PointCloud2] local_map_fine: Out[PointCloud2] diff --git a/dimos/mapping/ray_tracing/rust/Cargo.lock b/dimos/mapping/ray_tracing/rust/Cargo.lock index d8b122d8534..568d065f0b4 100644 --- a/dimos/mapping/ray_tracing/rust/Cargo.lock +++ b/dimos/mapping/ray_tracing/rust/Cargo.lock @@ -615,15 +615,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "dimos-message-adapters" -version = "0.1.0" -dependencies = [ - "dimos-generated-messages", - "dimos-module", - "nalgebra", -] - [[package]] name = "dimos-module" version = "0.2.0" @@ -631,6 +622,7 @@ dependencies = [ "cdr", "dimos-lcm", "dimos-module-macros", + "dimos-tf-messages", "lcm-msgs", "nalgebra", "rayon", @@ -639,6 +631,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "transforms", "url", "validator", "zenoh", @@ -654,6 +647,17 @@ dependencies = [ "toml 1.1.6+spec-1.1.0", ] +[[package]] +name = "dimos-tf-messages" +version = "0.1.0" +dependencies = [ + "cdr", + "heapless", + "ros2msg", + "serde", + "serde-big-array", +] + [[package]] name = "dimos-voxel-ray-tracing" version = "0.1.0" @@ -661,7 +665,6 @@ dependencies = [ "ahash", "arrayvec", "dimos-generated-messages", - "dimos-message-adapters", "dimos-module", "nalgebra", "rayon", @@ -1062,6 +1065,11 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "heapless" @@ -3436,6 +3444,18 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "transforms" +version = "2.2.0" +source = "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#76cf9022173d5764814544082f2b518a9df1934b" +dependencies = [ + "approx", + "hashbrown 0.17.1", + "libm", + "serde", + "thiserror", +] + [[package]] name = "twox-hash" version = "1.6.3" diff --git a/dimos/mapping/ray_tracing/rust/Cargo.toml b/dimos/mapping/ray_tracing/rust/Cargo.toml index 4e63a47684d..1c0e389348b 100644 --- a/dimos/mapping/ray_tracing/rust/Cargo.toml +++ b/dimos/mapping/ray_tracing/rust/Cargo.toml @@ -24,6 +24,7 @@ threads = 2 lidar = "sensor_msgs/msg/PointCloud2" loaded_map = "sensor_msgs/msg/PointCloud2" tf = "tf2_msgs/msg/TFMessage" +tf_static = "tf2_msgs/msg/TFMessage" [package.metadata.dimos.module.ray_tracing.outputs] global_map = "sensor_msgs/msg/PointCloud2" @@ -35,8 +36,7 @@ region_bounds = "dimos_msgs/msg/RegionBounds" map_regions = "dimos_msgs/msg/PointCloudRegion" [dependencies] -dimos-module = { path = "../../../../native/rust/dimos-module", features = ["cdr"] } -dimos-message-adapters = { path = "../../../../native/rust/dimos-message-adapters" } +dimos-module = { path = "../../../../native/rust/dimos-module" } dimos-generated-messages = { path = "../../../../build/message-source/rust" } tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal"] } serde = { version = "1", features = ["derive"] } diff --git a/dimos/mapping/ray_tracing/rust/crate-hashes.json b/dimos/mapping/ray_tracing/rust/crate-hashes.json index ab24c6fabdc..6b69cda334e 100644 --- a/dimos/mapping/ray_tracing/rust/crate-hashes.json +++ b/dimos/mapping/ray_tracing/rust/crate-hashes.json @@ -1,5 +1,6 @@ { "git+https://github.com/TomCC7/cdr-rs?rev=38a4368255d408faf374726653b39d4a4e9735cb#cdr@0.2.4": "sha256-akg/bLBY3wQ1YRr2bijE5ZqB211Cst5lKjELLrgiG6o=", + "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#transforms@2.2.0": "sha256-8TdIhfkDahcX5MkLYMbCqaODp0+HHUqJNzyk8K7MEBU=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#dimos-lcm@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#lcm-msgs@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=" } \ No newline at end of file diff --git a/dimos/mapping/ray_tracing/rust/flake.nix b/dimos/mapping/ray_tracing/rust/flake.nix index e5b93c9ea42..edffc630f95 100644 --- a/dimos/mapping/ray_tracing/rust/flake.nix +++ b/dimos/mapping/ray_tracing/rust/flake.nix @@ -31,21 +31,18 @@ cp -r ${moduleSource} $out chmod -R u+w $out mkdir -p $out/sdk - cp -r ${sharedSource}/native/rust/dimos-module ${sharedSource}/native/rust/dimos-module-macros ${sharedSource}/native/rust/dimos-message-adapters $out/sdk/ + cp -r ${sharedSource}/native/rust/dimos-module ${sharedSource}/native/rust/dimos-module-macros ${sharedSource}/native/rust/dimos-tf-messages $out/sdk/ cp -r ${messageSource}/rust $out/messages - substituteInPlace $out/sdk/dimos-message-adapters/Cargo.toml \ - --replace-fail '../../../build/message-source/rust' '../../messages' substituteInPlace $out/Cargo.toml \ --replace-fail '../../../../native/rust/dimos-module' 'sdk/dimos-module' \ - --replace-fail '../../../../native/rust/dimos-message-adapters' 'sdk/dimos-message-adapters' \ --replace-fail '../../../../build/message-source/rust' 'messages' \ --replace-fail '[workspace]' '[workspace] - exclude = ["sdk/dimos-module", "sdk/dimos-module-macros", "sdk/dimos-message-adapters", "messages"]' + exclude = ["sdk/dimos-module", "sdk/dimos-module-macros", "sdk/dimos-tf-messages", "messages"]' ''; generated = crate2nix.tools.${system}.generatedCargoNix { inherit name src; }; - ours = [ name "dimos-module" "dimos-module-macros" "dimos-message-adapters" ]; + ours = [ name "dimos-module" "dimos-module-macros" "dimos-tf-messages" ]; callWith = mode: import generated { inherit pkgs; buildRustCrateForPkgs = cratePkgs: crate: diff --git a/dimos/mapping/ray_tracing/rust/src/module.rs b/dimos/mapping/ray_tracing/rust/src/module.rs index f4819eab154..36e9ffe26c5 100644 --- a/dimos/mapping/ray_tracing/rust/src/module.rs +++ b/dimos/mapping/ray_tracing/rust/src/module.rs @@ -31,10 +31,10 @@ use dimos_generated_messages::sensor_msgs::msg::{ point_cloud2::PointCloud2, point_field::PointField, }; use dimos_generated_messages::std_msgs::msg::header::Header; -use dimos_message_adapters::tf::{decode as decode_tf, encode as encode_tf}; + use dimos_module::cdr; use dimos_module::{ - debug_throttled, error_throttled, warn_throttled, Input, Module, Output, Tf, Transform, + debug_throttled, error_throttled, warn_throttled, Input, Module, Output, Tf, TransformStamped, }; use tokio::sync::mpsc; use tokio::sync::mpsc::error::TryRecvError; @@ -68,7 +68,7 @@ pub struct RayTracingVoxelMap { #[input(decode = dimos_module::cdr::decode, handler = on_loaded_map)] loaded_map: Input, - #[tf(decode = decode_tf, encode = encode_tf)] + #[tf] tf: Tf, #[output(encode = cdr::encode)] @@ -369,19 +369,23 @@ impl Worker { /// Fold one lidar frame into the map and publish whatever is due. async fn ingest_frame(&self, state: &mut State, msg: PointCloud2, received: Instant) { - // Register with the transform nearest the cloud stamp, waiting briefly + // Register with the transform at the cloud stamp, waiting briefly // for one still in flight rather than dropping the cloud. let stamp = time_secs(&msg.header.stamp); let tolerance = self.config.tf_match_tolerance_s; let lookup = self .tf .lookup(&self.config.world_frame, &msg.header.frame_id) - .at(stamp) - .tolerance(tolerance); + .at(dimos_module::tf::Time { + sec: msg.header.stamp.sec, + nanosec: msg.header.stamp.nanosec, + }); let latest = self .tf .get_latest(&self.config.world_frame, &msg.header.frame_id) - .map(|latest| latest.ts); + .map(|latest| { + latest.header.stamp.sec as f64 + latest.header.stamp.nanosec as f64 * 1e-9 + }); if is_stale(stamp, latest, self.config.max_cloud_age_s) { warn_throttled!(Duration::from_secs(5), cloud_frame = %msg.header.frame_id, "Skipped a cloud older than max_cloud_age_s: the map is behind and catching up."); return; @@ -398,7 +402,7 @@ impl Worker { stamp, world_frame = %self.config.world_frame, cloud_frame = %msg.header.frame_id, - "No transform within tolerance of the cloud stamp, dropped a cloud.", + "TF history cannot resolve the cloud stamp, dropped a cloud.", ); return; }; @@ -706,16 +710,20 @@ async fn publish_bounds(out: &Output, msg: &RegionBounds) { } /// The f32 pose of a transform, for registering clouds. -fn tf_to_pose(t: &Transform) -> Pose { - let translation = t.translation().cast::(); - let rotation = t.rotation().cast::(); +fn tf_to_pose(t: &TransformStamped) -> Pose { + let translation = &t.transform.translation; + let rotation = &t.transform.rotation; Pose { - position: (translation.x, translation.y, translation.z), + position: ( + translation.x as f32, + translation.y as f32, + translation.z as f32, + ), orientation: ( - rotation.coords.x, - rotation.coords.y, - rotation.coords.z, - rotation.coords.w, + rotation.x as f32, + rotation.y as f32, + rotation.z as f32, + rotation.w as f32, ), } } @@ -855,7 +863,12 @@ mod tests { Translation3::new(10.0, 0.0, 0.0), UnitQuaternion::from_axis_angle(&Vector3::z_axis(), std::f64::consts::FRAC_PI_2), ); - let t = Transform::new("odom", "map", 0.0, iso); + let t = dimos_module::tf::from_isometry( + "odom", + "map", + dimos_module::tf::Time { sec: 0, nanosec: 0 }, + iso, + ); let cloud = points_to_cloud(&[3.5, 0.0, 0.5], "map", Time { sec: 0, nanosec: 0 }); let part = prepare_seed(&cloud, tf_to_pose(&t), 1.0, (0.0, 0.0, 0.0), 4.0) diff --git a/dimos/mapping/ray_tracing/rust/src/wire.rs b/dimos/mapping/ray_tracing/rust/src/wire.rs index 7111f015b0a..b00c503fde7 100644 --- a/dimos/mapping/ray_tracing/rust/src/wire.rs +++ b/dimos/mapping/ray_tracing/rust/src/wire.rs @@ -43,29 +43,6 @@ mod tests { use super::*; use dimos_generated_messages::builtin_interfaces::msg::time::Time; use dimos_generated_messages::std_msgs::msg::header::Header; - use dimos_generated_messages::tf2_msgs::msg::tf_message::TFMessage; - use dimos_message_adapters::tf::{decode as decode_tf, encode as encode_tf}; - use dimos_module::cdr; - use dimos_module::nalgebra::Isometry3; - - #[test] - fn tf_cdr_retains_exact_stamps_through_both_wire_orders() { - for ns in [0, -1, 1_700_000_000_123_456_789] { - let transform = dimos_module::tf::Transform::from_nanoseconds( - "odom", - "lidar", - ns, - Isometry3::identity(), - ); - let message: TFMessage = cdr::decode(&encode_tf(&[transform]).unwrap()).unwrap(); - for little in [false, true] { - let decoded = decode_tf(&cdr::encode_endian(&message, little).unwrap()).unwrap(); - assert_eq!(decoded[0].stamp_nanoseconds(), Some(ns)); - let received: TFMessage = cdr::decode(&encode_tf(&decoded).unwrap()).unwrap(); - assert_eq!(received, message); - } - } - } #[test] fn organized_cloud_reader_keeps_endian_and_row_padding_and_filters_missing_points() { diff --git a/dimos/mapping/ray_tracing/test_generated_native.py b/dimos/mapping/ray_tracing/test_generated_native.py index 01bf85bb447..19ca2d53073 100644 --- a/dimos/mapping/ray_tracing/test_generated_native.py +++ b/dimos/mapping/ray_tracing/test_generated_native.py @@ -107,6 +107,7 @@ def test_actual_native_mapper_cdr_registered_clouds_keyed_regions_and_seed_pair( "lidar", "loaded_map", "tf", + "tf_static", "global_map", "local_map", "local_map_fine", @@ -152,6 +153,20 @@ def tf_and_header(): header = Header(frame_id="odom", stamp=time_from_nanoseconds(epoch + sequence)) source_stamps.add(epoch + sequence) sequence += 1 + wires["tf_static"].publish( + TFMessage( + transforms=[ + TransformStamped( + header=Header(frame_id="odom", stamp=time_from_nanoseconds(0)), + child_frame_id="lidar", + transform=Transform( + translation=Vector3(x=0, y=0, z=0), + rotation=Quaternion(x=0, y=0, z=0, w=1), + ), + ) + ] + ) + ) wires["tf"].publish( TFMessage( transforms=[ @@ -163,7 +178,7 @@ def tf_and_header(): rotation=Quaternion(x=0, y=0, z=0, w=1), ), ) - for child, x in [("lidar", 0), ("map", 1)] + for child, x in [("map", 1)] ] ) ) diff --git a/dimos/navigation/global_planner/mls_planner/mls_planner_native.py b/dimos/navigation/global_planner/mls_planner/mls_planner_native.py index b66726a445e..d05a9cb3113 100644 --- a/dimos/navigation/global_planner/mls_planner/mls_planner_native.py +++ b/dimos/navigation/global_planner/mls_planner/mls_planner_native.py @@ -77,6 +77,7 @@ class MLSPlannerNative(NativeModule, spec.GlobalPlanner): seed_bounds: In[RegionBounds] goal: In[PointStamped] tf: IO[TFMessage] + tf_static: In[TFMessage] path: Out[Path] surface_map: Out[PointCloudRegion] diff --git a/dimos/navigation/global_planner/mls_planner/rust/Cargo.lock b/dimos/navigation/global_planner/mls_planner/rust/Cargo.lock index ce61b21662d..48470e51fbe 100644 --- a/dimos/navigation/global_planner/mls_planner/rust/Cargo.lock +++ b/dimos/navigation/global_planner/mls_planner/rust/Cargo.lock @@ -609,22 +609,12 @@ dependencies = [ "tokio", ] -[[package]] -name = "dimos-message-adapters" -version = "0.1.0" -dependencies = [ - "dimos-generated-messages", - "dimos-module", - "nalgebra", -] - [[package]] name = "dimos-mls-planner" version = "0.1.0" dependencies = [ "ahash", "dimos-generated-messages", - "dimos-message-adapters", "dimos-module", "rayon", "serde", @@ -653,6 +643,7 @@ dependencies = [ "cdr", "dimos-lcm", "dimos-module-macros", + "dimos-tf-messages", "lcm-msgs", "nalgebra", "rayon", @@ -661,6 +652,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "transforms", "url", "validator", "zenoh", @@ -676,6 +668,17 @@ dependencies = [ "toml 1.1.6+spec-1.1.0", ] +[[package]] +name = "dimos-tf-messages" +version = "0.1.0" +dependencies = [ + "cdr", + "heapless", + "ros2msg", + "serde", + "serde-big-array", +] + [[package]] name = "dirs" version = "6.0.0" @@ -1057,6 +1060,11 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "heapless" @@ -3431,6 +3439,18 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "transforms" +version = "2.2.0" +source = "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#76cf9022173d5764814544082f2b518a9df1934b" +dependencies = [ + "approx", + "hashbrown 0.17.1", + "libm", + "serde", + "thiserror", +] + [[package]] name = "twox-hash" version = "1.6.3" diff --git a/dimos/navigation/global_planner/mls_planner/rust/Cargo.toml b/dimos/navigation/global_planner/mls_planner/rust/Cargo.toml index 1f09c3be6b0..1c49d50c281 100644 --- a/dimos/navigation/global_planner/mls_planner/rust/Cargo.toml +++ b/dimos/navigation/global_planner/mls_planner/rust/Cargo.toml @@ -29,6 +29,7 @@ seed_map = "dimos_msgs/msg/PointCloudRegion" seed_bounds = "dimos_msgs/msg/RegionBounds" goal = "geometry_msgs/msg/PointStamped" tf = "tf2_msgs/msg/TFMessage" +tf_static = "tf2_msgs/msg/TFMessage" [package.metadata.dimos.module.mls_planner.outputs] surface_map = "dimos_msgs/msg/PointCloudRegion" @@ -37,8 +38,7 @@ node_edges = "dimos_msgs/msg/LineSegments3DRegion" path = "nav_msgs/msg/Path" [dependencies] -dimos-module = { path = "../../../../../native/rust/dimos-module", features = ["cdr"] } -dimos-message-adapters = { path = "../../../../../native/rust/dimos-message-adapters" } +dimos-module = { path = "../../../../../native/rust/dimos-module" } dimos-generated-messages = { path = "../../../../../build/message-source/rust" } tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal", "time"] } serde = { version = "1", features = ["derive"] } diff --git a/dimos/navigation/global_planner/mls_planner/rust/crate-hashes.json b/dimos/navigation/global_planner/mls_planner/rust/crate-hashes.json index ab24c6fabdc..6b69cda334e 100644 --- a/dimos/navigation/global_planner/mls_planner/rust/crate-hashes.json +++ b/dimos/navigation/global_planner/mls_planner/rust/crate-hashes.json @@ -1,5 +1,6 @@ { "git+https://github.com/TomCC7/cdr-rs?rev=38a4368255d408faf374726653b39d4a4e9735cb#cdr@0.2.4": "sha256-akg/bLBY3wQ1YRr2bijE5ZqB211Cst5lKjELLrgiG6o=", + "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#transforms@2.2.0": "sha256-8TdIhfkDahcX5MkLYMbCqaODp0+HHUqJNzyk8K7MEBU=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#dimos-lcm@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#lcm-msgs@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=" } \ No newline at end of file diff --git a/dimos/navigation/global_planner/mls_planner/rust/flake.nix b/dimos/navigation/global_planner/mls_planner/rust/flake.nix index 132117c6844..336bc0f3f72 100644 --- a/dimos/navigation/global_planner/mls_planner/rust/flake.nix +++ b/dimos/navigation/global_planner/mls_planner/rust/flake.nix @@ -31,21 +31,18 @@ cp -r ${moduleSource} $out chmod -R u+w $out mkdir -p $out/sdk - cp -r ${sharedSource}/native/rust/dimos-module ${sharedSource}/native/rust/dimos-module-macros ${sharedSource}/native/rust/dimos-message-adapters $out/sdk/ + cp -r ${sharedSource}/native/rust/dimos-module ${sharedSource}/native/rust/dimos-module-macros ${sharedSource}/native/rust/dimos-tf-messages $out/sdk/ cp -r ${messageSource}/rust $out/messages - substituteInPlace $out/sdk/dimos-message-adapters/Cargo.toml \ - --replace-fail '../../../build/message-source/rust' '../../messages' substituteInPlace $out/Cargo.toml \ --replace-fail '../../../../../native/rust/dimos-module' 'sdk/dimos-module' \ - --replace-fail '../../../../../native/rust/dimos-message-adapters' 'sdk/dimos-message-adapters' \ --replace-fail '../../../../../build/message-source/rust' 'messages' \ --replace-fail '[workspace]' '[workspace] - exclude = ["sdk/dimos-module", "sdk/dimos-module-macros", "sdk/dimos-message-adapters", "messages"]' + exclude = ["sdk/dimos-module", "sdk/dimos-module-macros", "sdk/dimos-tf-messages", "messages"]' ''; generated = crate2nix.tools.${system}.generatedCargoNix { inherit name src; }; - ours = [ name "dimos-module" "dimos-module-macros" "dimos-message-adapters" ]; + ours = [ name "dimos-module" "dimos-module-macros" "dimos-tf-messages" ]; callWith = mode: import generated { inherit pkgs; buildRustCrateForPkgs = cratePkgs: crate: diff --git a/dimos/navigation/global_planner/mls_planner/rust/src/module.rs b/dimos/navigation/global_planner/mls_planner/rust/src/module.rs index 796e3bdfc1d..252dd1812aa 100644 --- a/dimos/navigation/global_planner/mls_planner/rust/src/module.rs +++ b/dimos/navigation/global_planner/mls_planner/rust/src/module.rs @@ -37,7 +37,7 @@ use dimos_generated_messages::{ sensor_msgs::msg::{point_cloud2::PointCloud2, point_field::PointField}, std_msgs::msg::header::Header, }; -use dimos_message_adapters::tf::{decode as decode_tf, encode as encode_tf}; + use dimos_module::cdr; use dimos_module::pointcloud::{extract_xyz_rows, ExtractError}; use dimos_module::{debug_throttled, error_throttled, warn_throttled, Input, Module, Output, Tf}; @@ -261,7 +261,7 @@ pub struct MlsPlanner { #[input(decode = dimos_module::cdr::decode, handler = on_goal)] goal: Input, - #[tf(decode = decode_tf, encode = encode_tf)] + #[tf] tf: Tf, #[output(encode = cdr::encode)] @@ -677,7 +677,8 @@ impl Worker { let t = self .tf .get_latest(&self.config.world_frame, &self.config.base_frame)? - .translation(); + .transform + .translation; Some((t.x as f32, t.y as f32, t.z as f32)) } diff --git a/dimos/navigation/global_planner/mls_planner/test_generated_native.py b/dimos/navigation/global_planner/mls_planner/test_generated_native.py index 68e7c2fd0bd..c64aff1bc9d 100644 --- a/dimos/navigation/global_planner/mls_planner/test_generated_native.py +++ b/dimos/navigation/global_planner/mls_planner/test_generated_native.py @@ -135,6 +135,7 @@ def test_actual_native_mapper_to_mls_cdr_route_and_weighted_viewer_regions(monke "lidar", "loaded_map", "tf", + "tf_static", "global_map", "local_map", "local_map_fine", @@ -153,6 +154,7 @@ def test_actual_native_mapper_to_mls_cdr_route_and_weighted_viewer_regions(monke "seed_bounds", "goal", "tf", + "tf_static", "path", "surface_map", "nodes", diff --git a/dimos/navigation/local_planner/native.py b/dimos/navigation/local_planner/native.py index cea67fc4281..a93df090624 100644 --- a/dimos/navigation/local_planner/native.py +++ b/dimos/navigation/local_planner/native.py @@ -72,6 +72,7 @@ class LocalPlannerNative(NativeModule, spec.MapLocalPlanner): planner_path: In[Path] # IO, not In: rust `#[tf]` subscribes and publishes, and refuses to start on a mismatch. tf: IO[TFMessage] + tf_static: In[TFMessage] path: Out[Path] # The floor voxels the ground plane was fit to, moved onto it. Empty while the body height stands in. diff --git a/dimos/navigation/local_planner/rust/Cargo.lock b/dimos/navigation/local_planner/rust/Cargo.lock index 6e29f0d8cd6..207de17f9bc 100644 --- a/dimos/navigation/local_planner/rust/Cargo.lock +++ b/dimos/navigation/local_planner/rust/Cargo.lock @@ -614,7 +614,6 @@ name = "dimos-local-planner" version = "0.1.0" dependencies = [ "dimos-generated-messages", - "dimos-message-adapters", "dimos-module", "serde", "serde_json", @@ -624,15 +623,6 @@ dependencies = [ "validator", ] -[[package]] -name = "dimos-message-adapters" -version = "0.1.0" -dependencies = [ - "dimos-generated-messages", - "dimos-module", - "nalgebra", -] - [[package]] name = "dimos-module" version = "0.2.0" @@ -640,6 +630,7 @@ dependencies = [ "cdr", "dimos-lcm", "dimos-module-macros", + "dimos-tf-messages", "lcm-msgs", "nalgebra", "rayon", @@ -648,6 +639,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "transforms", "url", "validator", "zenoh", @@ -663,6 +655,17 @@ dependencies = [ "toml 1.1.6+spec-1.1.0", ] +[[package]] +name = "dimos-tf-messages" +version = "0.1.0" +dependencies = [ + "cdr", + "heapless", + "ros2msg", + "serde", + "serde-big-array", +] + [[package]] name = "dirs" version = "6.0.0" @@ -1044,6 +1047,11 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "heapless" @@ -3300,6 +3308,18 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "transforms" +version = "2.2.0" +source = "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#76cf9022173d5764814544082f2b518a9df1934b" +dependencies = [ + "approx", + "hashbrown 0.17.1", + "libm", + "serde", + "thiserror", +] + [[package]] name = "twox-hash" version = "1.6.3" diff --git a/dimos/navigation/local_planner/rust/Cargo.toml b/dimos/navigation/local_planner/rust/Cargo.toml index 9f22124d244..6557c489fc2 100644 --- a/dimos/navigation/local_planner/rust/Cargo.toml +++ b/dimos/navigation/local_planner/rust/Cargo.toml @@ -17,8 +17,7 @@ required-features = ["module"] [dependencies] serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["float_roundtrip"] } -dimos-module = { path = "../../../../native/rust/dimos-module", features = ["cdr"], optional = true } -dimos-message-adapters = { path = "../../../../native/rust/dimos-message-adapters", optional = true } +dimos-module = { path = "../../../../native/rust/dimos-module", optional = true } dimos-generated-messages = { path = "../../../../build/message-source/rust", optional = true } tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal", "time"], optional = true } tracing = { version = "0.1", optional = true } @@ -28,7 +27,7 @@ validator = { version = "0.21", features = ["derive"], optional = true } [features] # Nothing by default: `module` is the native module that runs on the robot. default = [] -module = ["dep:dimos-message-adapters", "dep:dimos-module", "dep:dimos-generated-messages", "dep:tokio", "dep:tracing", "dep:tracing-subscriber", "dep:validator"] +module = ["dep:dimos-module", "dep:dimos-generated-messages", "dep:tokio", "dep:tracing", "dep:tracing-subscriber", "dep:validator"] # `Emb::fixture()`, a test body for this crate and its dependants. test-bodies = [] @@ -46,6 +45,7 @@ threads = 2 local_map = "sensor_msgs/msg/PointCloud2" planner_path = "nav_msgs/msg/Path" tf = "tf2_msgs/msg/TFMessage" +tf_static = "tf2_msgs/msg/TFMessage" [package.metadata.dimos.module.local_planner.outputs] path = "nav_msgs/msg/Path" diff --git a/dimos/navigation/local_planner/rust/crate-hashes.json b/dimos/navigation/local_planner/rust/crate-hashes.json index ab24c6fabdc..6b69cda334e 100644 --- a/dimos/navigation/local_planner/rust/crate-hashes.json +++ b/dimos/navigation/local_planner/rust/crate-hashes.json @@ -1,5 +1,6 @@ { "git+https://github.com/TomCC7/cdr-rs?rev=38a4368255d408faf374726653b39d4a4e9735cb#cdr@0.2.4": "sha256-akg/bLBY3wQ1YRr2bijE5ZqB211Cst5lKjELLrgiG6o=", + "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#transforms@2.2.0": "sha256-8TdIhfkDahcX5MkLYMbCqaODp0+HHUqJNzyk8K7MEBU=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#dimos-lcm@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#lcm-msgs@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=" } \ No newline at end of file diff --git a/dimos/navigation/local_planner/rust/flake.nix b/dimos/navigation/local_planner/rust/flake.nix index 1db44d2afa6..ac781dfe87d 100644 --- a/dimos/navigation/local_planner/rust/flake.nix +++ b/dimos/navigation/local_planner/rust/flake.nix @@ -32,19 +32,16 @@ cp -r ${moduleSource} $out chmod -R u+w $out mkdir -p $out/sdk - cp -r ${sdkSource}/native/rust/dimos-module ${sdkSource}/native/rust/dimos-module-macros ${sdkSource}/native/rust/dimos-message-adapters $out/sdk/ + cp -r ${sdkSource}/native/rust/dimos-module ${sdkSource}/native/rust/dimos-module-macros ${sdkSource}/native/rust/dimos-tf-messages $out/sdk/ cp -r ${messageSource}/rust $out/messages - substituteInPlace $out/sdk/dimos-message-adapters/Cargo.toml \ - --replace-fail '../../../build/message-source/rust' '../../messages' substituteInPlace $out/Cargo.toml \ --replace-fail '../../../../native/rust/dimos-module' 'sdk/dimos-module' \ - --replace-fail '../../../../native/rust/dimos-message-adapters' 'sdk/dimos-message-adapters' \ --replace-fail '../../../../build/message-source/rust' 'messages' ''; generated = crate2nix.tools.${system}.generatedCargoNix { inherit name src; }; - ours = [ name "dimos-module" "dimos-module-macros" "dimos-message-adapters" ]; + ours = [ name "dimos-module" "dimos-module-macros" "dimos-tf-messages" ]; callWith = mode: import generated { inherit pkgs; rootFeatures = if mode == null then [ "module" ] else [ "module" "test-bodies" ]; diff --git a/dimos/navigation/local_planner/rust/src/module/msg.rs b/dimos/navigation/local_planner/rust/src/module/msg.rs index d1b88267047..26705c59dfa 100644 --- a/dimos/navigation/local_planner/rust/src/module/msg.rs +++ b/dimos/navigation/local_planner/rust/src/module/msg.rs @@ -241,7 +241,7 @@ pub fn extract_xyz( #[cfg(test)] mod tests { use super::*; - use dimos_message_adapters::tf::{decode as decode_tf, encode as encode_tf}; + use dimos_module::cdr; use std::f64::consts::PI; @@ -291,48 +291,6 @@ mod tests { let path = build_path(&states, &[], 5.0, "odom", 0.0); assert_eq!(path_stamps(&path), vec![5.0, 5.0]); } - #[test] - fn generated_tf_cdr_round_trip_retains_exact_wire_time() { - use dimos_generated_messages::tf2_msgs::msg::tf_message::TFMessage; - use dimos_module::nalgebra::Isometry3; - for ns in [0, -1, 1_700_000_000_123_456_789] { - let source = dimos_module::Transform::from_nanoseconds( - "world", - "base", - ns, - Isometry3::translation(1., 2., 3.), - ); - let payload = encode_tf(&[source]).unwrap(); - let value: TFMessage = cdr::decode(&payload).unwrap(); - assert_eq!(nanoseconds(&value.transforms[0].header.stamp), ns); - assert_eq!(value.transforms[0].header.frame_id, "world"); - for little in [false, true] { - let received = decode_tf(&cdr::encode_endian(&value, little).unwrap()).unwrap(); - assert_eq!(received[0].stamp_nanoseconds(), Some(ns)); - assert_eq!(received[0].translation().x, 1.); - } - } - } - - #[test] - fn tf_codec_rejects_invalid_packets_and_ros_time() { - use dimos_generated_messages::tf2_msgs::msg::tf_message::TFMessage; - use dimos_module::nalgebra::Isometry3; - let payload = encode_tf(&[dimos_module::Transform::from_nanoseconds( - "a", - "b", - 0, - Isometry3::identity(), - )]) - .unwrap(); - let mut message: TFMessage = cdr::decode(&payload).unwrap(); - message.transforms[0].header.stamp.nanosec = 1_000_000_000; - assert!(decode_tf(&cdr::encode(&message).unwrap()).is_err()); - assert!(decode_tf(&[0, 3, 0, 0]).is_err()); - let mut trailing = payload; - trailing.push(0); - assert!(decode_tf(&trailing).is_err()); - } #[test] fn generated_path_codec_and_relative_profile_keep_nanosecond_differences() { diff --git a/dimos/navigation/local_planner/rust/src/module/planner.rs b/dimos/navigation/local_planner/rust/src/module/planner.rs index 0eb35a1cb99..85d3923d5fc 100644 --- a/dimos/navigation/local_planner/rust/src/module/planner.rs +++ b/dimos/navigation/local_planner/rust/src/module/planner.rs @@ -118,7 +118,7 @@ pub struct LocalPlanner { #[config] config: Config, - #[tf(decode = dimos_message_adapters::tf::decode, encode = dimos_message_adapters::tf::encode)] + #[tf] tf: Tf, shared: Arc>, diff --git a/dimos/navigation/local_planner/rust/src/module/tf_pose.rs b/dimos/navigation/local_planner/rust/src/module/tf_pose.rs index 273451f686f..b8ae3537237 100644 --- a/dimos/navigation/local_planner/rust/src/module/tf_pose.rs +++ b/dimos/navigation/local_planner/rust/src/module/tf_pose.rs @@ -18,8 +18,8 @@ use std::time::Instant; -use dimos_module::nalgebra::{Isometry3, Translation3}; -use dimos_module::{Tf, Transform}; +use dimos_module::nalgebra::Isometry3; +use dimos_module::{Tf, TransformStamped}; use crate::module::msg::{yaw_of, State}; @@ -90,10 +90,10 @@ impl PoseWatch { } } -fn edge_of(t: Transform) -> Option<(i64, Isometry3)> { +fn edge_of(t: TransformStamped) -> Option<(i64, Isometry3)> { Some(( - t.stamp_nanoseconds()?, - Isometry3::from_parts(Translation3::from(t.translation()), t.rotation()), + dimos_module::tf::nanoseconds(&t.header.stamp).ok()?, + dimos_module::tf::isometry(&t).ok()?, )) } @@ -113,7 +113,7 @@ pub fn state_of(iso: &Isometry3) -> State { #[cfg(test)] mod tests { use super::*; - use dimos_module::nalgebra::UnitQuaternion; + use dimos_module::nalgebra::{Translation3, UnitQuaternion}; use std::time::Duration; fn body_at(x: f64, yaw: f64, ts: f64) -> Option<(f64, Isometry3)> { @@ -197,14 +197,24 @@ mod tests { let mut watch = PoseWatch::new(2.5); let now = Instant::now(); let ns = 1_700_000_000_123_456_789; - let first = Transform::from_nanoseconds("world", "base", ns, Isometry3::identity()); + let first = dimos_module::tf::from_isometry( + "world", + "base", + dimos_module::tf::time_from_nanoseconds(ns).unwrap(), + Isometry3::identity(), + ); assert!(watch .observe_nanoseconds(edge_of(first.clone()), now) .is_some()); assert!(watch .observe_nanoseconds(edge_of(first), now + Duration::from_secs(3)) .is_none()); - let fresh = Transform::from_nanoseconds("world", "base", ns + 1, Isometry3::identity()); + let fresh = dimos_module::tf::from_isometry( + "world", + "base", + dimos_module::tf::time_from_nanoseconds(ns + 1).unwrap(), + Isometry3::identity(), + ); assert!(watch .observe_nanoseconds(edge_of(fresh), now + Duration::from_secs(3)) .is_some()); diff --git a/dimos/navigation/local_planner/test_generated_native.py b/dimos/navigation/local_planner/test_generated_native.py index a4cecf682b0..922f23c82ec 100644 --- a/dimos/navigation/local_planner/test_generated_native.py +++ b/dimos/navigation/local_planner/test_generated_native.py @@ -103,7 +103,7 @@ def test_actual_native_planner_consumes_python_cdr_and_returns_canonical_path(mo session=session, ) wires = {} - for name in ["local_map", "planner_path", "tf", "path", "ground_support"]: + for name in ["local_map", "planner_path", "tf", "tf_static", "path", "ground_support"]: port = getattr(module, name) wire = ZenohTransport( ZenohTopic("native/planner/" + name, port.type), **session.model_dump() diff --git a/dimos/navigation/trajectory_follower/fancy/native.py b/dimos/navigation/trajectory_follower/fancy/native.py index f19fe0a1522..ab4eb90d985 100644 --- a/dimos/navigation/trajectory_follower/fancy/native.py +++ b/dimos/navigation/trajectory_follower/fancy/native.py @@ -70,6 +70,7 @@ class TrajectoryFollowerNative(NativeModule, spec.TrajectoryFollower): path: In[Path] tf: IO[TFMessage] # IO, not In: see planner_native.py + tf_static: In[TFMessage] nav_cmd_vel: Out[Twist] goal_reached: Out[Bool] diff --git a/dimos/navigation/trajectory_follower/fancy/rust/Cargo.lock b/dimos/navigation/trajectory_follower/fancy/rust/Cargo.lock index 03b55adeb8c..a1df25c0bf1 100644 --- a/dimos/navigation/trajectory_follower/fancy/rust/Cargo.lock +++ b/dimos/navigation/trajectory_follower/fancy/rust/Cargo.lock @@ -614,7 +614,6 @@ name = "dimos-local-planner" version = "0.1.0" dependencies = [ "dimos-generated-messages", - "dimos-message-adapters", "dimos-module", "serde", "serde_json", @@ -624,15 +623,6 @@ dependencies = [ "validator", ] -[[package]] -name = "dimos-message-adapters" -version = "0.1.0" -dependencies = [ - "dimos-generated-messages", - "dimos-module", - "nalgebra", -] - [[package]] name = "dimos-module" version = "0.2.0" @@ -640,6 +630,7 @@ dependencies = [ "cdr", "dimos-lcm", "dimos-module-macros", + "dimos-tf-messages", "lcm-msgs", "nalgebra", "rayon", @@ -648,6 +639,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "transforms", "url", "validator", "zenoh", @@ -663,13 +655,23 @@ dependencies = [ "toml 1.1.6+spec-1.1.0", ] +[[package]] +name = "dimos-tf-messages" +version = "0.1.0" +dependencies = [ + "cdr", + "heapless", + "ros2msg", + "serde", + "serde-big-array", +] + [[package]] name = "dimos-trajectory-follower" version = "0.1.0" dependencies = [ "dimos-generated-messages", "dimos-local-planner", - "dimos-message-adapters", "dimos-module", "numpy", "pyo3", @@ -1062,6 +1064,11 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "heapless" @@ -3435,6 +3442,18 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "transforms" +version = "2.2.0" +source = "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#76cf9022173d5764814544082f2b518a9df1934b" +dependencies = [ + "approx", + "hashbrown 0.17.1", + "libm", + "serde", + "thiserror", +] + [[package]] name = "twox-hash" version = "1.6.3" diff --git a/dimos/navigation/trajectory_follower/fancy/rust/Cargo.toml b/dimos/navigation/trajectory_follower/fancy/rust/Cargo.toml index 2275a85b8a8..1c77a3415d4 100644 --- a/dimos/navigation/trajectory_follower/fancy/rust/Cargo.toml +++ b/dimos/navigation/trajectory_follower/fancy/rust/Cargo.toml @@ -20,8 +20,7 @@ required-features = ["module"] # The body (`Emb`) the laws are parameterised from; python feature off, see adapter. dimos-local-planner = { path = "../../../local_planner/rust", default-features = false } serde = { version = "1", features = ["derive"], optional = true } -dimos-module = { path = "../../../../../native/rust/dimos-module", features = ["cdr"], optional = true } -dimos-message-adapters = { path = "../../../../../native/rust/dimos-message-adapters", optional = true } +dimos-module = { path = "../../../../../native/rust/dimos-module", optional = true } dimos-generated-messages = { path = "../../../../../build/message-source/rust", optional = true } tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal", "time"], optional = true } tracing = { version = "0.1", optional = true } @@ -36,7 +35,7 @@ serde_json = { version = "1", features = ["float_roundtrip"], optional = true } # Python; maturin builds with defaults and gets the extension module. default = [] python = ["dep:pyo3", "dep:numpy", "dep:serde_json"] -module = ["dep:dimos-message-adapters", "dimos-local-planner/module", "dep:serde", "dep:dimos-module", "dep:dimos-generated-messages", "dep:tokio", "dep:tracing", "dep:tracing-subscriber", "dep:validator"] +module = ["dimos-local-planner/module", "dep:serde", "dep:dimos-module", "dep:dimos-generated-messages", "dep:tokio", "dep:tracing", "dep:tracing-subscriber", "dep:validator"] # `cargo test --features module` also runs the module's own tests. [dev-dependencies] @@ -51,6 +50,7 @@ threads = 2 [package.metadata.dimos.module.trajectory_follower.inputs] path = "nav_msgs/msg/Path" tf = "tf2_msgs/msg/TFMessage" +tf_static = "tf2_msgs/msg/TFMessage" [package.metadata.dimos.module.trajectory_follower.outputs] nav_cmd_vel = "geometry_msgs/msg/Twist" diff --git a/dimos/navigation/trajectory_follower/fancy/rust/crate-hashes.json b/dimos/navigation/trajectory_follower/fancy/rust/crate-hashes.json index ab24c6fabdc..6b69cda334e 100644 --- a/dimos/navigation/trajectory_follower/fancy/rust/crate-hashes.json +++ b/dimos/navigation/trajectory_follower/fancy/rust/crate-hashes.json @@ -1,5 +1,6 @@ { "git+https://github.com/TomCC7/cdr-rs?rev=38a4368255d408faf374726653b39d4a4e9735cb#cdr@0.2.4": "sha256-akg/bLBY3wQ1YRr2bijE5ZqB211Cst5lKjELLrgiG6o=", + "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#transforms@2.2.0": "sha256-8TdIhfkDahcX5MkLYMbCqaODp0+HHUqJNzyk8K7MEBU=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#dimos-lcm@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#lcm-msgs@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=" } \ No newline at end of file diff --git a/dimos/navigation/trajectory_follower/fancy/rust/flake.nix b/dimos/navigation/trajectory_follower/fancy/rust/flake.nix index e7ada378e0d..f1109d04bb1 100644 --- a/dimos/navigation/trajectory_follower/fancy/rust/flake.nix +++ b/dimos/navigation/trajectory_follower/fancy/rust/flake.nix @@ -32,26 +32,22 @@ chmod -R u+w $out mkdir -p $out/sdk cp -r ${plannerSource}/dimos/navigation/local_planner/rust $out/local-planner - cp -r ${plannerSource}/native/rust/dimos-module ${plannerSource}/native/rust/dimos-module-macros ${plannerSource}/native/rust/dimos-message-adapters $out/sdk/ + cp -r ${plannerSource}/native/rust/dimos-module ${plannerSource}/native/rust/dimos-module-macros ${plannerSource}/native/rust/dimos-tf-messages $out/sdk/ cp -r ${messageSource}/rust $out/messages - substituteInPlace $out/sdk/dimos-message-adapters/Cargo.toml \ - --replace-fail '../../../build/message-source/rust' '../../messages' # The source artifacts own workspace roots; do not make them automatic members. substituteInPlace $out/Cargo.toml --replace-fail '[workspace]' '[workspace] - exclude = ["local-planner", "sdk/dimos-module", "sdk/dimos-module-macros", "sdk/dimos-message-adapters", "messages"]' + exclude = ["local-planner", "sdk/dimos-module", "sdk/dimos-module-macros", "sdk/dimos-tf-messages", "messages"]' substituteInPlace $out/Cargo.toml \ --replace-fail '../../../local_planner/rust' 'local-planner' \ --replace-fail '../../../../../native/rust/dimos-module' 'sdk/dimos-module' \ - --replace-fail '../../../../../native/rust/dimos-message-adapters' 'sdk/dimos-message-adapters' \ --replace-fail '../../../../../build/message-source/rust' 'messages' substituteInPlace $out/local-planner/Cargo.toml \ --replace-fail '../../../../native/rust/dimos-module' '../sdk/dimos-module' \ - --replace-fail '../../../../native/rust/dimos-message-adapters' '../sdk/dimos-message-adapters' \ --replace-fail '../../../../build/message-source/rust' '../messages' ''; generated = crate2nix.tools.${system}.generatedCargoNix { inherit name src; }; - ours = [ name "dimos-local-planner" "dimos-module" "dimos-module-macros" "dimos-message-adapters" ]; + ours = [ name "dimos-local-planner" "dimos-module" "dimos-module-macros" "dimos-tf-messages" ]; callWith = mode: import generated { inherit pkgs; rootFeatures = [ "module" ]; diff --git a/dimos/navigation/trajectory_follower/fancy/rust/src/module/follower.rs b/dimos/navigation/trajectory_follower/fancy/rust/src/module/follower.rs index cb79fc24736..d39c65ba8c4 100644 --- a/dimos/navigation/trajectory_follower/fancy/rust/src/module/follower.rs +++ b/dimos/navigation/trajectory_follower/fancy/rust/src/module/follower.rs @@ -130,7 +130,7 @@ pub struct TrajectoryFollower { #[config] config: Config, - #[tf(decode = dimos_message_adapters::tf::decode, encode = dimos_message_adapters::tf::encode)] + #[tf] tf: Tf, shared: Arc>, diff --git a/dimos/perception/depth2depth_cloud/module.py b/dimos/perception/depth2depth_cloud/module.py index 917a3ef2b6c..a0d08425971 100644 --- a/dimos/perception/depth2depth_cloud/module.py +++ b/dimos/perception/depth2depth_cloud/module.py @@ -54,7 +54,6 @@ class Depth2DepthCloudConfig(NativeModuleConfig): world_frame: str = "odom" lidar_history_s: float = Field(default=2.0, ge=0.0, le=30.0) max_anchor_range_m: float = Field(default=12.0, ge=0.1, le=200.0) - tf_tolerance_s: float = Field(default=0.1, ge=0.0, le=5.0) # Frames and scans wait this long for their transform before they are dropped. max_tf_lag_s: float = Field(default=0.5, ge=0.0, le=2.0) # Calibration (depth2depth::CalibrationConfig): edge-aware spread near lidar, a smooth fit away from it. @@ -112,6 +111,7 @@ class Depth2DepthCloud(NativeModule): camera_info: In[CameraInfo] lidar: In[PointCloud2] tf: In[TFMessage] + tf_static: In[TFMessage] depth_cloud: Out[PointCloud2] diff --git a/dimos/perception/depth2depth_cloud/rust/Cargo.lock b/dimos/perception/depth2depth_cloud/rust/Cargo.lock index 9313e2b0863..3ad4ad7a7c7 100644 --- a/dimos/perception/depth2depth_cloud/rust/Cargo.lock +++ b/dimos/perception/depth2depth_cloud/rust/Cargo.lock @@ -841,7 +841,6 @@ version = "0.1.0" dependencies = [ "depth2depth", "dimos-generated-messages", - "dimos-message-adapters", "dimos-module", "nalgebra", "rayon", @@ -873,15 +872,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "dimos-message-adapters" -version = "0.1.0" -dependencies = [ - "dimos-generated-messages", - "dimos-module", - "nalgebra", -] - [[package]] name = "dimos-module" version = "0.2.0" @@ -889,6 +879,7 @@ dependencies = [ "cdr", "dimos-lcm", "dimos-module-macros", + "dimos-tf-messages", "lcm-msgs", "nalgebra", "rayon", @@ -897,6 +888,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "transforms", "url", "validator", "zenoh", @@ -912,6 +904,17 @@ dependencies = [ "toml 1.1.4+spec-1.1.0", ] +[[package]] +name = "dimos-tf-messages" +version = "0.1.0" +dependencies = [ + "cdr", + "heapless", + "ros2msg", + "serde", + "serde-big-array", +] + [[package]] name = "dirs" version = "6.0.0" @@ -1697,6 +1700,11 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "heapless" @@ -4433,6 +4441,18 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "transforms" +version = "2.2.0" +source = "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#76cf9022173d5764814544082f2b518a9df1934b" +dependencies = [ + "approx", + "hashbrown 0.17.1", + "libm", + "serde", + "thiserror 2.0.20", +] + [[package]] name = "turbojpeg" version = "1.5.1" diff --git a/dimos/perception/depth2depth_cloud/rust/Cargo.toml b/dimos/perception/depth2depth_cloud/rust/Cargo.toml index e569e18ec0d..db07f0f6afe 100644 --- a/dimos/perception/depth2depth_cloud/rust/Cargo.toml +++ b/dimos/perception/depth2depth_cloud/rust/Cargo.toml @@ -25,13 +25,13 @@ image = "sensor_msgs/msg/CompressedImage" camera_info = "sensor_msgs/msg/CameraInfo" lidar = "sensor_msgs/msg/PointCloud2" tf = "tf2_msgs/msg/TFMessage" +tf_static = "tf2_msgs/msg/TFMessage" [package.metadata.dimos.module.depth2depth_cloud.outputs] depth_cloud = "sensor_msgs/msg/PointCloud2" [dependencies] -dimos-module = { path = "../../../../native/rust/dimos-module", features = ["cdr"] } -dimos-message-adapters = { path = "../../../../native/rust/dimos-message-adapters" } +dimos-module = { path = "../../../../native/rust/dimos-module" } dimos-generated-messages = { path = "../../../../build/message-source/rust" } tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal"] } serde = { version = "1", features = ["derive"] } diff --git a/dimos/perception/depth2depth_cloud/rust/crate-hashes.json b/dimos/perception/depth2depth_cloud/rust/crate-hashes.json index ab24c6fabdc..6b69cda334e 100644 --- a/dimos/perception/depth2depth_cloud/rust/crate-hashes.json +++ b/dimos/perception/depth2depth_cloud/rust/crate-hashes.json @@ -1,5 +1,6 @@ { "git+https://github.com/TomCC7/cdr-rs?rev=38a4368255d408faf374726653b39d4a4e9735cb#cdr@0.2.4": "sha256-akg/bLBY3wQ1YRr2bijE5ZqB211Cst5lKjELLrgiG6o=", + "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#transforms@2.2.0": "sha256-8TdIhfkDahcX5MkLYMbCqaODp0+HHUqJNzyk8K7MEBU=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#dimos-lcm@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=", "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#lcm-msgs@0.1.0": "sha256-GGkx4Mn6NYP6KZecmoRLKGWIih/+y8OgNn12DeXX6n8=" } \ No newline at end of file diff --git a/dimos/perception/depth2depth_cloud/rust/flake.nix b/dimos/perception/depth2depth_cloud/rust/flake.nix index 619295354a9..8f88ad56621 100644 --- a/dimos/perception/depth2depth_cloud/rust/flake.nix +++ b/dimos/perception/depth2depth_cloud/rust/flake.nix @@ -50,20 +50,17 @@ cp -r ${moduleSource} $out chmod -R u+w $out mkdir -p $out/sdk - cp -r ${sharedSource}/native/rust/dimos-module ${sharedSource}/native/rust/dimos-module-macros ${sharedSource}/native/rust/dimos-message-adapters $out/sdk/ + cp -r ${sharedSource}/native/rust/dimos-module ${sharedSource}/native/rust/dimos-module-macros ${sharedSource}/native/rust/dimos-tf-messages $out/sdk/ cp -r ${messageSource}/rust $out/messages - substituteInPlace $out/sdk/dimos-message-adapters/Cargo.toml \ - --replace-fail '../../../build/message-source/rust' '../../messages' substituteInPlace $out/Cargo.toml --replace-fail '[workspace]' '[workspace] - exclude = ["sdk/dimos-module", "sdk/dimos-module-macros", "sdk/dimos-message-adapters", "messages"]' + exclude = ["sdk/dimos-module", "sdk/dimos-module-macros", "sdk/dimos-tf-messages", "messages"]' substituteInPlace $out/Cargo.toml \ --replace-fail '../../../../native/rust/dimos-module' 'sdk/dimos-module' \ - --replace-fail '../../../../native/rust/dimos-message-adapters' 'sdk/dimos-message-adapters' \ --replace-fail '../../../../build/message-source/rust' 'messages' ''; generated = crate2nix.tools.${system}.generatedCargoNix { inherit name src; }; - ours = [ name "dimos-module" "dimos-module-macros" "dimos-message-adapters" ]; + ours = [ name "dimos-module" "dimos-module-macros" "dimos-tf-messages" ]; build = mode: features: (import generated { inherit pkgs; rootFeatures = [ "default" ] ++ features; diff --git a/dimos/perception/depth2depth_cloud/rust/src/module.rs b/dimos/perception/depth2depth_cloud/rust/src/module.rs index e6a7e9f4e1a..f7f1bc83f62 100644 --- a/dimos/perception/depth2depth_cloud/rust/src/module.rs +++ b/dimos/perception/depth2depth_cloud/rust/src/module.rs @@ -37,7 +37,7 @@ use dimos_generated_messages::sensor_msgs::msg::compressed_image::CompressedImag use dimos_generated_messages::sensor_msgs::msg::point_cloud2::PointCloud2; use dimos_generated_messages::sensor_msgs::msg::point_field::PointField; use dimos_generated_messages::std_msgs::msg::header::Header; -use dimos_message_adapters::tf::{decode as decode_tf, encode as encode_tf}; + use dimos_module::cdr; use dimos_module::pointcloud::{extract_xyz_rows, ExtractError}; use dimos_module::{native_config, warn_throttled, Input, Module, Output, Tf}; @@ -101,9 +101,6 @@ pub struct Config { /// Lidar points farther than this from the camera are not anchors. #[validate(range(min = 0.1, max = 200.0))] max_anchor_range_m: f64, - /// Largest gap between a stamp and the transform used for it. - #[validate(range(min = 0.0, max = 5.0))] - tf_tolerance_s: f64, /// Frames and scans wait this long for their transform before they are dropped. #[validate(range(min = 0.0, max = 2.0))] max_tf_lag_s: f64, @@ -157,7 +154,7 @@ pub struct Depth2DepthCloud { #[input(decode = cdr::decode, handler = on_lidar)] lidar: Input, - #[tf(decode = decode_tf, encode = encode_tf)] + #[tf] tf: Tf, #[output(encode = cdr::encode)] @@ -379,7 +376,13 @@ impl Worker { let newest = self.shared.frames.lock().unwrap().back().map(|image| { let frame_id = resolve_frame_id(&cfg.frame_id, &info.header.frame_id, &image.header.frame_id); - (frame_id.to_string(), seconds(&image.header.stamp)) + ( + frame_id.to_string(), + dimos_module::tf::Time { + sec: image.header.stamp.sec, + nanosec: image.header.stamp.nanosec, + }, + ) }); let Some((frame_id, stamp)) = newest else { frame_arrived.await; @@ -388,13 +391,13 @@ impl Worker { let wait = Duration::from_secs_f64(cfg.max_tf_lag_s); let lookup = |target: &str| { let tf = self.tf.clone(); - let (target, frame_id) = (target.to_string(), frame_id.clone()); + let (target, frame_id, stamp) = + (target.to_string(), frame_id.clone(), stamp.clone()); async move { target.is_empty() || tf .lookup(&target, &frame_id) - .at(stamp) - .tolerance(cfg.tf_tolerance_s) + .at(stamp.clone()) .within(wait) .await .is_some() @@ -411,7 +414,7 @@ impl Worker { .frames .lock() .unwrap() - .retain(|image| seconds(&image.header.stamp) > stamp); + .retain(|image| (image.header.stamp.sec, image.header.stamp.nanosec) > (stamp.sec, stamp.nanosec)); } } } @@ -586,18 +589,22 @@ impl Worker { scan_arrived.await; continue; }; - let stamp = seconds(&msg.header.stamp); + let query_stamp = dimos_module::tf::Time { + sec: msg.header.stamp.sec, + nanosec: msg.header.stamp.nanosec, + }; let Some(world_from_lidar) = self .tf .lookup(&cfg.world_frame, &msg.header.frame_id) - .at(stamp) - .tolerance(cfg.tf_tolerance_s) + .at(query_stamp) .within(Duration::from_secs_f64(cfg.max_tf_lag_s)) .await else { continue; }; - let pose = isometry(&world_from_lidar); + let Ok(pose) = dimos_module::tf::isometry(&world_from_lidar) else { + continue; + }; let points = match extract_xyz(&msg) { Ok(points) => points, Err(error) => { @@ -613,6 +620,7 @@ impl Worker { [p.x as f32, p.y as f32, p.z as f32] }) .collect(); + let stamp = seconds(&msg.header.stamp); let mut history = self.shared.history.lock().unwrap(); history.push_back(Scan { stamp, points }); let newest = history.iter().map(|scan| scan.stamp).fold(stamp, f64::max); @@ -630,7 +638,13 @@ impl Worker { &info.header.frame_id, &image.header.frame_id, ); - let poses = self.poses(frame_id, seconds(&image.header.stamp))?; + let poses = self.poses( + frame_id, + dimos_module::tf::Time { + sec: image.header.stamp.sec, + nanosec: image.header.stamp.nanosec, + }, + )?; Some((i, (frame_id.to_string(), poses))) })?; let image = frames.drain(..=index).next_back()?; @@ -642,15 +656,10 @@ impl Worker { }) } - fn poses(&self, frame_id: &str, stamp: f64) -> Option { + fn poses(&self, frame_id: &str, stamp: dimos_module::tf::Time) -> Option { let pose = |target: &str| { - let transform = self - .tf - .lookup(target, frame_id) - .at(stamp) - .tolerance(self.config.tf_tolerance_s) - .get()?; - Some(isometry(&transform)) + let transform = self.tf.lookup(target, frame_id).at(stamp.clone()).get()?; + dimos_module::tf::isometry(&transform).ok() }; let optional = |target: &str| match target { "" => Some(None), @@ -765,10 +774,6 @@ fn make_cloud(points: &[[f32; 3]], source: &Header, frame_id: String) -> PointCl } } -fn isometry(transform: &dimos_module::tf::Transform) -> Isometry3 { - Isometry3::from_parts(transform.translation().into(), transform.rotation()) -} - /// A configured size, or the derived one when it is 0. fn or_derived(configured: usize, derived: usize) -> usize { if configured > 0 { @@ -874,52 +879,6 @@ mod tests { } } - #[test] - fn cdr_tf_adapter_preserves_frames_and_rejects_wrong_encoding() { - let transform = dimos_module::tf::Transform::new( - "world", - "camera", - -0.25, - Isometry3::translation(1., 2., 3.), - ); - let decoded = decode_tf(&encode_tf(&[transform]).unwrap()).unwrap(); - assert_eq!(decoded.len(), 1); - assert_eq!(decoded[0].parent, "world"); - assert_eq!(decoded[0].child, "camera"); - assert_eq!(decoded[0].ts, -0.25); - assert_eq!(decoded[0].translation(), nalgebra::Vector3::new(1., 2., 3.)); - assert!(decode_tf(&[0, 3, 0, 0]).is_err()); - } - - #[test] - fn tf_cdr_source_stamps_survive_epoch_nanoseconds_and_negative_times() { - use dimos_generated_messages::tf2_msgs::msg::tf_message::TFMessage; - for ns in [0, -1, 1_700_000_000_123_456_789] { - let value = dimos_module::tf::Transform::from_nanoseconds( - "world", - "camera", - ns, - Isometry3::translation(1., 2., 3.), - ); - let message: TFMessage = cdr::decode(&encode_tf(&[value]).unwrap()).unwrap(); - assert_eq!( - message.transforms[0].header.stamp.sec as i64, - ns.div_euclid(1_000_000_000) - ); - assert_eq!( - message.transforms[0].header.stamp.nanosec as i64, - ns.rem_euclid(1_000_000_000) - ); - for little in [false, true] { - let bytes = cdr::encode_endian(&message, little).unwrap(); - let decoded = decode_tf(&bytes).unwrap(); - assert_eq!(decoded[0].stamp_nanoseconds(), Some(ns)); - let output: TFMessage = cdr::decode(&encode_tf(&decoded).unwrap()).unwrap(); - assert_eq!(output, message); - } - } - } - #[test] fn a_stage_behind_takes_the_newest_item_and_counts_the_ones_it_missed() { let latest = Latest::default(); diff --git a/native/rust/dimos-message-adapters/Cargo.lock b/native/rust/dimos-message-adapters/Cargo.lock deleted file mode 100644 index 43682952e50..00000000000 --- a/native/rust/dimos-message-adapters/Cargo.lock +++ /dev/null @@ -1,4447 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "advisory-lock" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6caee7d48f930f9ad3fc9546f8cbf843365da0c5b0ca4eee1d1ac3dd12d8f93" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures 0.2.17", -] - -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "getrandom 0.3.4", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "android_system_properties" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" - -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arc-swap" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" -dependencies = [ - "rustversion", -] - -[[package]] -name = "array-init" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" - -[[package]] -name = "asn1-rs" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f43a50ac4fdca5df8e885c21b835997f0a1cdee65494a6847694a98652d9d8" -dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror", - "time", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", - "synstructure 0.13.2", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "async-trait" -version = "0.1.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "autocfg" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" - -[[package]] -name = "bit-vec" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" -dependencies = [ - "serde_core", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bs58" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "buddy_system_allocator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7913f22349ffcfc6ca0ca9a656ec26cfbba538ed49c31a273dff2c5d1ea83d9" -dependencies = [ - "spin 0.9.9", -] - -[[package]] -name = "bumpalo" -version = "3.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" - -[[package]] -name = "bytemuck" -version = "1.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" - -[[package]] -name = "cc" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877bf67ac8e52449eb2f9e98a344ea163beb70dd1f9eebe3cc5357dcfeaee4df" -dependencies = [ - "find-msvc-tools", - "shlex", -] - -[[package]] -name = "cdr" -version = "0.2.4" -source = "git+https://github.com/TomCC7/cdr-rs?rev=38a4368255d408faf374726653b39d4a4e9735cb#38a4368255d408faf374726653b39d4a4e9735cb" -dependencies = [ - "byteorder", - "serde", -] - -[[package]] -name = "cfg-if" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "cfg_aliases" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" - -[[package]] -name = "chacha20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.1", - "rand_core 0.10.1", -] - -[[package]] -name = "chrono" -version = "0.4.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" -dependencies = [ - "iana-time-zone", - "num-traits", - "serde", - "windows-link", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "combine" -version = "4.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "const_format" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" -dependencies = [ - "const_format_proc_macros", - "konst", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e71406cd8807725f7ac2f999a4cdd32e98f829fdf65f528343cebf945e41df1e" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e8bd762f7479489c70ed6c768ddca99d7296857de437a68dcb2a94365b3fae" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" - -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "darling" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" -dependencies = [ - "darling_core 0.23.0", - "darling_macro 0.23.0", -] - -[[package]] -name = "darling" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" -dependencies = [ - "darling_core 0.24.1", - "darling_macro 0.24.1", -] - -[[package]] -name = "darling_core" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" -dependencies = [ - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.119", -] - -[[package]] -name = "darling_core" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" -dependencies = [ - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 3.0.9", -] - -[[package]] -name = "darling_macro" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" -dependencies = [ - "darling_core 0.23.0", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "darling_macro" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" -dependencies = [ - "darling_core 0.24.1", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "data-encoding" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" - -[[package]] -name = "defmt" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" -dependencies = [ - "bitflags 1.3.2", - "defmt-macros", -] - -[[package]] -name = "defmt-macros" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" -dependencies = [ - "defmt-parser", - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "defmt-parser" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" -dependencies = [ - "thiserror", -] - -[[package]] -name = "der-parser" -version = "10.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - -[[package]] -name = "deranged" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "serde_core", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", -] - -[[package]] -name = "dimos-generated-messages" -version = "0.0.14" -dependencies = [ - "cdr", - "heapless", - "ros2msg", - "serde", - "serde-big-array", -] - -[[package]] -name = "dimos-lcm" -version = "0.1.0" -source = "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#04d78e8622500244123ba9cefa4c51b4cb454549" -dependencies = [ - "byteorder", - "socket2 0.5.10", - "tokio", -] - -[[package]] -name = "dimos-message-adapters" -version = "0.1.0" -dependencies = [ - "dimos-generated-messages", - "dimos-module", - "nalgebra", -] - -[[package]] -name = "dimos-module" -version = "0.2.0" -dependencies = [ - "cdr", - "dimos-lcm", - "dimos-module-macros", - "lcm-msgs", - "nalgebra", - "rayon", - "serde", - "serde_json", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "validator", - "zenoh", -] - -[[package]] -name = "dimos-module-macros" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", - "toml 1.1.6+spec-1.1.0", -] - -[[package]] -name = "dirs" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.61.2", -] - -[[package]] -name = "displaydoc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "dtoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" - -[[package]] -name = "dyn-clone" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - -[[package]] -name = "either" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "event-listener" -version = "5.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" -dependencies = [ - "parking", - "pin-project-lite", -] - -[[package]] -name = "fastbloom" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef975e30683b2d965054bb0a836f8973857c4ebf6acf274fe46617cd285060d8" -dependencies = [ - "foldhash 0.2.0", - "libm", - "portable-atomic", - "siphasher", -] - -[[package]] -name = "fastrand" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" - -[[package]] -name = "find-msvc-tools" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c66915cc5391097de7a2b0b972e8505aa33c0df401fd3a6811dbdb32881ba48" - -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - -[[package]] -name = "flate2" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" -dependencies = [ - "crc32fast", - "miniz_oxide", - "zlib-rs", -] - -[[package]] -name = "flume" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "spin 0.9.9", -] - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foldhash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" - -[[package]] -name = "futures-executor" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" - -[[package]] -name = "futures-macro" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "futures-sink" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" - -[[package]] -name = "futures-task" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" - -[[package]] -name = "futures-util" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi 5.3.0", - "wasip2", -] - -[[package]] -name = "getrandom" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi 6.0.0", - "rand_core 0.10.1", - "wasm-bindgen", -] - -[[package]] -name = "git-version" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad568aa3db0fcbc81f2f116137f263d7304f512a1209b35b85150d3ef88ad19" -dependencies = [ - "git-version-macro", -] - -[[package]] -name = "git-version-macro" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "glam" -version = "0.30.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9" - -[[package]] -name = "glam" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556f6b2ea90b8d15a74e0e7bb41671c9bdf38cd9f78c284d750b9ce58a2b5be7" - -[[package]] -name = "glam" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f70749695b063ecbf6b62949ccccde2e733ec3ecbbd71d467dca4e5c6c97cca0" - -[[package]] -name = "glam" -version = "0.33.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e762b9b188634fc508d4ec54b62ea3d352c43fd431d18d05d46f559f217f4725" - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", -] - -[[package]] -name = "hashbrown" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32", - "serde", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "home" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "humantime" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15cdd26707701c53297e2fa6afb323d55fbc1d0810c3aec078ae3ef0424c3c15" - -[[package]] -name = "iana-time-zone" -version = "0.1.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" -dependencies = [ - "displaydoc", - "potential_utf", - "utf8_iter", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" - -[[package]] -name = "icu_properties" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" - -[[package]] -name = "icu_provider" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" -dependencies = [ - "equivalent", - "hashbrown 0.17.1", - "serde", - "serde_core", -] - -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", -] - -[[package]] -name = "ipnetwork" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" -dependencies = [ - "serde", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "jiff" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb" -dependencies = [ - "defmt", - "jiff-core", - "jiff-static", - "jiff-tzdb-platform", - "log", - "portable-atomic", - "portable-atomic-util", - "serde_core", - "windows-link", -] - -[[package]] -name = "jiff-core" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c" -dependencies = [ - "defmt", - "log", -] - -[[package]] -name = "jiff-static" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212" -dependencies = [ - "jiff-core", - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "jiff-tzdb" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" - -[[package]] -name = "jiff-tzdb-platform" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" -dependencies = [ - "jiff-tzdb", -] - -[[package]] -name = "jni" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" -dependencies = [ - "cfg-if", - "combine", - "jni-macros", - "jni-sys", - "log", - "simd_cesu8", - "thiserror", - "walkdir", - "windows-link", -] - -[[package]] -name = "jni-macros" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "simd_cesu8", - "syn 2.0.119", -] - -[[package]] -name = "jni-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" -dependencies = [ - "jni-sys-macros", -] - -[[package]] -name = "jni-sys-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" -dependencies = [ - "quote", - "syn 2.0.119", -] - -[[package]] -name = "js-sys" -version = "0.3.105" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce57d20d1ea864ce2ac172ab472d409214f4fd359f0b2a2775abdf522e2af99e" -dependencies = [ - "cfg-if", - "futures-util", - "wasm-bindgen", -] - -[[package]] -name = "json5" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" -dependencies = [ - "pest", - "pest_derive", - "serde", -] - -[[package]] -name = "keccak" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" -dependencies = [ - "cpufeatures 0.2.17", -] - -[[package]] -name = "keyed-set" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d255a6b6ecd77bb93ce91de984d7039bff7503f500eb4851a1269732f22baf" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "konst" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" -dependencies = [ - "konst_macro_rules", -] - -[[package]] -name = "konst_macro_rules" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lcm-msgs" -version = "0.1.0" -source = "git+https://github.com/dimensionalOS/dimos-lcm.git?rev=04d78e8622500244123ba9cefa4c51b4cb454549#04d78e8622500244123ba9cefa4c51b4cb454549" -dependencies = [ - "byteorder", -] - -[[package]] -name = "libc" -version = "0.2.191" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a" - -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link", -] - -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - -[[package]] -name = "libredox" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6480ccc157a1389bb2e4891b24751b0f798ba640d22386f23143fbcc89da195a" -dependencies = [ - "libc", -] - -[[package]] -name = "litemap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "lockfree" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74ee94b5ad113c7cb98c5a040f783d0952ee4fe100993881d1673c2cb002dd23" -dependencies = [ - "owned-alloc", -] - -[[package]] -name = "log" -version = "0.4.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" - -[[package]] -name = "lru-slab" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f" - -[[package]] -name = "lz4_flex" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8c72594ac26bfd34f2d99dfced2edfaddfe8a476e3ff2ca0eb293d925c4f83" -dependencies = [ - "twox-hash", -] - -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "matrixmultiply" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f607c237553f086e7043417a51df26b2eb899d3caff94e6a67592ff992fedc7" -dependencies = [ - "autocfg", - "rawpointer", -] - -[[package]] -name = "memchr" -version = "2.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "nalgebra" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc43a60c217b0c6ff46e47f26911015ad8d2e5a8be1af668c67e370d99a4346" -dependencies = [ - "approx", - "glam 0.30.10", - "glam 0.31.1", - "glam 0.32.1", - "glam 0.33.7", - "matrixmultiply", - "nalgebra-macros", - "num-complex", - "num-rational", - "num-traits", - "simba", - "typenum", -] - -[[package]] -name = "nalgebra-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "973e7178a678cfd059ccec50887658d482ce16b0aa9da3888ddeab5cd5eb4889" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom 0.2.17", -] - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.13.2", - "cfg-if", - "cfg_aliases 0.2.2", - "libc", -] - -[[package]] -name = "no-std-net" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nonempty-collections" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e216d0e8cf9d54fa66e5780f6e1d5dc96d1c1b3c25aeba3b6758548bcbbd8b9d" -dependencies = [ - "serde", -] - -[[package]] -name = "nu-ansi-term" -version = "0.50.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "num-bigint" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" - -[[package]] -name = "num-integer" -version = "0.1.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "oid-registry" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" -dependencies = [ - "asn1-rs", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "openssl-probe" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "owned-alloc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30fceb411f9a12ff9222c5f824026be368ff15dc2f13468d850c7d3f502205d6" - -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pem" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d354a98a3d1251555de99e8fdd8afda05573c31b82f59063a7b0a29b5527f120" -dependencies = [ - "base64 0.23.1", - "serde_core", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pest" -version = "2.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd47a460a9cbc3b3429c7e22bf0d76653e779319bae45a499ca010c9a990bb23" -dependencies = [ - "memchr", - "psm", - "stacker", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "203e46697708f7519ab1608393cf89239cafb46b8e6d08a8ffe359359b11ef44" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e84ae6340a458d3d6cfc73cf328cf3cfe90b2484cd0de25eb66aa954615ed4d5" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "pest_meta" -version = "2.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b57f92f32b3dbce6598fd8f5cdf1f06a6072570b8103fa21728fa9036923e710" -dependencies = [ - "pest", -] - -[[package]] -name = "petgraph" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" -dependencies = [ - "fixedbitset", - "hashbrown 0.15.5", - "indexmap 2.14.2", - "serde", -] - -[[package]] -name = "phf" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" -dependencies = [ - "phf_macros", - "phf_shared", - "serde", -] - -[[package]] -name = "phf_generator" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" -dependencies = [ - "fastrand", - "phf_shared", -] - -[[package]] -name = "phf_macros" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "phf_shared" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "pnet_base" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc190d4067df16af3aba49b3b74c469e611cad6314676eaf1157f31aa0fb2f7" -dependencies = [ - "no-std-net", -] - -[[package]] -name = "pnet_datalink" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79e70ec0be163102a332e1d2d5586d362ad76b01cec86f830241f2b6452a7b7" -dependencies = [ - "ipnetwork", - "libc", - "pnet_base", - "pnet_sys", - "winapi", -] - -[[package]] -name = "pnet_sys" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d4643d3d4db6b08741050c2f3afa9a892c4244c085a72fcda93c9c2c9a00f4b" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "portable-atomic" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" - -[[package]] -name = "portable-atomic-util" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "potential_utf" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" -dependencies = [ - "zerovec", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.119", -] - -[[package]] -name = "proc-macro-crate" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro-error-attr3" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e564d14133360e1ae169ffde5da25881b5fa47261665b8e5713c212c27799da" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error3" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0d4471b3436c22106b21913b1dda531558918ae9b7ec55d58aa84b43552233" -dependencies = [ - "proc-macro-error-attr3", - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "proc-macro2" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prometheus-client" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cca3d75b4566b9a29fe1ed623587fb058e826eb329a0be4b7c4da1ebb2d7a6ca" -dependencies = [ - "dtoa", - "itoa", - "parking_lot", - "prometheus-client-derive-encode", -] - -[[package]] -name = "prometheus-client-derive-encode" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01e34894696ff94f64a20c2c373a6440903e9c2789a303d68ec6e6f953f890e4" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "psm" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" -dependencies = [ - "cc", -] - -[[package]] -name = "quinn" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4051e23e9185c255a7e33ef59cdbca87a22d359052eecd22fc6b901fb37d9d11" -dependencies = [ - "bytes", - "cfg_aliases 0.2.2", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2 0.6.5", - "thiserror", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9746dbde176634f4f2f1faf2404e30a31b2bc1e9cafb5329c95d8177a18c9fc" -dependencies = [ - "bytes", - "fastbloom", - "getrandom 0.4.3", - "lru-slab", - "rand 0.10.2", - "rand_pcg", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "rustls-platform-verifier", - "slab", - "thiserror", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" -dependencies = [ - "cfg_aliases 0.2.2", - "libc", - "once_cell", - "socket2 0.6.5", - "tracing", - "windows-sys 0.61.2", -] - -[[package]] -name = "quote" -version = "1.0.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "r-efi" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" - -[[package]] -name = "rand" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" -dependencies = [ - "libc", - "rand_chacha", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" -dependencies = [ - "chacha20", - "getrandom 0.4.3", - "rand_core 0.10.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", -] - -[[package]] -name = "rand_core" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" - -[[package]] -name = "rand_pcg" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" -dependencies = [ - "rand_core 0.10.1", -] - -[[package]] -name = "rawpointer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" - -[[package]] -name = "rayon" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "rcgen" -version = "0.14.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8774e05a7d0de114588e6a28fe7e71694b82614ed569d86d8b389dfbc98b8ad8" -dependencies = [ - "pem", - "ring", - "rustls-pki-types", - "time", - "x509-parser", - "yasna", -] - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags 2.13.2", -] - -[[package]] -name = "redox_users" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" -dependencies = [ - "libredox", - "thiserror", -] - -[[package]] -name = "ref-cast" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "regex" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.17", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "ringbuffer-spsc" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3e7aa0a681b232e7cd7f856a53b10603df88ca74b79a8d8088845185492e35" -dependencies = [ - "array-init", - "crossbeam", -] - -[[package]] -name = "rlimit" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7043b63bd0cd1aaa628e476b80e6d4023a3b50eb32789f2728908107bd0c793a" -dependencies = [ - "libc", -] - -[[package]] -name = "ron" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81116b9531d61eabc41aeb228e4b6b2435bcca3233b98cf3b3077d4e6e9debb3" -dependencies = [ - "bitflags 2.13.2", - "once_cell", - "serde", - "serde_derive", - "typeid", - "unicode-ident", -] - -[[package]] -name = "ros2msg" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fe291be5cb6d4b8e6bf9c9de80c40bd1cb09ecac50deafa2fdcae0027e04988" -dependencies = [ - "heck", - "pest", - "pest_derive", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "syn 2.0.119", - "thiserror", -] - -[[package]] -name = "rustc-hash" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rusticata-macros" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" -dependencies = [ - "nom", -] - -[[package]] -name = "rustls" -version = "0.23.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" -dependencies = [ - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" -dependencies = [ - "web-time", - "zeroize", -] - -[[package]] -name = "rustls-platform-verifier" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustls-platform-verifier-android" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" - -[[package]] -name = "rustls-webpki" -version = "0.103.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" - -[[package]] -name = "ryu" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" - -[[package]] -name = "safe_arch" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42c6efa15875e6ecb39ca61fb0b0c1a40b84fac5a5ffe71eef7d1000c8eb3f5f" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "schemars" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - -[[package]] -name = "schemars" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" -dependencies = [ - "dyn-clone", - "either", - "ref-cast", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98c67716b46af2f0b8cf752abc930f6f9aecfbf671ecfb531db8a31dbe4e2ba" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 3.0.9", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "secrecy" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" -dependencies = [ - "serde", - "zeroize", -] - -[[package]] -name = "security-framework" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" -dependencies = [ - "bitflags 2.13.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" - -[[package]] -name = "serde" -version = "1.0.229" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde-big-array" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_core" -version = "1.0.229" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.229" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "serde_derive_internals" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "serde_json" -version = "1.0.154" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" -dependencies = [ - "foldhash 0.2.0", - "indexmap 2.14.2", - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "serde_spanned" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" -dependencies = [ - "serde_core", -] - -[[package]] -name = "serde_with" -version = "3.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "935177bb8c0cd8ca1a4e6d1a2ac8988bea69cab4f9d3a31311e012ad27868ea4" -dependencies = [ - "base64 0.23.1", - "bs58", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.14.2", - "jiff", - "schemars 0.9.0", - "schemars 1.2.2", - "serde_core", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d607aa01a3cb0ad757d6fd216136910db3c97b102fe686585689615a02dbcdc" -dependencies = [ - "darling 0.24.1", - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap 2.14.2", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "sha2-const-stable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9" - -[[package]] -name = "sha3" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" -dependencies = [ - "digest", - "keccak", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shellexpand" -version = "3.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32824fab5e16e6c4d86dc1ba84489390419a39f97699852b66480bb87d297ed8" -dependencies = [ - "dirs", -] - -[[package]] -name = "shlex" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" - -[[package]] -name = "signal-hook-registry" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - -[[package]] -name = "simba" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a7200d82ff1c7b4235efd12f11e2537a402c91cf83a5cb97ce80eef787fde7" -dependencies = [ - "approx", - "num-complex", - "num-traits", - "wide", -] - -[[package]] -name = "simd-adler32" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" - -[[package]] -name = "simd_cesu8" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" -dependencies = [ - "rustc_version", - "simdutf8", -] - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - -[[package]] -name = "siphasher" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" - -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" - -[[package]] -name = "smallvec" -version = "1.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba467056f1b547ed52077911161fc86985becbc60e8e1857c8a144dab0def891" - -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "socket2" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "spin" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" -dependencies = [ - "lock_api", -] - -[[package]] -name = "spin" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" - -[[package]] -name = "stabby" -version = "72.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d53d2428934c46277fafd2d41e39357595aa1e47954c75db2b14ed90632f3cc" -dependencies = [ - "rustversion", - "stabby-abi", -] - -[[package]] -name = "stabby-abi" -version = "72.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f375eae680bb54203ee5e47d4cd2ae7b79c0a79ed90919279f38f500ad53f190" -dependencies = [ - "rustc_version", - "rustversion", - "sha2-const-stable", - "stabby-macros", -] - -[[package]] -name = "stabby-macros" -version = "72.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea664671a576c5f7e32fee291ac123d82af5e92b0689beb3555347c00c76eef1" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "stacker" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707f49d46706bacf8a2b00d51dace3f9de527c13eec3778f570c411f89e69967" -dependencies = [ - "cc", - "cfg-if", - "libc", - "psm", - "windows-sys 0.61.2", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "static_init" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bae1df58c5fea7502e8e352ec26b5579f6178e1fdb311e088580c980dee25ed" -dependencies = [ - "bitflags 1.3.2", - "cfg_aliases 0.2.2", - "libc", - "parking_lot", - "parking_lot_core", - "static_init_macro", - "winapi", -] - -[[package]] -name = "static_init_macro" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1389c88ddd739ec6d3f8f83343764a0e944cd23cfbf126a9796a714b0b6edd6f" -dependencies = [ - "cfg_aliases 0.1.1", - "memchr", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.119" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "3.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "synstructure" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "talc" -version = "4.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ae828aa394de34c7de08f522d1b86bd1c182c668d27da69caadda00590f26d" - -[[package]] -name = "thiserror" -version = "2.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "thread-priority" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe075d7053dae61ac5413a34ea7d4913b6e6207844fd726bdd858b37ff72bf5" -dependencies = [ - "bitflags 2.13.2", - "cfg-if", - "libc", - "log", - "rustversion", - "winapi", -] - -[[package]] -name = "thread_local" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "time" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" -dependencies = [ - "deranged", - "num-conv", - "powerfmt", - "serde_core", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" - -[[package]] -name = "time-macros" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinystr" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinyvec" -version = "1.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" - -[[package]] -name = "token-cell" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb48920ae769b58126c8c93269805011c793201f95fde28b479b81a9a531bbde" -dependencies = [ - "paste", - "portable-atomic", - "rustversion", -] - -[[package]] -name = "tokio" -version = "1.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" -dependencies = [ - "bytes", - "libc", - "mio", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.6.5", - "tokio-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "tokio-util" -version = "0.7.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "futures-util", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.9.12+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" -dependencies = [ - "indexmap 2.14.2", - "serde_core", - "serde_spanned", - "toml_datetime 0.7.5+spec-1.1.0", - "toml_parser", - "toml_writer", - "winnow 0.7.15", -] - -[[package]] -name = "toml" -version = "1.1.6+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "920602543f0911ab71da12c50d59701da54c196d1a2bf5cb4b75667f137a406a" -dependencies = [ - "indexmap 2.14.2", - "serde_core", - "serde_spanned", - "toml_datetime 1.1.1+spec-1.1.0", - "toml_parser", - "toml_writer", - "winnow 1.0.4", -] - -[[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_datetime" -version = "1.1.1+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_edit" -version = "0.25.15+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1340ea94a5856333492c9064b02c778b191dd2c853778d9609debdcdfea3a614" -dependencies = [ - "indexmap 2.14.2", - "toml_datetime 1.1.1+spec-1.1.0", - "toml_parser", - "winnow 1.0.4", -] - -[[package]] -name = "toml_parser" -version = "1.1.3+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" -dependencies = [ - "winnow 1.0.4", -] - -[[package]] -name = "toml_writer" -version = "1.1.2+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-serde" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" -dependencies = [ - "serde", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", - "serde", - "serde_json", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", - "tracing-serde", -] - -[[package]] -name = "twox-hash" -version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if", - "static_assertions", -] - -[[package]] -name = "typeid" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" - -[[package]] -name = "typenum" -version = "1.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" - -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - -[[package]] -name = "uhlc" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62a645e3e4e6c85b7abe49b086aa3204119431f42b6123b0070419fb6e9d24e" -dependencies = [ - "humantime", - "lazy_static", - "log", - "rand 0.8.8", - "serde", - "spin 0.10.1", -] - -[[package]] -name = "unicode-ident" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "unzip-n" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b5bb2756c16fb66f80cfbf5fb0e0c09a7001e739f453c9ec241b9c8b1556fda" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "url" -version = "2.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "validated_struct" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "869a93e8a7286e339e1128630051d82babbcd75d585975af07b9f3327220e60e" -dependencies = [ - "json5", - "serde", - "serde_json", - "validated_struct_macros", -] - -[[package]] -name = "validated_struct_macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c44ce98e7227a04eeb4cf9c784109a5c9710e54849ceb4f09f8597247897f1e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", - "unzip-n", -] - -[[package]] -name = "validator" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d68c6633c483df6780cc5277a417c7c2d1bceee2649d06c8ab6b0fd2dd3c81" -dependencies = [ - "idna", - "regex", - "serde", - "serde_derive", - "serde_json", - "url", - "validator_derive", -] - -[[package]] -name = "validator_derive" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240e4b81c20a1d6d50d1d7265c658dfbd204e8b9ac4d80f3c931f39462196335" -dependencies = [ - "darling 0.23.0", - "proc-macro-error3", - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasip2" -version = "1.0.4+wasi-0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.128" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.128" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.128" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn 3.0.9", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.128" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-root-certs" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "webpki-roots" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "wide" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d920ac99c3c8edce110cb8d07dbb324d6d026011dce85b1e9355b70f0adacc4f" -dependencies = [ - "bytemuck", - "safe_arch", -] - -[[package]] -name = "win-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7b128a98c1cfa201b09eb49ba285887deb3cbe7466a98850eb1adabb452be5" -dependencies = [ - "windows", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45296b64204227616fdbf2614cefa4c236b98ee64dfaaaa435207ed99fe7829f" -dependencies = [ - "windows_aarch64_msvc 0.34.0", - "windows_i686_gnu 0.34.0", - "windows_i686_msvc 0.34.0", - "windows_x86_64_gnu 0.34.0", - "windows_x86_64_msvc 0.34.0", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" - -[[package]] -name = "winnow" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" -dependencies = [ - "memchr", -] - -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - -[[package]] -name = "writeable" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" - -[[package]] -name = "x509-parser" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" -dependencies = [ - "asn1-rs", - "data-encoding", - "der-parser", - "lazy_static", - "nom", - "oid-registry", - "ring", - "rusticata-macros", - "thiserror", - "time", -] - -[[package]] -name = "yasna" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5f6765e852b9b4dc8e2a76843e4d64d1cea8e79bcde0b6901aea8e7c7f08282" -dependencies = [ - "bit-vec", - "time", -] - -[[package]] -name = "yoke" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", - "synstructure 0.13.2", -] - -[[package]] -name = "zenoh" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ba5d28a1197653aae4bb024fd74a9d5c7051d5a19a77f3a43d83f40c22584" -dependencies = [ - "ahash", - "arc-swap", - "async-trait", - "bytes", - "const_format", - "flate2", - "flume", - "futures", - "git-version", - "itertools", - "json5", - "lazy_static", - "nonempty-collections", - "once_cell", - "petgraph", - "phf", - "rand 0.8.8", - "rustc_version", - "serde", - "serde_json", - "socket2 0.5.10", - "tokio", - "tokio-util", - "tracing", - "uhlc", - "vec_map", - "zenoh-buffers", - "zenoh-codec", - "zenoh-collections", - "zenoh-config", - "zenoh-core", - "zenoh-keyexpr", - "zenoh-link", - "zenoh-link-commons", - "zenoh-macros", - "zenoh-plugin-trait", - "zenoh-protocol", - "zenoh-result", - "zenoh-runtime", - "zenoh-shm", - "zenoh-sync", - "zenoh-task", - "zenoh-transport", - "zenoh-util", -] - -[[package]] -name = "zenoh-buffers" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555a8169c9888fc5571f1b38d2843a63db786621e153abad1b075c40b20e83b4" -dependencies = [ - "zenoh-collections", -] - -[[package]] -name = "zenoh-codec" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc959f727893eab9b66ec051c8f4a2d6f66b4ee70bf23f2ed244aa754705e854" -dependencies = [ - "rand 0.8.8", - "tracing", - "uhlc", - "zenoh-buffers", - "zenoh-protocol", - "zenoh-shm", -] - -[[package]] -name = "zenoh-collections" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c05abd8dcfd2239a8dfb5b79bd4ed85094c6bb6d6b991d3529bff364cc48e29" -dependencies = [ - "ahash", -] - -[[package]] -name = "zenoh-config" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59799d556b4fac79886cb0a9c90f3bc48d0894816b99c8a90a3509b1809a02dd" -dependencies = [ - "json5", - "nonempty-collections", - "num_cpus", - "secrecy", - "serde", - "serde_json", - "serde_with", - "serde_yaml", - "toml 0.9.12+spec-1.1.0", - "tracing", - "uhlc", - "validated_struct", - "zenoh-core", - "zenoh-keyexpr", - "zenoh-macros", - "zenoh-protocol", - "zenoh-result", - "zenoh-util", -] - -[[package]] -name = "zenoh-core" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975073c51353c1c33e81a98370bf3560863540913e5f30091923f5a328fc46d4" -dependencies = [ - "lazy_static", - "tokio", - "zenoh-result", - "zenoh-runtime", -] - -[[package]] -name = "zenoh-crypto" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e281a36cfd351ba9232a24899d946a782d0ff3ac0c3d759f87f3e7cbe09a4553" -dependencies = [ - "aes", - "hmac", - "rand 0.8.8", - "rand_chacha", - "sha3", - "zenoh-result", -] - -[[package]] -name = "zenoh-keyexpr" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c6fcb7f18846b4e9b097c61ed7c656ec8d7858ab54a12d5f5025fe1514caae" -dependencies = [ - "getrandom 0.2.17", - "hashbrown 0.16.1", - "keyed-set", - "rand 0.8.8", - "schemars 1.2.2", - "serde", - "token-cell", - "zenoh-result", -] - -[[package]] -name = "zenoh-link" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55c4fbc923328f0b62b1b492723ff53b757a36421f70218e652f0aa899cde6c" -dependencies = [ - "zenoh-config", - "zenoh-link-commons", - "zenoh-link-tcp", - "zenoh-link-udp", - "zenoh-protocol", - "zenoh-result", -] - -[[package]] -name = "zenoh-link-commons" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d52520b4c22d05173c8621e3cbe18d838a17d74477891ed9c59a7aeedaa325d" -dependencies = [ - "async-trait", - "base64 0.22.1", - "bytes", - "flume", - "futures", - "quinn", - "quinn-proto", - "rcgen", - "rustls", - "rustls-pemfile", - "rustls-pki-types", - "rustls-webpki", - "secrecy", - "serde", - "socket2 0.5.10", - "time", - "tokio", - "tokio-util", - "tracing", - "webpki-roots", - "x509-parser", - "zenoh-buffers", - "zenoh-codec", - "zenoh-config", - "zenoh-core", - "zenoh-protocol", - "zenoh-result", - "zenoh-runtime", - "zenoh-util", -] - -[[package]] -name = "zenoh-link-quic_datagram" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1af3abf41c719c82ca356864b5ddeeb7c77cb29fe777776b40b31eb4d19de288" -dependencies = [ - "async-trait", - "rustls-webpki", - "time", - "tokio-util", - "tracing", - "zenoh-core", - "zenoh-link-commons", - "zenoh-protocol", - "zenoh-result", -] - -[[package]] -name = "zenoh-link-tcp" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4702d55fe9f17cbd1d3b601901f8ba0a693a7ad1ce685a1ea4c60f775552b7" -dependencies = [ - "async-trait", - "socket2 0.5.10", - "tokio", - "tokio-util", - "tracing", - "zenoh-config", - "zenoh-core", - "zenoh-link-commons", - "zenoh-protocol", - "zenoh-result", -] - -[[package]] -name = "zenoh-link-udp" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b140e7b65715fe8b29b706b2b9fc3009fc6181346931c8926d290113fe38df4b" -dependencies = [ - "async-trait", - "libc", - "socket2 0.5.10", - "tokio", - "tokio-util", - "tracing", - "windows-sys 0.61.2", - "zenoh-buffers", - "zenoh-core", - "zenoh-link-commons", - "zenoh-link-quic_datagram", - "zenoh-protocol", - "zenoh-result", - "zenoh-sync", - "zenoh-util", -] - -[[package]] -name = "zenoh-macros" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f483b343fd79b6c1bd7d79f130b5c6c208e7fef243a4d7966a6bf9fdecbd70f8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", - "zenoh-keyexpr", -] - -[[package]] -name = "zenoh-plugin-trait" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d57f491f63afa7413d68ee68e4de2bc9ce361c4ac89a76d5a0a0e3ca0624e21" -dependencies = [ - "git-version", - "libloading", - "serde", - "stabby", - "tracing", - "zenoh-config", - "zenoh-keyexpr", - "zenoh-macros", - "zenoh-result", - "zenoh-util", -] - -[[package]] -name = "zenoh-protocol" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4492192986df044627f33c8eeb8aa237fb4d3bbd2d8cc68bc7eee16748c2fb61" -dependencies = [ - "const_format", - "rand 0.8.8", - "serde", - "uhlc", - "zenoh-buffers", - "zenoh-keyexpr", - "zenoh-macros", - "zenoh-result", -] - -[[package]] -name = "zenoh-result" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6d0ca24186d9cfbf14f2d08b8b0a09afac690fe5cd68899d8f896f9247a3dd" -dependencies = [ - "anyhow", -] - -[[package]] -name = "zenoh-runtime" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e8ea6ed9fb3300d02bc303b3202a21a758aa5d7a1e7dcc38610428910af9f9" -dependencies = [ - "lazy_static", - "ron", - "serde", - "tokio", - "tracing", - "zenoh-macros", - "zenoh-result", -] - -[[package]] -name = "zenoh-shm" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1600eef8e5b1148585b020985bd4b7851d86b585dc90dd306343127e552c591f" -dependencies = [ - "advisory-lock", - "async-trait", - "buddy_system_allocator", - "crossbeam-channel", - "crossbeam-queue", - "nix", - "num-traits", - "rand 0.8.8", - "rlimit", - "stabby", - "static_assertions", - "static_init", - "talc", - "thread-priority", - "tokio", - "tracing", - "win-sys", - "winapi", - "zenoh-buffers", - "zenoh-core", - "zenoh-macros", - "zenoh-result", -] - -[[package]] -name = "zenoh-stats" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2f2972f429c8686e6d4963649b96e1f74bee0826fc80d398292913d0bb852fe" -dependencies = [ - "ahash", - "prometheus-client", - "serde_json", - "smallvec", - "zenoh-keyexpr", - "zenoh-protocol", -] - -[[package]] -name = "zenoh-sync" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d57ed2156b61df6e877b03fb13dd72227d3d286a7fa689120109bad289ddf12b" -dependencies = [ - "arc-swap", - "event-listener", - "futures", - "tokio", - "zenoh-buffers", - "zenoh-collections", - "zenoh-core", -] - -[[package]] -name = "zenoh-task" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887115c0f81c72ff8c9b99e6fccd9e1c3829d83e16b8b063174786b9fba08810" -dependencies = [ - "futures", - "tokio", - "tokio-util", - "tracing", - "zenoh-core", - "zenoh-runtime", -] - -[[package]] -name = "zenoh-transport" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72bae2e0aca56ac6431bd6c37c6ac3fcc9367446cbb356bd44137cc01d1493ee" -dependencies = [ - "async-trait", - "crossbeam-utils", - "flume", - "futures", - "lazy_static", - "lockfree", - "lz4_flex", - "rand 0.8.8", - "ringbuffer-spsc", - "serde", - "sha3", - "static_init", - "tokio", - "tokio-util", - "tracing", - "zenoh-buffers", - "zenoh-codec", - "zenoh-config", - "zenoh-core", - "zenoh-crypto", - "zenoh-link", - "zenoh-link-commons", - "zenoh-protocol", - "zenoh-result", - "zenoh-runtime", - "zenoh-shm", - "zenoh-stats", - "zenoh-sync", - "zenoh-task", - "zenoh-util", -] - -[[package]] -name = "zenoh-util" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a473dcc62026b9d9589acc22c62b04cb7dab4070bba5543d2afac741ddf947" -dependencies = [ - "async-trait", - "const_format", - "flume", - "home", - "humantime", - "lazy_static", - "libc", - "libloading", - "pnet_datalink", - "schemars 1.2.2", - "serde", - "serde_json", - "shellexpand", - "tokio", - "tracing", - "tracing-subscriber", - "winapi", - "zenoh-core", - "zenoh-result", -] - -[[package]] -name = "zerocopy" -version = "0.8.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d35102a9f36d089ccae9e4c6802bc118be4487b80aaffc0ab4e0cf5ce92d2873" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c01f5ab44258da43cf276c74a2763db2ff3969c9c652c3f2de07041d0b2bc" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "zerofrom" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", - "synstructure 0.14.0", -] - -[[package]] -name = "zeroize" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" - -[[package]] -name = "zerotrie" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - -[[package]] -name = "zlib-rs" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" - -[[package]] -name = "zmij" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/native/rust/dimos-message-adapters/Cargo.toml b/native/rust/dimos-message-adapters/Cargo.toml deleted file mode 100644 index 491f8539730..00000000000 --- a/native/rust/dimos-message-adapters/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "dimos-message-adapters" -version = "0.1.0" -edition = "2021" -license = "Apache-2.0" -description = "Generated-message adapters for the dimOS native module SDK" - -[workspace] - -[dependencies] -dimos-module = { path = "../dimos-module", features = ["cdr"] } -dimos-generated-messages = { path = "../../../build/message-source/rust" } -nalgebra = "0.35.0" diff --git a/native/rust/dimos-message-adapters/src/lib.rs b/native/rust/dimos-message-adapters/src/lib.rs deleted file mode 100644 index 8a893dc1b5c..00000000000 --- a/native/rust/dimos-message-adapters/src/lib.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2026 Dimensional Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Generated-message adapters for the dimOS native module SDK. - -pub mod tf; diff --git a/native/rust/dimos-message-adapters/src/tf.rs b/native/rust/dimos-message-adapters/src/tf.rs deleted file mode 100644 index 061f316c429..00000000000 --- a/native/rust/dimos-message-adapters/src/tf.rs +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2026 Dimensional Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Canonical generated TF messages at the SDK numeric transform boundary. - -use dimos_generated_messages::builtin_interfaces::msg::time::Time; -use dimos_generated_messages::std_msgs::msg::header::Header; -use dimos_module::cdr; -use nalgebra::Isometry3; - -pub fn decode(bytes: &[u8]) -> std::io::Result> { - from_message(cdr::decode(bytes)?) -} - -pub fn from_message( - message: dimos_generated_messages::tf2_msgs::msg::tf_message::TFMessage, -) -> std::io::Result> { - use nalgebra::{Quaternion, Translation3, UnitQuaternion}; - message - .transforms - .into_iter() - .map(|edge| { - let p = edge.transform.translation; - let q = edge.transform.rotation; - if ![p.x, p.y, p.z, q.x, q.y, q.z, q.w] - .iter() - .all(|v| v.is_finite()) - { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "nonfinite TF components", - )); - } - let rotation = UnitQuaternion::try_new(Quaternion::new(q.w, q.x, q.y, q.z), 1e-9) - .ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "zero TF quaternion") - })?; - if edge.header.stamp.nanosec >= 1_000_000_000 { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "unnormalized TF stamp", - )); - } - Ok(dimos_module::Transform::from_nanoseconds( - edge.header.frame_id, - edge.child_frame_id, - edge.header.stamp.sec as i64 * 1_000_000_000 + edge.header.stamp.nanosec as i64, - Isometry3::from_parts(Translation3::new(p.x, p.y, p.z), rotation), - )) - }) - .collect() -} - -pub fn encode(transforms: &[dimos_module::Transform]) -> std::io::Result> { - cdr::encode(&to_message(transforms)?) -} - -pub fn to_message( - transforms: &[dimos_module::Transform], -) -> std::io::Result { - use dimos_generated_messages::{ - geometry_msgs::msg::{ - quaternion::Quaternion, transform::Transform, transform_stamped::TransformStamped, - vector3::Vector3, - }, - tf2_msgs::msg::tf_message::TFMessage, - }; - let transforms = transforms - .iter() - .map(|value| { - let ns = value.stamp_nanoseconds().ok_or_else(|| { - std::io::Error::new( - std::io::ErrorKind::InvalidInput, - "TF timestamp is outside range", - ) - })?; - let sec = i32::try_from(ns.div_euclid(1_000_000_000)).map_err(|_| { - std::io::Error::new( - std::io::ErrorKind::InvalidInput, - "TF seconds exceed ROS int32", - ) - })?; - let p = value.translation(); - let q = value.rotation(); - if ![p.x, p.y, p.z, q.i, q.j, q.k, q.w] - .iter() - .all(|v| v.is_finite()) - { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - "nonfinite TF components", - )); - } - Ok(TransformStamped { - header: Header { - stamp: Time { - sec, - nanosec: ns.rem_euclid(1_000_000_000) as u32, - }, - frame_id: value.parent.clone(), - }, - child_frame_id: value.child.clone(), - transform: Transform { - translation: Vector3 { - x: p.x, - y: p.y, - z: p.z, - }, - rotation: Quaternion { - x: q.i, - y: q.j, - z: q.k, - w: q.w, - }, - }, - }) - }) - .collect::>>()?; - Ok(TFMessage { transforms }) -} - -#[cfg(test)] -mod tests { - use super::*; - use dimos_module::Transform; - use nalgebra::Isometry3; - - #[test] - fn canonical_tf_preserves_exact_stamps_and_values_in_both_wire_orders() { - for ns in [ - 0, - -1, - 1_700_000_000_000_000_001, - 1_700_000_000_000_000_002, - 1_700_000_000_123_456_789, - ] { - let edge = Transform::from_nanoseconds( - "map", - "camera", - ns, - Isometry3::translation(1.0, 2.0, 3.0), - ); - let message = to_message(&[edge]).unwrap(); - assert_eq!( - message.transforms[0].header.stamp.sec as i64 * 1_000_000_000 - + message.transforms[0].header.stamp.nanosec as i64, - ns - ); - for little in [false, true] { - let decoded = decode(&cdr::encode_endian(&message, little).unwrap()).unwrap(); - assert_eq!(decoded[0].stamp_nanoseconds(), Some(ns)); - assert_eq!(decoded[0].translation(), nalgebra::Vector3::new(1., 2., 3.)); - let restored = cdr::decode::< - dimos_generated_messages::tf2_msgs::msg::tf_message::TFMessage, - >(&encode(&decoded).unwrap()) - .unwrap(); - assert_eq!(restored, message); - } - } - } - - #[test] - fn reject_invalid_components_and_time_before_returning_any_edges() { - let good = - to_message(&[Transform::new("map", "camera", 0., Isometry3::identity())]).unwrap(); - let mut bad_stamp = good.clone(); - bad_stamp.transforms[0].header.stamp.nanosec = 1_000_000_000; - assert_eq!( - from_message(bad_stamp).unwrap_err().kind(), - std::io::ErrorKind::InvalidData - ); - let mut bad_rotation = good.clone(); - bad_rotation.transforms[0].transform.rotation.w = 0.; - assert_eq!( - from_message(bad_rotation).unwrap_err().kind(), - std::io::ErrorKind::InvalidData - ); - let mut bad_position = good; - bad_position.transforms[0].transform.translation.x = f64::NAN; - assert_eq!( - from_message(bad_position).unwrap_err().kind(), - std::io::ErrorKind::InvalidData - ); - let overflow = - Transform::from_nanoseconds("map", "camera", i64::MAX, Isometry3::identity()); - assert_eq!( - encode(&[overflow]).unwrap_err().kind(), - std::io::ErrorKind::InvalidInput - ); - } -} diff --git a/native/rust/dimos-module-macros/src/lib.rs b/native/rust/dimos-module-macros/src/lib.rs index 2ac7083fef4..ff19a4af1ad 100644 --- a/native/rust/dimos-module-macros/src/lib.rs +++ b/native/rust/dimos-module-macros/src/lib.rs @@ -194,9 +194,7 @@ enum FieldKind { handler: Ident, }, Config, - Tf { - codecs: Option<(Path, Path)>, - }, + Tf, State, } @@ -335,12 +333,7 @@ fn expand(input: DeriveInput) -> syn::Result { quote!(#name: builder.io(#name_str, #decode, #encode)) } FieldKind::Config => quote!(#name: config), - FieldKind::Tf { codecs: None } => quote!(#name: builder.tf()), - FieldKind::Tf { - codecs: Some((decode, encode)), - } => { - quote!(#name: builder.tf_with_codec(#decode, #encode)) - } + FieldKind::Tf => quote!(#name: builder.tf()), FieldKind::State => quote!(#name: ::core::default::Default::default()), } }); @@ -458,23 +451,36 @@ fn port_decls(classified: &[ClassifiedField], want_input: bool) -> Vec // goes: bake has to put the topic in the host's map or the module // refuses to start. It lists under `inputs` because the graph has // no io kind and a host mostly consumes tf. - FieldKind::Tf { .. } => want_input, + FieldKind::Tf => want_input, _ => false, }) - .map(|f| PortDecl { - name: f.name.to_string(), - // `Tf` carries no generic payload. The port is TFMessage by - // construction. - // An explicit `msg` wins: a view type's wire payload and the dimos - // message it stands for are allowed to differ. - ty: match f.kind { - FieldKind::Tf { .. } => TF_PAYLOAD_TYPE.to_string(), - _ => f - .msg - .clone() - .or_else(|| port_payload_type(f.ty)) - .unwrap_or_default(), - }, + .flat_map(|f| { + let port = PortDecl { + name: f.name.to_string(), + // `Tf` carries no generic payload. The port is TFMessage by + // construction. + // An explicit `msg` wins: a view type's wire payload and the dimos + // message it stands for are allowed to differ. + ty: match f.kind { + FieldKind::Tf => TF_PAYLOAD_TYPE.to_string(), + _ => f + .msg + .clone() + .or_else(|| port_payload_type(f.ty)) + .unwrap_or_default(), + }, + }; + if matches!(f.kind, FieldKind::Tf) { + vec![ + port, + PortDecl { + name: "tf_static".into(), + ty: TF_PAYLOAD_TYPE.into(), + }, + ] + } else { + vec![port] + } }) .collect() } @@ -656,31 +662,13 @@ fn classify_field(field: &Field, name: &Ident) -> syn::Result { if found.is_some() { return Err(syn::Error::new_spanned(attr, ONE_ATTR_ONLY)); } - let codecs = if matches!(&attr.meta, syn::Meta::Path(_)) { - None - } else { - let mut decode: Option = None; - let mut encode: Option = None; - attr.parse_nested_meta(|meta| { - if meta.path.is_ident("decode") { - decode = Some(meta.value()?.parse()?); - } else if meta.path.is_ident("encode") { - encode = Some(meta.value()?.parse()?); - } else { - return Err(meta.error("expected `decode = ...` or `encode = ...`")); - } - Ok(()) - })?; - Some(( - decode.ok_or_else(|| { - syn::Error::new_spanned(attr, "#[tf] requires both decode and encode") - })?, - encode.ok_or_else(|| { - syn::Error::new_spanned(attr, "#[tf] requires both decode and encode") - })?, - )) - }; - found = Some(FieldKind::Tf { codecs }); + if !matches!(&attr.meta, syn::Meta::Path(_)) { + return Err(syn::Error::new_spanned( + attr, + "#[tf] uses standard ROS TF messages and takes no codec arguments", + )); + } + found = Some(FieldKind::Tf); } } @@ -769,10 +757,7 @@ mod tests { #[test] fn tf_accepts_legacy_or_explicit_codec_pair_and_keeps_registry_type() { - for field in [ - parse_quote!(#[tf] tf: Tf), - parse_quote!(#[tf(decode = wire::decode, encode = wire::encode)] tf: Tf), - ] { + for field in [parse_quote!(#[tf] tf: Tf)] { let attr = super::classify_field(&field, &parse_quote!(tf)).expect("valid TF field"); let ty: syn::Type = parse_quote!(Tf); let name = parse_quote!(tf); @@ -783,8 +768,9 @@ mod tests { msg: attr.msg, }]; let ports = super::port_decls(&fields, true); - assert_eq!(ports.len(), 1); + assert_eq!(ports.len(), 2); assert_eq!(ports[0].ty, "TFMessage"); + assert_eq!(ports[1].name, "tf_static"); } } diff --git a/native/rust/dimos-module/Cargo.lock b/native/rust/dimos-module/Cargo.lock index 8d3aceb5cb4..b8b86804020 100644 --- a/native/rust/dimos-module/Cargo.lock +++ b/native/rust/dimos-module/Cargo.lock @@ -605,6 +605,7 @@ dependencies = [ "cdr", "dimos-lcm", "dimos-module-macros", + "dimos-tf-messages", "lcm-msgs", "nalgebra", "rayon", @@ -614,6 +615,7 @@ dependencies = [ "tracing", "tracing-subscriber", "tracing-test", + "transforms", "url", "validator", "zenoh", @@ -629,6 +631,17 @@ dependencies = [ "toml 1.1.6+spec-1.1.0", ] +[[package]] +name = "dimos-tf-messages" +version = "0.1.0" +dependencies = [ + "cdr", + "heapless", + "ros2msg", + "serde", + "serde-big-array", +] + [[package]] name = "dirs" version = "6.0.0" @@ -960,6 +973,15 @@ version = "0.33.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e762b9b188634fc508d4ec54b62ea3d352c43fd431d18d05d46f559f217f4725" +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1001,6 +1023,28 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -1936,6 +1980,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.119", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -2290,6 +2344,23 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "ros2msg" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fe291be5cb6d4b8e6bf9c9de80c40bd1cb09ecac50deafa2fdcae0027e04988" +dependencies = [ + "heck", + "pest", + "pest_derive", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "syn 2.0.119", + "thiserror", +] + [[package]] name = "rustc-hash" version = "2.1.3" @@ -2530,6 +2601,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + [[package]] name = "serde_core" version = "1.0.229" @@ -3226,6 +3306,18 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "transforms" +version = "2.2.0" +source = "git+https://github.com/TomCC7/transforms?rev=76cf9022173d5764814544082f2b518a9df1934b#76cf9022173d5764814544082f2b518a9df1934b" +dependencies = [ + "approx", + "hashbrown 0.17.1", + "libm", + "serde", + "thiserror", +] + [[package]] name = "twox-hash" version = "1.6.3" diff --git a/native/rust/dimos-module/Cargo.toml b/native/rust/dimos-module/Cargo.toml index cfeca5a96b2..17489e53b0e 100644 --- a/native/rust/dimos-module/Cargo.toml +++ b/native/rust/dimos-module/Cargo.toml @@ -7,11 +7,10 @@ license = "Apache-2.0" [workspace] -[features] -cdr = ["dep:cdr"] - [dependencies] -cdr = { version = "=0.2.4", git = "https://github.com/TomCC7/cdr-rs", rev = "38a4368255d408faf374726653b39d4a4e9735cb", optional = true } +dimos-tf-messages = { path = "../dimos-tf-messages" } +transforms = { version = "=2.2.0", git = "https://github.com/TomCC7/transforms", rev = "76cf9022173d5764814544082f2b518a9df1934b" } +cdr = { version = "=0.2.4", git = "https://github.com/TomCC7/cdr-rs", rev = "38a4368255d408faf374726653b39d4a4e9735cb" } dimos-lcm = { git = "https://github.com/dimensionalOS/dimos-lcm.git", rev = "04d78e8622500244123ba9cefa4c51b4cb454549" } dimos-module-macros = { version = "=0.1.0", path = "../dimos-module-macros" } lcm-msgs = { git = "https://github.com/dimensionalOS/dimos-lcm.git", rev = "04d78e8622500244123ba9cefa4c51b4cb454549" } diff --git a/native/rust/dimos-module/README.md b/native/rust/dimos-module/README.md new file mode 100644 index 00000000000..77054406d08 --- /dev/null +++ b/native/rust/dimos-module/README.md @@ -0,0 +1,28 @@ +# Native module SDK + +`#[tf]` binds standard `tf2_msgs/TFMessage` streams named `tf` and `tf_static`. +Both ports must appear in the native module registry and Python wrapper. +The SDK uses generated `TransformStamped` and `Time` values directly. TF +fields accept no codec parameters; CDR is the default wire format. + +`lookup_transform(target, source, time)` maps source coordinates into the +target frame. ROS zero time selects the latest common time. `lookup().at()` +also takes a ROS `Time`; `within()` waits for missing data. Lookups interpolate +and reject extrapolation. The `transforms` library owns the frame tree, +history, composition and interpolation. Its current registry pins each child's +parent and static/dynamic kind; changing either requires rebuilding the buffer. + +`publish()` sends dynamic transforms and `publish_static()` sends static +transforms. Static edges never expire from a receiving buffer and do not +constrain the common time of a dynamic chain. Invalid batches do not change +the graph or enqueue a packet. A failed publication queue leaves the graph +unchanged. + +The SDK's LCM and Zenoh transports do not provide ROS DDS transient-local +history. A static publisher must remain available and reannounce its complete +mount set for late subscribers. Existing Python static-mount publishers still +reannounce on dynamic `tf` for compatibility with the Python query layer; they +have not been migrated to `tf_static` in this SDK change. + +Older modules pinned to SDK 0.1.0 retain their explicit legacy wire path. SDK +0.2.0 does not fall back to legacy TF decoding. diff --git a/native/rust/dimos-module/src/lib.rs b/native/rust/dimos-module/src/lib.rs index 69ef3fcdac5..c2345519993 100644 --- a/native/rust/dimos-module/src/lib.rs +++ b/native/rust/dimos-module/src/lib.rs @@ -17,7 +17,6 @@ #[cfg(test)] extern crate self as dimos_module; -#[cfg(feature = "cdr")] pub mod cdr; pub mod host; pub mod lcm; @@ -34,7 +33,7 @@ pub use dimos_module_macros::{native_config, Module}; pub use host::{host_main, HostSpec, ModuleEntry}; pub use lcm::LcmTransport; pub use module::{run, Builder, Input, Io, Module, ModuleConfig, NativeConfig, NoConfig, Output}; -pub use tf::{Lookup, Tf, Transform}; +pub use tf::{Lookup, Tf, TransformStamped}; pub use transport::{SharedTransport, Transport}; pub use workers::worker_pool; pub use zenoh::ZenohTransport; diff --git a/native/rust/dimos-module/src/module.rs b/native/rust/dimos-module/src/module.rs index 01cfb7af63c..75b5aa44a94 100644 --- a/native/rust/dimos-module/src/module.rs +++ b/native/rust/dimos-module/src/module.rs @@ -414,41 +414,22 @@ impl Builder { } } - /// A handle that answers transform queries and publishes on the `tf` topic. - /// - /// The graph fills in the background as `tf` messages arrive. Repeated calls - /// share one graph. + /// Standard ROS TF streams. Dynamic and static messages share one frame tree. pub fn tf(&mut self) -> crate::tf::Tf { - self.tf_with_codec(crate::tf::decode_legacy, crate::tf::encode_legacy) - } - - /// Select TF wire codecs while retaining the same graph and lookup API. - /// Repeated calls share one graph and must select the same codec pair. - /// - /// # Panics - /// Panics if this module already selected a different pair for its TF topic. - pub fn tf_with_codec( - &mut self, - decode: crate::tf::DecodeTransforms, - encode: crate::tf::EncodeTransforms, - ) -> crate::tf::Tf { if let Some(tf) = &self.tf { - assert!( - tf.uses_codec(decode, encode), - "one TF topic cannot mix codec pairs" - ); return tf.clone(); } let topic = self.topic_for("tf"); + let static_topic = self.topic_for("tf_static"); let sender = self.add_publisher(&topic); - let (tf, route) = crate::tf::tf_subscription_with_codec( - topic.clone(), - crate::tf::DEFAULT_TF_WINDOW_SECS, - sender, - decode, - encode, - ); + let static_sender = self.add_publisher(&static_topic); + let (tf, route, static_route) = + crate::tf::tf_subscription(sender, static_sender, crate::tf::DEFAULT_TF_WINDOW); self.routes.entry(topic).or_default().push(route); + self.routes + .entry(static_topic) + .or_default() + .push(static_route); self.tf = Some(tf.clone()); tf } @@ -999,7 +980,10 @@ mod tests { #[test] fn a_tf_field_claims_the_tf_topic() { - let mut builder = builder_with_topics(&[("tf", "/tf#tf2_msgs.TFMessage")]); + let mut builder = builder_with_topics(&[ + ("tf", "/tf#tf2_msgs.TFMessage"), + ("tf_static", "/tf_static#tf2_msgs.TFMessage"), + ]); builder.tf(); builder.enforce_topics_match_ports().expect("tf claimed"); } @@ -1066,86 +1050,10 @@ mod tests { let mut builder = builder_with_topics(&[("tf", "/tf")]); builder.tf(); builder.tf(); - assert_eq!(builder.outputs.len(), 1); + assert_eq!(builder.outputs.len(), 2); assert_eq!(builder.routes.get("/tf").map(Vec::len), Some(1)); } - fn encode_tagged_tf(values: &[crate::tf::Transform]) -> io::Result> { - let mut bytes = b"test-tf:".to_vec(); - bytes.extend(crate::tf::encode_legacy(values)?); - Ok(bytes) - } - - fn decode_tagged_tf(bytes: &[u8]) -> io::Result> { - crate::tf::decode_legacy(bytes.strip_prefix(b"test-tf:").ok_or_else(|| { - io::Error::new(io::ErrorKind::InvalidData, "missing test codec prefix") - })?) - } - - #[derive(crate::Module)] - struct TaggedTfModule { - #[tf(decode = decode_tagged_tf, encode = encode_tagged_tf)] - tf: crate::tf::Tf, - } - - #[tokio::test] - async fn derived_tf_field_uses_selected_codecs_for_publish_and_receive() { - let mut sender = builder_with_topics(&[("tf", "/robot/tf")]); - let mut receiver = builder_with_topics(&[("tf", "/robot/tf")]); - let producer = TaggedTfModule::build(&mut sender, NoConfig); - let consumer = TaggedTfModule::build(&mut receiver, NoConfig); - let edge = crate::tf::Transform::new( - "map", - "camera", - 3.25, - nalgebra::Isometry3::translation(1.0, 2.0, 3.0), - ); - producer.tf.publish(&[edge]).await.unwrap(); - let bytes = sender.outputs[0].1.recv().await.unwrap(); - assert!(bytes.starts_with(b"test-tf:")); - receiver.routes["/robot/tf"][0].try_dispatch(b"wrong codec"); - assert!(consumer.tf.get_latest("map", "camera").is_none()); - receiver.routes["/robot/tf"][0].try_dispatch(&bytes); - let found = consumer.tf.get_latest("map", "camera").unwrap(); - assert_eq!(found.translation(), nalgebra::Vector3::new(1.0, 2.0, 3.0)); - assert_eq!(found.ts, 3.25); - receiver.tf_with_codec(decode_tagged_tf, encode_tagged_tf); - assert_eq!(receiver.outputs.len(), 1); - assert_eq!(receiver.routes["/robot/tf"].len(), 1); - } - - #[test] - #[should_panic(expected = "one TF topic cannot mix codec pairs")] - fn tf_rejects_mixed_codecs_on_one_topic() { - let mut builder = builder_with_topics(&[("tf", "/tf")]); - builder.tf_with_codec(decode_tagged_tf, encode_tagged_tf); - builder.tf(); - } - - #[tokio::test] - async fn tf_encode_error_does_not_publish_or_change_the_local_graph() { - fn reject(_: &[crate::tf::Transform]) -> io::Result> { - Err(io::Error::new( - io::ErrorKind::InvalidData, - "unencodable transform", - )) - } - let mut builder = builder_with_topics(&[("tf", "/tf")]); - let tf = builder.tf_with_codec(decode_tagged_tf, reject); - let edge = - crate::tf::Transform::new("map", "camera", 3.25, nalgebra::Isometry3::identity()); - let error = tf - .publish(&[edge]) - .await - .expect_err("codec error must reach the caller"); - assert_eq!(error.kind(), io::ErrorKind::InvalidData); - assert!(tf.get_latest("map", "camera").is_none()); - assert!(matches!( - builder.outputs[0].1.try_recv(), - Err(tokio::sync::mpsc::error::TryRecvError::Empty) - )); - } - #[tokio::test] async fn port_encode_error_does_not_enqueue_or_close_the_port() { fn encode(value: &Vec) -> io::Result> { diff --git a/native/rust/dimos-module/src/tf.rs b/native/rust/dimos-module/src/tf.rs index 04865ef86c3..314e4bbe74a 100644 --- a/native/rust/dimos-module/src/tf.rs +++ b/native/rust/dimos-module/src/tf.rs @@ -12,1397 +12,604 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Transform client for native modules. -//! -//! Each `/tf` edge is buffered per `(parent, child)`, and [`Tf::lookup`] composes -//! the shortest path through the frame graph. Lookups are nearest-in-time within -//! a tolerance, not interpolated. [`Tf::publish`] sends transforms onto the same -//! topic and feeds the local graph. - -use std::collections::{HashMap, HashSet, VecDeque}; -use std::io; -use std::sync::atomic::AtomicU64; -use std::sync::{Arc, Mutex, RwLock}; -use std::time::Duration; - -use nalgebra::{Isometry3, Quaternion, Translation3, UnitQuaternion, Vector3}; -use tokio::sync::{mpsc, Notify}; -use tracing::warn; +//! ROS TF messages backed by the `transforms` frame tree. use crate::module::Route; -use crate::time::now_secs; - -/// How many seconds of history each edge keeps. -pub(crate) const DEFAULT_TF_WINDOW_SECS: f64 = 10.0; - -const WARN_INTERVAL: Duration = Duration::from_secs(1); - -/// A rigid transform from `parent` to `child` at a point in time. -/// -/// It maps a point expressed in `child` coordinates into `parent` coordinates. -#[derive(Clone, Debug)] -pub struct Transform { - pub parent: String, - pub child: String, - pub ts: f64, - stamp_ns: Option, - iso: Isometry3, +use nalgebra::{Isometry3, Quaternion, Translation3, UnitQuaternion}; +use std::{ + io, + sync::{Arc, RwLock}, + time::{Duration, SystemTime, UNIX_EPOCH}, +}; +use tokio::sync::{mpsc, Notify}; +use transforms::{ + geometry::{ + Quaternion as FrameQuaternion, Transform as FrameTransform, Vector3 as FrameVector, + }, + time::Stamp, + Registry, +}; + +pub use dimos_tf_messages::{ + builtin_interfaces::msg::time::Time, geometry_msgs::msg::transform_stamped::TransformStamped, + tf2_msgs::msg::tf_message::TFMessage, +}; +use dimos_tf_messages::{ + geometry_msgs::msg::{ + quaternion::Quaternion as WireQuaternion, transform::Transform, vector3::Vector3, + }, + std_msgs::msg::header::Header, +}; + +pub(crate) const DEFAULT_TF_WINDOW: Duration = Duration::from_secs(10); + +fn invalid(error: impl std::fmt::Display) -> io::Error { + io::Error::new(io::ErrorKind::InvalidData, error.to_string()) } -impl Transform { - pub fn new( - parent: impl Into, - child: impl Into, - ts: f64, - iso: Isometry3, - ) -> Self { - Self { - parent: parent.into(), - child: child.into(), - ts, - stamp_ns: None, - iso, - } - } - - /// Retain a wire timestamp without passing its nanoseconds through a float. - /// The existing `ts` field remains available for seconds-based math. - pub fn from_nanoseconds( - parent: impl Into, - child: impl Into, - stamp_ns: i64, - iso: Isometry3, - ) -> Self { - Self { - parent: parent.into(), - child: child.into(), - ts: stamp_ns as f64 / 1_000_000_000., - stamp_ns: Some(stamp_ns), - iso, - } - } - - /// Exact source time, or rounded seconds for values made with `new`. - /// A caller updating the public `ts` field invalidates saved wire metadata. - pub fn stamp_nanoseconds(&self) -> Option { - if let Some(ns) = self.stamp_ns { - if self.ts == ns as f64 / 1_000_000_000. { - return Some(ns); - } - } - let ns = (self.ts * 1_000_000_000.).round(); - (ns.is_finite() && ns >= i64::MIN as f64 && ns < i64::MAX as f64).then_some(ns as i64) - } - - pub fn translation(&self) -> Vector3 { - self.iso.translation.vector - } - - pub fn rotation(&self) -> UnitQuaternion { - self.iso.rotation - } - - fn inverse(&self) -> Transform { - Transform { - parent: self.child.clone(), - child: self.parent.clone(), - ts: self.ts, - stamp_ns: self.stamp_ns, - iso: self.iso.inverse(), - } - } - - fn compose(&self, other: &Transform) -> Transform { - Transform { - parent: self.parent.clone(), - child: other.child.clone(), - ts: self.ts, - stamp_ns: self.stamp_ns, - iso: self.iso * other.iso, - } +pub fn nanoseconds(time: &Time) -> io::Result { + if time.nanosec >= 1_000_000_000 { + return Err(invalid("unnormalized ROS time")); } + Ok(i64::from(time.sec) * 1_000_000_000 + i64::from(time.nanosec)) } -struct Sample { - ts: f64, - stamp_ns: Option, - iso: Isometry3, +pub fn time_from_nanoseconds(ns: i64) -> io::Result