├── .dockerignore ├── .gitattributes ├── pyproject.toml ├── .flake8 ├── Pipfile ├── .vscode └── settings.json ├── .gitignore ├── event_helpers ├── __init__.py ├── client_utils.py └── annotators.py ├── docker-compose.yml ├── device_name.py ├── Dockerfile ├── nuscenes2bag ├── Dockerfile ├── can_utils.py ├── annotation_utils.py ├── sensor_utils.py └── map_utils.py ├── convert_mini_scenes.sh ├── convert_to_ros2bag.sh ├── .github └── workflows │ └── lint.yml ├── foxglove ├── GeoJSON_pb2.pyi ├── Point2_pb2.pyi ├── Vector2_pb2.pyi ├── KeyValuePair_pb2.pyi ├── GeoJSON_pb2.py ├── Point3_pb2.pyi ├── Vector3_pb2.pyi ├── Point2_pb2.py ├── Vector2_pb2.py ├── Point3_pb2.py ├── Vector3_pb2.py ├── KeyValuePair_pb2.py ├── Color_pb2.py ├── Quaternion_pb2.py ├── Color_pb2.pyi ├── Quaternion_pb2.pyi ├── Pose_pb2.py ├── CompressedImage_pb2.py ├── PoseInFrame_pb2.py ├── SceneUpdate_pb2.py ├── PosesInFrame_pb2.py ├── RawImage_pb2.py ├── ImageAnnotations_pb2.py ├── Pose_pb2.pyi ├── CubePrimitive_pb2.py ├── TextPrimitive_pb2.py ├── SpherePrimitive_pb2.py ├── ArrowPrimitive_pb2.py ├── ImageAnnotations_pb2.pyi ├── CameraCalibration_pb2.py ├── LaserScan_pb2.py ├── SceneEntityDeletion_pb2.py ├── LocationFix_pb2.py ├── PoseInFrame_pb2.pyi ├── SceneUpdate_pb2.pyi ├── PackedElementField_pb2.py ├── CylinderPrimitive_pb2.py ├── Log_pb2.py ├── TriangleListPrimitive_pb2.py ├── ModelPrimitive_pb2.py ├── FrameTransform_pb2.py ├── PointCloud_pb2.py ├── CubePrimitive_pb2.pyi ├── CircleAnnotation_pb2.py ├── SpherePrimitive_pb2.pyi ├── PosesInFrame_pb2.pyi ├── CompressedImage_pb2.pyi ├── Grid_pb2.py ├── LinePrimitive_pb2.py ├── PointsAnnotation_pb2.py ├── RawImage_pb2.pyi ├── FrameTransform_pb2.pyi ├── ArrowPrimitive_pb2.pyi ├── CylinderPrimitive_pb2.pyi ├── TextPrimitive_pb2.pyi ├── CircleAnnotation_pb2.pyi ├── PointCloud_pb2.pyi ├── SceneEntityDeletion_pb2.pyi ├── Log_pb2.pyi ├── LaserScan_pb2.pyi ├── ModelPrimitive_pb2.pyi ├── PackedElementField_pb2.pyi ├── TriangleListPrimitive_pb2.pyi ├── SceneEntity_pb2.py ├── Grid_pb2.pyi ├── LocationFix_pb2.pyi ├── PointsAnnotation_pb2.pyi ├── LinePrimitive_pb2.pyi ├── CameraCalibration_pb2.pyi └── SceneEntity_pb2.pyi ├── LICENSE ├── .devcontainer └── devcontainer.json ├── delete_all_events.py ├── ProtobufWriter.py ├── vm_helpers ├── ready_scratch_disk.py └── Makefile ├── RosmsgWriter.py ├── upload_mcap.py ├── can.py ├── README.md ├── upload_events.py ├── Pipfile.lock └── turbomap.json /.dockerignore: -------------------------------------------------------------------------------- 1 | data/ 2 | output/ 3 | *.tgz 4 | *.zip 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | foxglove/** linguist-vendored linguist-generated 2 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | exclude = "foxglove/.*_pb2.py.*" 3 | line-length = 160 4 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 160 3 | ignore = E203 4 | exclude = 5 | foxglove/*pb2.py*, 6 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [dev-packages] 2 | flake8 = "*" 3 | black = "*" 4 | 5 | [requires] 6 | python_version = "3" 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.formatting.provider": "black", 3 | "[python]": { 4 | "editor.formatOnSave": true 5 | } 6 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bag 2 | *.tgz 3 | *.zip 4 | .ipynb_checkpoints 5 | data 6 | __pycache__ 7 | *.mcap 8 | output 9 | 10 | # Byte-compiled / optimized / DLL files 11 | __pycache__/ 12 | 13 | # Distribution / packaging 14 | build/ 15 | install/ 16 | log/ 17 | 18 | -------------------------------------------------------------------------------- /event_helpers/__init__.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | from typing import Dict 3 | 4 | 5 | @dataclass 6 | class Event: 7 | timestamp_ns: int 8 | duration_ns: int 9 | metadata: Dict[str, str] = field(default_factory=dict) 10 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | rosbag_service: 4 | image: rosbag_image 5 | build: 6 | context: . 7 | dockerfile: ./Dockerfile 8 | volumes: 9 | - .:/work 10 | command: sleep inf 11 | -------------------------------------------------------------------------------- /device_name.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | from typing import Dict 3 | 4 | 5 | def make_device_name(metadata: Dict[str, str]) -> str: 6 | """constructs a synthetic device name from vehicle name and location.""" 7 | vehicle = metadata["vehicle"] 8 | location = metadata["location"] 9 | return hashlib.sha256((vehicle + location).encode("utf8")).hexdigest()[:6] 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ros:noetic-ros-core 2 | 3 | RUN apt-get update 4 | RUN apt-get install -y git python3-pip python3-tf2-ros ros-noetic-foxglove-msgs libgl1 libgeos-dev 5 | RUN rm -rf /var/lib/apt/lists/* 6 | 7 | RUN pip3 install shapely==1.8.* numpy==1.19 nuscenes-devkit mcap 'mcap-protobuf-support>=0.0.8' foxglove-data-platform tqdm requests protobuf 8 | RUN pip3 install git+https://github.com/DanielPollithy/pypcd.git 9 | 10 | COPY . /work 11 | 12 | WORKDIR /work 13 | -------------------------------------------------------------------------------- /nuscenes2bag/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ros:humble-ros-core 2 | 3 | RUN apt-get update 4 | RUN apt-get install -y git python3-pip python3-tf2-ros libgl1 libgeos-dev ros-humble-ros2bag ros-humble-rosbag2* ros-humble-foxglove-msgs ros-humble-tf2-tools ros-humble-tf-transformations 5 | RUN apt install -y python3-colcon-common-extensions 6 | 7 | RUN rm -rf /var/lib/apt/lists/* 8 | 9 | RUN pip3 install shapely numpy==1.26.4 nuscenes-devkit mcap tqdm requests 10 | RUN pip3 install git+https://github.com/DanielPollithy/pypcd.git 11 | 12 | COPY . /work 13 | 14 | WORKDIR /work 15 | -------------------------------------------------------------------------------- /convert_mini_scenes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | # This script is an example usage of `convert_to_mcap.py` to convert the nuScenes mini-v1.0 dataset to MCAP. 4 | 5 | if [ ! -d "data" ]; then 6 | echo "data dir does not exist: please create and extract nuScenes data into it." 7 | exit 1 8 | fi 9 | 10 | docker build -t mcap_converter . 11 | mkdir -p output 12 | docker run -t --rm \ 13 | --user $(id -u):$(id -g) \ 14 | -v $(pwd)/data:/data -v $(pwd)/output:/output \ 15 | mcap_converter python3 convert_to_mcap.py --data-dir /data --output-dir /output "$@" 16 | -------------------------------------------------------------------------------- /convert_to_ros2bag.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | # This script is an example usage of `convert_to_bag.py` to convert the nuScenes mini-v1.0 dataset to MCAP. 4 | 5 | if [ ! -d "data" ]; then 6 | echo "data dir does not exist: please create and extract nuScenes data into it." 7 | exit 1 8 | fi 9 | 10 | docker build -t mcap_converter . -f nuscenes2bag/Dockerfile 11 | mkdir -p output 12 | docker run -t --rm \ 13 | --user $(id -u):$(id -g) \ 14 | -v $(pwd)/data:/data -v $(pwd)/output:/output \ 15 | mcap_converter python3 nuscenes2bag/convert_to_bag.py --data-dir /data --output-dir /output "$@" -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | "on": 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: ["*"] 8 | 9 | jobs: 10 | lint-python: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | with: 15 | lfs: true 16 | - uses: actions/setup-python@v4 17 | with: 18 | python-version: 3.7 19 | cache: pipenv 20 | - uses: satackey/action-docker-layer-caching@v0.0.11 21 | continue-on-error: true 22 | - run: pip install pipenv 23 | - run: pipenv install --dev --deploy 24 | - run: pipenv run python -m flake8 25 | - run: pipenv run black --check --diff --color . 26 | -------------------------------------------------------------------------------- /event_helpers/client_utils.py: -------------------------------------------------------------------------------- 1 | from foxglove_data_platform.client import Client 2 | from datetime import datetime 3 | from typing import Optional 4 | 5 | PAGE_LENGTH = 100 6 | 7 | 8 | def get_all_events_for_device(client: Client, device_id: str, start: Optional[datetime] = None, end: Optional[datetime] = None): 9 | """The client.get_events API is paginated, meaning to successfully find all events 10 | we must call the API repeatedly with a changing offset. 11 | """ 12 | all_events = [] 13 | offset = 0 14 | while True: 15 | events_returned = client.get_events(device_id=device_id, start=start, end=end, limit=PAGE_LENGTH, offset=offset) 16 | all_events.extend(events_returned) 17 | offset += len(events_returned) 18 | if len(events_returned) != PAGE_LENGTH: 19 | return all_events 20 | -------------------------------------------------------------------------------- /foxglove/GeoJSON_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.message 8 | import typing 9 | import typing_extensions 10 | 11 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 12 | 13 | class GeoJSON(google.protobuf.message.Message): 14 | """GeoJSON data for annotating maps""" 15 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 16 | GEOJSON_FIELD_NUMBER: builtins.int 17 | geojson: typing.Text 18 | """GeoJSON data encoded as a UTF-8 string""" 19 | 20 | def __init__(self, 21 | *, 22 | geojson: typing.Text = ..., 23 | ) -> None: ... 24 | def ClearField(self, field_name: typing_extensions.Literal["geojson",b"geojson"]) -> None: ... 25 | global___GeoJSON = GeoJSON 26 | -------------------------------------------------------------------------------- /foxglove/Point2_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.message 8 | import typing_extensions 9 | 10 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 11 | 12 | class Point2(google.protobuf.message.Message): 13 | """A point representing a position in 2D space""" 14 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 15 | X_FIELD_NUMBER: builtins.int 16 | Y_FIELD_NUMBER: builtins.int 17 | x: builtins.float 18 | """x coordinate position""" 19 | 20 | y: builtins.float 21 | """y coordinate position""" 22 | 23 | def __init__(self, 24 | *, 25 | x: builtins.float = ..., 26 | y: builtins.float = ..., 27 | ) -> None: ... 28 | def ClearField(self, field_name: typing_extensions.Literal["x",b"x","y",b"y"]) -> None: ... 29 | global___Point2 = Point2 30 | -------------------------------------------------------------------------------- /foxglove/Vector2_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.message 8 | import typing_extensions 9 | 10 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 11 | 12 | class Vector2(google.protobuf.message.Message): 13 | """A vector in 2D space that represents a direction only""" 14 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 15 | X_FIELD_NUMBER: builtins.int 16 | Y_FIELD_NUMBER: builtins.int 17 | x: builtins.float 18 | """x coordinate length""" 19 | 20 | y: builtins.float 21 | """y coordinate length""" 22 | 23 | def __init__(self, 24 | *, 25 | x: builtins.float = ..., 26 | y: builtins.float = ..., 27 | ) -> None: ... 28 | def ClearField(self, field_name: typing_extensions.Literal["x",b"x","y",b"y"]) -> None: ... 29 | global___Vector2 = Vector2 30 | -------------------------------------------------------------------------------- /foxglove/KeyValuePair_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.message 8 | import typing 9 | import typing_extensions 10 | 11 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 12 | 13 | class KeyValuePair(google.protobuf.message.Message): 14 | """(Experimental, subject to change) A key with its associated value""" 15 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 16 | KEY_FIELD_NUMBER: builtins.int 17 | VALUE_FIELD_NUMBER: builtins.int 18 | key: typing.Text 19 | """Key""" 20 | 21 | value: typing.Text 22 | """Value""" 23 | 24 | def __init__(self, 25 | *, 26 | key: typing.Text = ..., 27 | value: typing.Text = ..., 28 | ) -> None: ... 29 | def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ... 30 | global___KeyValuePair = KeyValuePair 31 | -------------------------------------------------------------------------------- /foxglove/GeoJSON_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/GeoJSON.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66oxglove/GeoJSON.proto\x12\x08\x66oxglove\"\x1a\n\x07GeoJSON\x12\x0f\n\x07geojson\x18\x01 \x01(\tb\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.GeoJSON_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _GEOJSON._serialized_start=36 24 | _GEOJSON._serialized_end=62 25 | # @@protoc_insertion_point(module_scope) 26 | -------------------------------------------------------------------------------- /foxglove/Point3_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.message 8 | import typing_extensions 9 | 10 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 11 | 12 | class Point3(google.protobuf.message.Message): 13 | """A point representing a position in 3D space""" 14 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 15 | X_FIELD_NUMBER: builtins.int 16 | Y_FIELD_NUMBER: builtins.int 17 | Z_FIELD_NUMBER: builtins.int 18 | x: builtins.float 19 | """x coordinate position""" 20 | 21 | y: builtins.float 22 | """y coordinate position""" 23 | 24 | z: builtins.float 25 | """z coordinate position""" 26 | 27 | def __init__(self, 28 | *, 29 | x: builtins.float = ..., 30 | y: builtins.float = ..., 31 | z: builtins.float = ..., 32 | ) -> None: ... 33 | def ClearField(self, field_name: typing_extensions.Literal["x",b"x","y",b"y","z",b"z"]) -> None: ... 34 | global___Point3 = Point3 35 | -------------------------------------------------------------------------------- /foxglove/Vector3_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.message 8 | import typing_extensions 9 | 10 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 11 | 12 | class Vector3(google.protobuf.message.Message): 13 | """A vector in 3D space that represents a direction only""" 14 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 15 | X_FIELD_NUMBER: builtins.int 16 | Y_FIELD_NUMBER: builtins.int 17 | Z_FIELD_NUMBER: builtins.int 18 | x: builtins.float 19 | """x coordinate length""" 20 | 21 | y: builtins.float 22 | """y coordinate length""" 23 | 24 | z: builtins.float 25 | """z coordinate length""" 26 | 27 | def __init__(self, 28 | *, 29 | x: builtins.float = ..., 30 | y: builtins.float = ..., 31 | z: builtins.float = ..., 32 | ) -> None: ... 33 | def ClearField(self, field_name: typing_extensions.Literal["x",b"x","y",b"y","z",b"z"]) -> None: ... 34 | global___Vector3 = Vector3 35 | -------------------------------------------------------------------------------- /foxglove/Point2_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/Point2.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66oxglove/Point2.proto\x12\x08\x66oxglove\"\x1e\n\x06Point2\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x62\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.Point2_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _POINT2._serialized_start=35 24 | _POINT2._serialized_end=65 25 | # @@protoc_insertion_point(module_scope) 26 | -------------------------------------------------------------------------------- /foxglove/Vector2_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/Vector2.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66oxglove/Vector2.proto\x12\x08\x66oxglove\"\x1f\n\x07Vector2\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x62\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.Vector2_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _VECTOR2._serialized_start=36 24 | _VECTOR2._serialized_end=67 25 | # @@protoc_insertion_point(module_scope) 26 | -------------------------------------------------------------------------------- /foxglove/Point3_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/Point3.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66oxglove/Point3.proto\x12\x08\x66oxglove\")\n\x06Point3\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x12\t\n\x01z\x18\x03 \x01(\x01\x62\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.Point3_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _POINT3._serialized_start=35 24 | _POINT3._serialized_end=76 25 | # @@protoc_insertion_point(module_scope) 26 | -------------------------------------------------------------------------------- /foxglove/Vector3_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/Vector3.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66oxglove/Vector3.proto\x12\x08\x66oxglove\"*\n\x07Vector3\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x12\t\n\x01z\x18\x03 \x01(\x01\x62\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.Vector3_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _VECTOR3._serialized_start=36 24 | _VECTOR3._serialized_end=78 25 | # @@protoc_insertion_point(module_scope) 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Foxglove Technologies Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /foxglove/KeyValuePair_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/KeyValuePair.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1b\x66oxglove/KeyValuePair.proto\x12\x08\x66oxglove\"*\n\x0cKeyValuePair\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\tb\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.KeyValuePair_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _KEYVALUEPAIR._serialized_start=41 24 | _KEYVALUEPAIR._serialized_end=83 25 | # @@protoc_insertion_point(module_scope) 26 | -------------------------------------------------------------------------------- /foxglove/Color_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/Color.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x66oxglove/Color.proto\x12\x08\x66oxglove\"3\n\x05\x43olor\x12\t\n\x01r\x18\x01 \x01(\x01\x12\t\n\x01g\x18\x02 \x01(\x01\x12\t\n\x01\x62\x18\x03 \x01(\x01\x12\t\n\x01\x61\x18\x04 \x01(\x01\x62\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.Color_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _COLOR._serialized_start=34 24 | _COLOR._serialized_end=85 25 | # @@protoc_insertion_point(module_scope) 26 | -------------------------------------------------------------------------------- /foxglove/Quaternion_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/Quaternion.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x66oxglove/Quaternion.proto\x12\x08\x66oxglove\"8\n\nQuaternion\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x12\t\n\x01z\x18\x03 \x01(\x01\x12\t\n\x01w\x18\x04 \x01(\x01\x62\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.Quaternion_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _QUATERNION._serialized_start=39 24 | _QUATERNION._serialized_end=95 25 | # @@protoc_insertion_point(module_scope) 26 | -------------------------------------------------------------------------------- /foxglove/Color_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.message 8 | import typing_extensions 9 | 10 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 11 | 12 | class Color(google.protobuf.message.Message): 13 | """A color in RGBA format""" 14 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 15 | R_FIELD_NUMBER: builtins.int 16 | G_FIELD_NUMBER: builtins.int 17 | B_FIELD_NUMBER: builtins.int 18 | A_FIELD_NUMBER: builtins.int 19 | r: builtins.float 20 | """Red value between 0 and 1""" 21 | 22 | g: builtins.float 23 | """Green value between 0 and 1""" 24 | 25 | b: builtins.float 26 | """Blue value between 0 and 1""" 27 | 28 | a: builtins.float 29 | """Alpha value between 0 and 1""" 30 | 31 | def __init__(self, 32 | *, 33 | r: builtins.float = ..., 34 | g: builtins.float = ..., 35 | b: builtins.float = ..., 36 | a: builtins.float = ..., 37 | ) -> None: ... 38 | def ClearField(self, field_name: typing_extensions.Literal["a",b"a","b",b"b","g",b"g","r",b"r"]) -> None: ... 39 | global___Color = Color 40 | -------------------------------------------------------------------------------- /foxglove/Quaternion_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.message 8 | import typing_extensions 9 | 10 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 11 | 12 | class Quaternion(google.protobuf.message.Message): 13 | """A [quaternion](https://eater.net/quaternions) representing a rotation in 3D space""" 14 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 15 | X_FIELD_NUMBER: builtins.int 16 | Y_FIELD_NUMBER: builtins.int 17 | Z_FIELD_NUMBER: builtins.int 18 | W_FIELD_NUMBER: builtins.int 19 | x: builtins.float 20 | """x value""" 21 | 22 | y: builtins.float 23 | """y value""" 24 | 25 | z: builtins.float 26 | """z value""" 27 | 28 | w: builtins.float 29 | """w value""" 30 | 31 | def __init__(self, 32 | *, 33 | x: builtins.float = ..., 34 | y: builtins.float = ..., 35 | z: builtins.float = ..., 36 | w: builtins.float = ..., 37 | ) -> None: ... 38 | def ClearField(self, field_name: typing_extensions.Literal["w",b"w","x",b"x","y",b"y","z",b"z"]) -> None: ... 39 | global___Quaternion = Quaternion 40 | -------------------------------------------------------------------------------- /foxglove/Pose_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/Pose.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Quaternion_pb2 as foxglove_dot_Quaternion__pb2 15 | from foxglove import Vector3_pb2 as foxglove_dot_Vector3__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13\x66oxglove/Pose.proto\x12\x08\x66oxglove\x1a\x19\x66oxglove/Quaternion.proto\x1a\x16\x66oxglove/Vector3.proto\"V\n\x04Pose\x12#\n\x08position\x18\x01 \x01(\x0b\x32\x11.foxglove.Vector3\x12)\n\x0borientation\x18\x02 \x01(\x0b\x32\x14.foxglove.Quaternionb\x06proto3') 19 | 20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.Pose_pb2', globals()) 22 | if _descriptor._USE_C_DESCRIPTORS == False: 23 | 24 | DESCRIPTOR._options = None 25 | _POSE._serialized_start=84 26 | _POSE._serialized_end=170 27 | # @@protoc_insertion_point(module_scope) 28 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.241.1/containers/docker-existing-dockerfile 3 | { 4 | "name": "Existing Dockerfile", 5 | 6 | // Sets the run context to one level up instead of the .devcontainer folder. 7 | "context": "..", 8 | 9 | // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename. 10 | "dockerFile": "../Dockerfile" 11 | 12 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 13 | // "forwardPorts": [], 14 | 15 | // Uncomment the next line to run commands after the container is created - for example installing curl. 16 | // "postCreateCommand": "apt-get update && apt-get install -y curl", 17 | 18 | // Uncomment when using a ptrace-based debugger like C++, Go, and Rust 19 | // "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], 20 | 21 | // Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker. 22 | // "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ], 23 | 24 | // Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root. 25 | // "remoteUser": "vscode" 26 | } 27 | -------------------------------------------------------------------------------- /foxglove/CompressedImage_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/CompressedImage.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1e\x66oxglove/CompressedImage.proto\x12\x08\x66oxglove\x1a\x1fgoogle/protobuf/timestamp.proto\"p\n\x0f\x43ompressedImage\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x66rame_id\x18\x04 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x0e\n\x06\x66ormat\x18\x03 \x01(\tb\x06proto3') 18 | 19 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 20 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.CompressedImage_pb2', globals()) 21 | if _descriptor._USE_C_DESCRIPTORS == False: 22 | 23 | DESCRIPTOR._options = None 24 | _COMPRESSEDIMAGE._serialized_start=77 25 | _COMPRESSEDIMAGE._serialized_end=189 26 | # @@protoc_insertion_point(module_scope) 27 | -------------------------------------------------------------------------------- /foxglove/PoseInFrame_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/PoseInFrame.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 15 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x66oxglove/PoseInFrame.proto\x12\x08\x66oxglove\x1a\x13\x66oxglove/Pose.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"l\n\x0bPoseInFrame\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x66rame_id\x18\x02 \x01(\t\x12\x1c\n\x04pose\x18\x03 \x01(\x0b\x32\x0e.foxglove.Poseb\x06proto3') 19 | 20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.PoseInFrame_pb2', globals()) 22 | if _descriptor._USE_C_DESCRIPTORS == False: 23 | 24 | DESCRIPTOR._options = None 25 | _POSEINFRAME._serialized_start=94 26 | _POSEINFRAME._serialized_end=202 27 | # @@protoc_insertion_point(module_scope) 28 | -------------------------------------------------------------------------------- /foxglove/SceneUpdate_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/SceneUpdate.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import SceneEntity_pb2 as foxglove_dot_SceneEntity__pb2 15 | from foxglove import SceneEntityDeletion_pb2 as foxglove_dot_SceneEntityDeletion__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x66oxglove/SceneUpdate.proto\x12\x08\x66oxglove\x1a\x1a\x66oxglove/SceneEntity.proto\x1a\"foxglove/SceneEntityDeletion.proto\"h\n\x0bSceneUpdate\x12\x30\n\tdeletions\x18\x01 \x03(\x0b\x32\x1d.foxglove.SceneEntityDeletion\x12\'\n\x08\x65ntities\x18\x02 \x03(\x0b\x32\x15.foxglove.SceneEntityb\x06proto3') 19 | 20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.SceneUpdate_pb2', globals()) 22 | if _descriptor._USE_C_DESCRIPTORS == False: 23 | 24 | DESCRIPTOR._options = None 25 | _SCENEUPDATE._serialized_start=104 26 | _SCENEUPDATE._serialized_end=208 27 | # @@protoc_insertion_point(module_scope) 28 | -------------------------------------------------------------------------------- /foxglove/PosesInFrame_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/PosesInFrame.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 15 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1b\x66oxglove/PosesInFrame.proto\x12\x08\x66oxglove\x1a\x13\x66oxglove/Pose.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"n\n\x0cPosesInFrame\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x66rame_id\x18\x02 \x01(\t\x12\x1d\n\x05poses\x18\x03 \x03(\x0b\x32\x0e.foxglove.Poseb\x06proto3') 19 | 20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.PosesInFrame_pb2', globals()) 22 | if _descriptor._USE_C_DESCRIPTORS == False: 23 | 24 | DESCRIPTOR._options = None 25 | _POSESINFRAME._serialized_start=95 26 | _POSESINFRAME._serialized_end=205 27 | # @@protoc_insertion_point(module_scope) 28 | -------------------------------------------------------------------------------- /foxglove/RawImage_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/RawImage.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x66oxglove/RawImage.proto\x12\x08\x66oxglove\x1a\x1fgoogle/protobuf/timestamp.proto\"\x98\x01\n\x08RawImage\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x66rame_id\x18\x07 \x01(\t\x12\r\n\x05width\x18\x02 \x01(\x07\x12\x0e\n\x06height\x18\x03 \x01(\x07\x12\x10\n\x08\x65ncoding\x18\x04 \x01(\t\x12\x0c\n\x04step\x18\x05 \x01(\x07\x12\x0c\n\x04\x64\x61ta\x18\x06 \x01(\x0c\x62\x06proto3') 18 | 19 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 20 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.RawImage_pb2', globals()) 21 | if _descriptor._USE_C_DESCRIPTORS == False: 22 | 23 | DESCRIPTOR._options = None 24 | _RAWIMAGE._serialized_start=71 25 | _RAWIMAGE._serialized_end=223 26 | # @@protoc_insertion_point(module_scope) 27 | -------------------------------------------------------------------------------- /foxglove/ImageAnnotations_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/ImageAnnotations.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import CircleAnnotation_pb2 as foxglove_dot_CircleAnnotation__pb2 15 | from foxglove import PointsAnnotation_pb2 as foxglove_dot_PointsAnnotation__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1f\x66oxglove/ImageAnnotations.proto\x12\x08\x66oxglove\x1a\x1f\x66oxglove/CircleAnnotation.proto\x1a\x1f\x66oxglove/PointsAnnotation.proto\"k\n\x10ImageAnnotations\x12+\n\x07\x63ircles\x18\x01 \x03(\x0b\x32\x1a.foxglove.CircleAnnotation\x12*\n\x06points\x18\x02 \x03(\x0b\x32\x1a.foxglove.PointsAnnotationb\x06proto3') 19 | 20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.ImageAnnotations_pb2', globals()) 22 | if _descriptor._USE_C_DESCRIPTORS == False: 23 | 24 | DESCRIPTOR._options = None 25 | _IMAGEANNOTATIONS._serialized_start=111 26 | _IMAGEANNOTATIONS._serialized_end=218 27 | # @@protoc_insertion_point(module_scope) 28 | -------------------------------------------------------------------------------- /foxglove/Pose_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Quaternion_pb2 7 | import foxglove.Vector3_pb2 8 | import google.protobuf.descriptor 9 | import google.protobuf.message 10 | import typing 11 | import typing_extensions 12 | 13 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 14 | 15 | class Pose(google.protobuf.message.Message): 16 | """A position and orientation for an object or reference frame in 3D space""" 17 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 18 | POSITION_FIELD_NUMBER: builtins.int 19 | ORIENTATION_FIELD_NUMBER: builtins.int 20 | @property 21 | def position(self) -> foxglove.Vector3_pb2.Vector3: 22 | """Point denoting position in 3D space""" 23 | pass 24 | @property 25 | def orientation(self) -> foxglove.Quaternion_pb2.Quaternion: 26 | """Quaternion denoting orientation in 3D space""" 27 | pass 28 | def __init__(self, 29 | *, 30 | position: typing.Optional[foxglove.Vector3_pb2.Vector3] = ..., 31 | orientation: typing.Optional[foxglove.Quaternion_pb2.Quaternion] = ..., 32 | ) -> None: ... 33 | def HasField(self, field_name: typing_extensions.Literal["orientation",b"orientation","position",b"position"]) -> builtins.bool: ... 34 | def ClearField(self, field_name: typing_extensions.Literal["orientation",b"orientation","position",b"position"]) -> None: ... 35 | global___Pose = Pose 36 | -------------------------------------------------------------------------------- /foxglove/CubePrimitive_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/CubePrimitive.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Color_pb2 as foxglove_dot_Color__pb2 15 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 16 | from foxglove import Vector3_pb2 as foxglove_dot_Vector3__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66oxglove/CubePrimitive.proto\x12\x08\x66oxglove\x1a\x14\x66oxglove/Color.proto\x1a\x13\x66oxglove/Pose.proto\x1a\x16\x66oxglove/Vector3.proto\"n\n\rCubePrimitive\x12\x1c\n\x04pose\x18\x01 \x01(\x0b\x32\x0e.foxglove.Pose\x12\x1f\n\x04size\x18\x02 \x01(\x0b\x32\x11.foxglove.Vector3\x12\x1e\n\x05\x63olor\x18\x03 \x01(\x0b\x32\x0f.foxglove.Colorb\x06proto3') 20 | 21 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 22 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.CubePrimitive_pb2', globals()) 23 | if _descriptor._USE_C_DESCRIPTORS == False: 24 | 25 | DESCRIPTOR._options = None 26 | _CUBEPRIMITIVE._serialized_start=109 27 | _CUBEPRIMITIVE._serialized_end=219 28 | # @@protoc_insertion_point(module_scope) 29 | -------------------------------------------------------------------------------- /foxglove/TextPrimitive_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/TextPrimitive.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Color_pb2 as foxglove_dot_Color__pb2 15 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66oxglove/TextPrimitive.proto\x12\x08\x66oxglove\x1a\x14\x66oxglove/Color.proto\x1a\x13\x66oxglove/Pose.proto\"\x9a\x01\n\rTextPrimitive\x12\x1c\n\x04pose\x18\x01 \x01(\x0b\x32\x0e.foxglove.Pose\x12\x11\n\tbillboard\x18\x02 \x01(\x08\x12\x11\n\tfont_size\x18\x03 \x01(\x01\x12\x17\n\x0fscale_invariant\x18\x04 \x01(\x08\x12\x1e\n\x05\x63olor\x18\x05 \x01(\x0b\x32\x0f.foxglove.Color\x12\x0c\n\x04text\x18\x06 \x01(\tb\x06proto3') 19 | 20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.TextPrimitive_pb2', globals()) 22 | if _descriptor._USE_C_DESCRIPTORS == False: 23 | 24 | DESCRIPTOR._options = None 25 | _TEXTPRIMITIVE._serialized_start=86 26 | _TEXTPRIMITIVE._serialized_end=240 27 | # @@protoc_insertion_point(module_scope) 28 | -------------------------------------------------------------------------------- /foxglove/SpherePrimitive_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/SpherePrimitive.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Color_pb2 as foxglove_dot_Color__pb2 15 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 16 | from foxglove import Vector3_pb2 as foxglove_dot_Vector3__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1e\x66oxglove/SpherePrimitive.proto\x12\x08\x66oxglove\x1a\x14\x66oxglove/Color.proto\x1a\x13\x66oxglove/Pose.proto\x1a\x16\x66oxglove/Vector3.proto\"p\n\x0fSpherePrimitive\x12\x1c\n\x04pose\x18\x01 \x01(\x0b\x32\x0e.foxglove.Pose\x12\x1f\n\x04size\x18\x02 \x01(\x0b\x32\x11.foxglove.Vector3\x12\x1e\n\x05\x63olor\x18\x03 \x01(\x0b\x32\x0f.foxglove.Colorb\x06proto3') 20 | 21 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 22 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.SpherePrimitive_pb2', globals()) 23 | if _descriptor._USE_C_DESCRIPTORS == False: 24 | 25 | DESCRIPTOR._options = None 26 | _SPHEREPRIMITIVE._serialized_start=111 27 | _SPHEREPRIMITIVE._serialized_end=223 28 | # @@protoc_insertion_point(module_scope) 29 | -------------------------------------------------------------------------------- /foxglove/ArrowPrimitive_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/ArrowPrimitive.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Color_pb2 as foxglove_dot_Color__pb2 15 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x66oxglove/ArrowPrimitive.proto\x12\x08\x66oxglove\x1a\x14\x66oxglove/Color.proto\x1a\x13\x66oxglove/Pose.proto\"\xa8\x01\n\x0e\x41rrowPrimitive\x12\x1c\n\x04pose\x18\x01 \x01(\x0b\x32\x0e.foxglove.Pose\x12\x14\n\x0cshaft_length\x18\x02 \x01(\x01\x12\x16\n\x0eshaft_diameter\x18\x03 \x01(\x01\x12\x13\n\x0bhead_length\x18\x04 \x01(\x01\x12\x15\n\rhead_diameter\x18\x05 \x01(\x01\x12\x1e\n\x05\x63olor\x18\x06 \x01(\x0b\x32\x0f.foxglove.Colorb\x06proto3') 19 | 20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.ArrowPrimitive_pb2', globals()) 22 | if _descriptor._USE_C_DESCRIPTORS == False: 23 | 24 | DESCRIPTOR._options = None 25 | _ARROWPRIMITIVE._serialized_start=87 26 | _ARROWPRIMITIVE._serialized_end=255 27 | # @@protoc_insertion_point(module_scope) 28 | -------------------------------------------------------------------------------- /foxglove/ImageAnnotations_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.CircleAnnotation_pb2 7 | import foxglove.PointsAnnotation_pb2 8 | import google.protobuf.descriptor 9 | import google.protobuf.internal.containers 10 | import google.protobuf.message 11 | import typing 12 | import typing_extensions 13 | 14 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 15 | 16 | class ImageAnnotations(google.protobuf.message.Message): 17 | """Array of annotations for a 2D image""" 18 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 19 | CIRCLES_FIELD_NUMBER: builtins.int 20 | POINTS_FIELD_NUMBER: builtins.int 21 | @property 22 | def circles(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.CircleAnnotation_pb2.CircleAnnotation]: 23 | """Circle annotations""" 24 | pass 25 | @property 26 | def points(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.PointsAnnotation_pb2.PointsAnnotation]: 27 | """Points annotations""" 28 | pass 29 | def __init__(self, 30 | *, 31 | circles: typing.Optional[typing.Iterable[foxglove.CircleAnnotation_pb2.CircleAnnotation]] = ..., 32 | points: typing.Optional[typing.Iterable[foxglove.PointsAnnotation_pb2.PointsAnnotation]] = ..., 33 | ) -> None: ... 34 | def ClearField(self, field_name: typing_extensions.Literal["circles",b"circles","points",b"points"]) -> None: ... 35 | global___ImageAnnotations = ImageAnnotations 36 | -------------------------------------------------------------------------------- /foxglove/CameraCalibration_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/CameraCalibration.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n foxglove/CameraCalibration.proto\x12\x08\x66oxglove\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb9\x01\n\x11\x43\x61meraCalibration\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x66rame_id\x18\t \x01(\t\x12\r\n\x05width\x18\x02 \x01(\x07\x12\x0e\n\x06height\x18\x03 \x01(\x07\x12\x18\n\x10\x64istortion_model\x18\x04 \x01(\t\x12\t\n\x01\x44\x18\x05 \x03(\x01\x12\t\n\x01K\x18\x06 \x03(\x01\x12\t\n\x01R\x18\x07 \x03(\x01\x12\t\n\x01P\x18\x08 \x03(\x01\x62\x06proto3') 18 | 19 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 20 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.CameraCalibration_pb2', globals()) 21 | if _descriptor._USE_C_DESCRIPTORS == False: 22 | 23 | DESCRIPTOR._options = None 24 | _CAMERACALIBRATION._serialized_start=80 25 | _CAMERACALIBRATION._serialized_end=265 26 | # @@protoc_insertion_point(module_scope) 27 | -------------------------------------------------------------------------------- /foxglove/LaserScan_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/LaserScan.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 15 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 16 | 17 | 18 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x66oxglove/LaserScan.proto\x12\x08\x66oxglove\x1a\x13\x66oxglove/Pose.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb7\x01\n\tLaserScan\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x66rame_id\x18\x02 \x01(\t\x12\x1c\n\x04pose\x18\x03 \x01(\x0b\x32\x0e.foxglove.Pose\x12\x13\n\x0bstart_angle\x18\x04 \x01(\x01\x12\x11\n\tend_angle\x18\x05 \x01(\x01\x12\x0e\n\x06ranges\x18\x06 \x03(\x01\x12\x13\n\x0bintensities\x18\x07 \x03(\x01\x62\x06proto3') 19 | 20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.LaserScan_pb2', globals()) 22 | if _descriptor._USE_C_DESCRIPTORS == False: 23 | 24 | DESCRIPTOR._options = None 25 | _LASERSCAN._serialized_start=93 26 | _LASERSCAN._serialized_end=276 27 | # @@protoc_insertion_point(module_scope) 28 | -------------------------------------------------------------------------------- /foxglove/SceneEntityDeletion_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/SceneEntityDeletion.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"foxglove/SceneEntityDeletion.proto\x12\x08\x66oxglove\x1a\x1fgoogle/protobuf/timestamp.proto\"\xa4\x01\n\x13SceneEntityDeletion\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x04type\x18\x02 \x01(\x0e\x32\".foxglove.SceneEntityDeletion.Type\x12\n\n\x02id\x18\x03 \x01(\t\" \n\x04Type\x12\x0f\n\x0bMATCHING_ID\x10\x00\x12\x07\n\x03\x41LL\x10\x01\x62\x06proto3') 18 | 19 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 20 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.SceneEntityDeletion_pb2', globals()) 21 | if _descriptor._USE_C_DESCRIPTORS == False: 22 | 23 | DESCRIPTOR._options = None 24 | _SCENEENTITYDELETION._serialized_start=82 25 | _SCENEENTITYDELETION._serialized_end=246 26 | _SCENEENTITYDELETION_TYPE._serialized_start=214 27 | _SCENEENTITYDELETION_TYPE._serialized_end=246 28 | # @@protoc_insertion_point(module_scope) 29 | -------------------------------------------------------------------------------- /foxglove/LocationFix_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/LocationFix.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x66oxglove/LocationFix.proto\x12\x08\x66oxglove\"\x89\x02\n\x0bLocationFix\x12\x10\n\x08latitude\x18\x01 \x01(\x01\x12\x11\n\tlongitude\x18\x02 \x01(\x01\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x01\x12\x1b\n\x13position_covariance\x18\x04 \x03(\x01\x12N\n\x18position_covariance_type\x18\x05 \x01(\x0e\x32,.foxglove.LocationFix.PositionCovarianceType\"V\n\x16PositionCovarianceType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x10\n\x0c\x41PPROXIMATED\x10\x01\x12\x12\n\x0e\x44IAGONAL_KNOWN\x10\x02\x12\t\n\x05KNOWN\x10\x03\x62\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.LocationFix_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _LOCATIONFIX._serialized_start=41 24 | _LOCATIONFIX._serialized_end=306 25 | _LOCATIONFIX_POSITIONCOVARIANCETYPE._serialized_start=220 26 | _LOCATIONFIX_POSITIONCOVARIANCETYPE._serialized_end=306 27 | # @@protoc_insertion_point(module_scope) 28 | -------------------------------------------------------------------------------- /foxglove/PoseInFrame_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Pose_pb2 7 | import google.protobuf.descriptor 8 | import google.protobuf.message 9 | import google.protobuf.timestamp_pb2 10 | import typing 11 | import typing_extensions 12 | 13 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 14 | 15 | class PoseInFrame(google.protobuf.message.Message): 16 | """A timestamped pose for an object or reference frame in 3D space""" 17 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 18 | TIMESTAMP_FIELD_NUMBER: builtins.int 19 | FRAME_ID_FIELD_NUMBER: builtins.int 20 | POSE_FIELD_NUMBER: builtins.int 21 | @property 22 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 23 | """Timestamp of pose""" 24 | pass 25 | frame_id: typing.Text 26 | """Frame of reference for pose position and orientation""" 27 | 28 | @property 29 | def pose(self) -> foxglove.Pose_pb2.Pose: 30 | """Pose in 3D space""" 31 | pass 32 | def __init__(self, 33 | *, 34 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 35 | frame_id: typing.Text = ..., 36 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 37 | ) -> None: ... 38 | def HasField(self, field_name: typing_extensions.Literal["pose",b"pose","timestamp",b"timestamp"]) -> builtins.bool: ... 39 | def ClearField(self, field_name: typing_extensions.Literal["frame_id",b"frame_id","pose",b"pose","timestamp",b"timestamp"]) -> None: ... 40 | global___PoseInFrame = PoseInFrame 41 | -------------------------------------------------------------------------------- /foxglove/SceneUpdate_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.SceneEntityDeletion_pb2 7 | import foxglove.SceneEntity_pb2 8 | import google.protobuf.descriptor 9 | import google.protobuf.internal.containers 10 | import google.protobuf.message 11 | import typing 12 | import typing_extensions 13 | 14 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 15 | 16 | class SceneUpdate(google.protobuf.message.Message): 17 | """(Experimental, subject to change) An update to the entities displayed in a 3D scene""" 18 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 19 | DELETIONS_FIELD_NUMBER: builtins.int 20 | ENTITIES_FIELD_NUMBER: builtins.int 21 | @property 22 | def deletions(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.SceneEntityDeletion_pb2.SceneEntityDeletion]: 23 | """Scene entities to delete""" 24 | pass 25 | @property 26 | def entities(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.SceneEntity_pb2.SceneEntity]: 27 | """Scene entities to add or replace""" 28 | pass 29 | def __init__(self, 30 | *, 31 | deletions: typing.Optional[typing.Iterable[foxglove.SceneEntityDeletion_pb2.SceneEntityDeletion]] = ..., 32 | entities: typing.Optional[typing.Iterable[foxglove.SceneEntity_pb2.SceneEntity]] = ..., 33 | ) -> None: ... 34 | def ClearField(self, field_name: typing_extensions.Literal["deletions",b"deletions","entities",b"entities"]) -> None: ... 35 | global___SceneUpdate = SceneUpdate 36 | -------------------------------------------------------------------------------- /foxglove/PackedElementField_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/PackedElementField.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!foxglove/PackedElementField.proto\x12\x08\x66oxglove\"\xe3\x01\n\x12PackedElementField\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06offset\x18\x02 \x01(\x07\x12\x36\n\x04type\x18\x03 \x01(\x0e\x32(.foxglove.PackedElementField.NumericType\"w\n\x0bNumericType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05UINT8\x10\x01\x12\x08\n\x04INT8\x10\x02\x12\n\n\x06UINT16\x10\x03\x12\t\n\x05INT16\x10\x04\x12\n\n\x06UINT32\x10\x05\x12\t\n\x05INT32\x10\x06\x12\x0b\n\x07\x46LOAT32\x10\x07\x12\x0b\n\x07\x46LOAT64\x10\x08\x62\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.PackedElementField_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _PACKEDELEMENTFIELD._serialized_start=48 24 | _PACKEDELEMENTFIELD._serialized_end=275 25 | _PACKEDELEMENTFIELD_NUMERICTYPE._serialized_start=156 26 | _PACKEDELEMENTFIELD_NUMERICTYPE._serialized_end=275 27 | # @@protoc_insertion_point(module_scope) 28 | -------------------------------------------------------------------------------- /foxglove/CylinderPrimitive_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/CylinderPrimitive.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Color_pb2 as foxglove_dot_Color__pb2 15 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 16 | from foxglove import Vector3_pb2 as foxglove_dot_Vector3__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n foxglove/CylinderPrimitive.proto\x12\x08\x66oxglove\x1a\x14\x66oxglove/Color.proto\x1a\x13\x66oxglove/Pose.proto\x1a\x16\x66oxglove/Vector3.proto\"\x9b\x01\n\x11\x43ylinderPrimitive\x12\x1c\n\x04pose\x18\x01 \x01(\x0b\x32\x0e.foxglove.Pose\x12\x1f\n\x04size\x18\x02 \x01(\x0b\x32\x11.foxglove.Vector3\x12\x14\n\x0c\x62ottom_scale\x18\x03 \x01(\x01\x12\x11\n\ttop_scale\x18\x04 \x01(\x01\x12\x1e\n\x05\x63olor\x18\x05 \x01(\x0b\x32\x0f.foxglove.Colorb\x06proto3') 20 | 21 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 22 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.CylinderPrimitive_pb2', globals()) 23 | if _descriptor._USE_C_DESCRIPTORS == False: 24 | 25 | DESCRIPTOR._options = None 26 | _CYLINDERPRIMITIVE._serialized_start=114 27 | _CYLINDERPRIMITIVE._serialized_end=269 28 | # @@protoc_insertion_point(module_scope) 29 | -------------------------------------------------------------------------------- /foxglove/Log_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/Log.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x66oxglove/Log.proto\x12\x08\x66oxglove\x1a\x1fgoogle/protobuf/timestamp.proto\"\xe1\x01\n\x03Log\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\"\n\x05level\x18\x02 \x01(\x0e\x32\x13.foxglove.Log.Level\x12\x0f\n\x07message\x18\x03 \x01(\t\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x0c\n\x04\x66ile\x18\x05 \x01(\t\x12\x0c\n\x04line\x18\x06 \x01(\x07\"L\n\x05Level\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x44\x45\x42UG\x10\x01\x12\x08\n\x04INFO\x10\x02\x12\x0b\n\x07WARNING\x10\x03\x12\t\n\x05\x45RROR\x10\x04\x12\t\n\x05\x46\x41TAL\x10\x05\x62\x06proto3') 18 | 19 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 20 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.Log_pb2', globals()) 21 | if _descriptor._USE_C_DESCRIPTORS == False: 22 | 23 | DESCRIPTOR._options = None 24 | _LOG._serialized_start=66 25 | _LOG._serialized_end=291 26 | _LOG_LEVEL._serialized_start=215 27 | _LOG_LEVEL._serialized_end=291 28 | # @@protoc_insertion_point(module_scope) 29 | -------------------------------------------------------------------------------- /foxglove/TriangleListPrimitive_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/TriangleListPrimitive.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Color_pb2 as foxglove_dot_Color__pb2 15 | from foxglove import Point3_pb2 as foxglove_dot_Point3__pb2 16 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$foxglove/TriangleListPrimitive.proto\x12\x08\x66oxglove\x1a\x14\x66oxglove/Color.proto\x1a\x15\x66oxglove/Point3.proto\x1a\x13\x66oxglove/Pose.proto\"\xa9\x01\n\x15TriangleListPrimitive\x12\x1c\n\x04pose\x18\x01 \x01(\x0b\x32\x0e.foxglove.Pose\x12 \n\x06points\x18\x02 \x03(\x0b\x32\x10.foxglove.Point3\x12\x1e\n\x05\x63olor\x18\x03 \x01(\x0b\x32\x0f.foxglove.Color\x12\x1f\n\x06\x63olors\x18\x04 \x03(\x0b\x32\x0f.foxglove.Color\x12\x0f\n\x07indices\x18\x05 \x03(\x07\x62\x06proto3') 20 | 21 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 22 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.TriangleListPrimitive_pb2', globals()) 23 | if _descriptor._USE_C_DESCRIPTORS == False: 24 | 25 | DESCRIPTOR._options = None 26 | _TRIANGLELISTPRIMITIVE._serialized_start=117 27 | _TRIANGLELISTPRIMITIVE._serialized_end=286 28 | # @@protoc_insertion_point(module_scope) 29 | -------------------------------------------------------------------------------- /foxglove/ModelPrimitive_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/ModelPrimitive.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Color_pb2 as foxglove_dot_Color__pb2 15 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 16 | from foxglove import Vector3_pb2 as foxglove_dot_Vector3__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x66oxglove/ModelPrimitive.proto\x12\x08\x66oxglove\x1a\x14\x66oxglove/Color.proto\x1a\x13\x66oxglove/Pose.proto\x1a\x16\x66oxglove/Vector3.proto\"\xb7\x01\n\x0eModelPrimitive\x12\x1c\n\x04pose\x18\x01 \x01(\x0b\x32\x0e.foxglove.Pose\x12 \n\x05scale\x18\x02 \x01(\x0b\x32\x11.foxglove.Vector3\x12\x1e\n\x05\x63olor\x18\x03 \x01(\x0b\x32\x0f.foxglove.Color\x12\x16\n\x0eoverride_color\x18\x04 \x01(\x08\x12\x0b\n\x03url\x18\x05 \x01(\t\x12\x12\n\nmedia_type\x18\x06 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x07 \x01(\x0c\x62\x06proto3') 20 | 21 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 22 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.ModelPrimitive_pb2', globals()) 23 | if _descriptor._USE_C_DESCRIPTORS == False: 24 | 25 | DESCRIPTOR._options = None 26 | _MODELPRIMITIVE._serialized_start=111 27 | _MODELPRIMITIVE._serialized_end=294 28 | # @@protoc_insertion_point(module_scope) 29 | -------------------------------------------------------------------------------- /foxglove/FrameTransform_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/FrameTransform.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Quaternion_pb2 as foxglove_dot_Quaternion__pb2 15 | from foxglove import Vector3_pb2 as foxglove_dot_Vector3__pb2 16 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x66oxglove/FrameTransform.proto\x12\x08\x66oxglove\x1a\x19\x66oxglove/Quaternion.proto\x1a\x16\x66oxglove/Vector3.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xc0\x01\n\x0e\x46rameTransform\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0fparent_frame_id\x18\x02 \x01(\t\x12\x16\n\x0e\x63hild_frame_id\x18\x03 \x01(\t\x12&\n\x0btranslation\x18\x04 \x01(\x0b\x32\x11.foxglove.Vector3\x12&\n\x08rotation\x18\x05 \x01(\x0b\x32\x14.foxglove.Quaternionb\x06proto3') 20 | 21 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 22 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.FrameTransform_pb2', globals()) 23 | if _descriptor._USE_C_DESCRIPTORS == False: 24 | 25 | DESCRIPTOR._options = None 26 | _FRAMETRANSFORM._serialized_start=128 27 | _FRAMETRANSFORM._serialized_end=320 28 | # @@protoc_insertion_point(module_scope) 29 | -------------------------------------------------------------------------------- /delete_all_events.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import sys 4 | 5 | from foxglove_data_platform.client import Client 6 | from event_helpers.client_utils import get_all_events_for_device 7 | 8 | 9 | def main(): 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument( 12 | "--token", 13 | "-t", 14 | help="data platform secret token (if not provided, FOXGLOVE_DATA_PLATFORM_TOKEN from environment is used)", 15 | ) 16 | parser.add_argument("--commit", "-y", action="store_true", help="actually perform deletions") 17 | parser.add_argument("--host", default="api.foxglove.dev", help="custom host to send data to") 18 | args = parser.parse_args() 19 | if args.token is None: 20 | token = os.environ.get("FOXGLOVE_DATA_PLATFORM_TOKEN") 21 | if token is None: 22 | print("FOXGLOVE_DATA_PLATFORM_TOKEN not in environment", file=sys.stderr) 23 | return 1 24 | args.token = token 25 | 26 | client = Client(token=args.token, host=args.host) 27 | device_ids = [resp["id"] for resp in client.get_devices()] 28 | print(f"Found events for devices: {device_ids}") 29 | 30 | # find all the events 31 | events_to_delete = [] 32 | for device_id in device_ids: 33 | events_to_delete.extend(get_all_events_for_device(client, device_id)) 34 | 35 | # destroy all events 36 | for old_event in events_to_delete: 37 | if not args.commit: 38 | print(f"Would delete: {old_event}") 39 | else: 40 | client.delete_event(event_id=old_event["id"]) 41 | print(f"would have deleted {len(events_to_delete)} events for devices: {device_ids}") 42 | 43 | 44 | if __name__ == "__main__": 45 | sys.exit(main()) 46 | -------------------------------------------------------------------------------- /foxglove/PointCloud_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/PointCloud.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import PackedElementField_pb2 as foxglove_dot_PackedElementField__pb2 15 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 16 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x66oxglove/PointCloud.proto\x12\x08\x66oxglove\x1a!foxglove/PackedElementField.proto\x1a\x13\x66oxglove/Pose.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xbd\x01\n\nPointCloud\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x66rame_id\x18\x02 \x01(\t\x12\x1c\n\x04pose\x18\x03 \x01(\x0b\x32\x0e.foxglove.Pose\x12\x14\n\x0cpoint_stride\x18\x04 \x01(\x07\x12,\n\x06\x66ields\x18\x05 \x03(\x0b\x32\x1c.foxglove.PackedElementField\x12\x0c\n\x04\x64\x61ta\x18\x06 \x01(\x0c\x62\x06proto3') 20 | 21 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 22 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.PointCloud_pb2', globals()) 23 | if _descriptor._USE_C_DESCRIPTORS == False: 24 | 25 | DESCRIPTOR._options = None 26 | _POINTCLOUD._serialized_start=129 27 | _POINTCLOUD._serialized_end=318 28 | # @@protoc_insertion_point(module_scope) 29 | -------------------------------------------------------------------------------- /foxglove/CubePrimitive_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Color_pb2 7 | import foxglove.Pose_pb2 8 | import foxglove.Vector3_pb2 9 | import google.protobuf.descriptor 10 | import google.protobuf.message 11 | import typing 12 | import typing_extensions 13 | 14 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 15 | 16 | class CubePrimitive(google.protobuf.message.Message): 17 | """(Experimental, subject to change) A primitive representing a cube or rectangular prism""" 18 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 19 | POSE_FIELD_NUMBER: builtins.int 20 | SIZE_FIELD_NUMBER: builtins.int 21 | COLOR_FIELD_NUMBER: builtins.int 22 | @property 23 | def pose(self) -> foxglove.Pose_pb2.Pose: 24 | """Position of the center of the cube and orientation of the cube""" 25 | pass 26 | @property 27 | def size(self) -> foxglove.Vector3_pb2.Vector3: 28 | """Size of the cube along each axis""" 29 | pass 30 | @property 31 | def color(self) -> foxglove.Color_pb2.Color: 32 | """Color of the arrow""" 33 | pass 34 | def __init__(self, 35 | *, 36 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 37 | size: typing.Optional[foxglove.Vector3_pb2.Vector3] = ..., 38 | color: typing.Optional[foxglove.Color_pb2.Color] = ..., 39 | ) -> None: ... 40 | def HasField(self, field_name: typing_extensions.Literal["color",b"color","pose",b"pose","size",b"size"]) -> builtins.bool: ... 41 | def ClearField(self, field_name: typing_extensions.Literal["color",b"color","pose",b"pose","size",b"size"]) -> None: ... 42 | global___CubePrimitive = CubePrimitive 43 | -------------------------------------------------------------------------------- /foxglove/CircleAnnotation_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/CircleAnnotation.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Color_pb2 as foxglove_dot_Color__pb2 15 | from foxglove import Point2_pb2 as foxglove_dot_Point2__pb2 16 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1f\x66oxglove/CircleAnnotation.proto\x12\x08\x66oxglove\x1a\x14\x66oxglove/Color.proto\x1a\x15\x66oxglove/Point2.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xd7\x01\n\x10\x43ircleAnnotation\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\"\n\x08position\x18\x02 \x01(\x0b\x32\x10.foxglove.Point2\x12\x10\n\x08\x64iameter\x18\x03 \x01(\x01\x12\x11\n\tthickness\x18\x04 \x01(\x01\x12#\n\nfill_color\x18\x05 \x01(\x0b\x32\x0f.foxglove.Color\x12&\n\routline_color\x18\x06 \x01(\x0b\x32\x0f.foxglove.Colorb\x06proto3') 20 | 21 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 22 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.CircleAnnotation_pb2', globals()) 23 | if _descriptor._USE_C_DESCRIPTORS == False: 24 | 25 | DESCRIPTOR._options = None 26 | _CIRCLEANNOTATION._serialized_start=124 27 | _CIRCLEANNOTATION._serialized_end=339 28 | # @@protoc_insertion_point(module_scope) 29 | -------------------------------------------------------------------------------- /foxglove/SpherePrimitive_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Color_pb2 7 | import foxglove.Pose_pb2 8 | import foxglove.Vector3_pb2 9 | import google.protobuf.descriptor 10 | import google.protobuf.message 11 | import typing 12 | import typing_extensions 13 | 14 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 15 | 16 | class SpherePrimitive(google.protobuf.message.Message): 17 | """(Experimental, subject to change) A primitive representing a sphere or ellipsoid""" 18 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 19 | POSE_FIELD_NUMBER: builtins.int 20 | SIZE_FIELD_NUMBER: builtins.int 21 | COLOR_FIELD_NUMBER: builtins.int 22 | @property 23 | def pose(self) -> foxglove.Pose_pb2.Pose: 24 | """Position of the center of the sphere and orientation of the sphere""" 25 | pass 26 | @property 27 | def size(self) -> foxglove.Vector3_pb2.Vector3: 28 | """Size (diameter) of the sphere along each axis""" 29 | pass 30 | @property 31 | def color(self) -> foxglove.Color_pb2.Color: 32 | """Color of the sphere""" 33 | pass 34 | def __init__(self, 35 | *, 36 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 37 | size: typing.Optional[foxglove.Vector3_pb2.Vector3] = ..., 38 | color: typing.Optional[foxglove.Color_pb2.Color] = ..., 39 | ) -> None: ... 40 | def HasField(self, field_name: typing_extensions.Literal["color",b"color","pose",b"pose","size",b"size"]) -> builtins.bool: ... 41 | def ClearField(self, field_name: typing_extensions.Literal["color",b"color","pose",b"pose","size",b"size"]) -> None: ... 42 | global___SpherePrimitive = SpherePrimitive 43 | -------------------------------------------------------------------------------- /foxglove/PosesInFrame_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Pose_pb2 7 | import google.protobuf.descriptor 8 | import google.protobuf.internal.containers 9 | import google.protobuf.message 10 | import google.protobuf.timestamp_pb2 11 | import typing 12 | import typing_extensions 13 | 14 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 15 | 16 | class PosesInFrame(google.protobuf.message.Message): 17 | """An array of timestamped poses for an object or reference frame in 3D space""" 18 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 19 | TIMESTAMP_FIELD_NUMBER: builtins.int 20 | FRAME_ID_FIELD_NUMBER: builtins.int 21 | POSES_FIELD_NUMBER: builtins.int 22 | @property 23 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 24 | """Timestamp of pose""" 25 | pass 26 | frame_id: typing.Text 27 | """Frame of reference for pose position and orientation""" 28 | 29 | @property 30 | def poses(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.Pose_pb2.Pose]: 31 | """Poses in 3D space""" 32 | pass 33 | def __init__(self, 34 | *, 35 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 36 | frame_id: typing.Text = ..., 37 | poses: typing.Optional[typing.Iterable[foxglove.Pose_pb2.Pose]] = ..., 38 | ) -> None: ... 39 | def HasField(self, field_name: typing_extensions.Literal["timestamp",b"timestamp"]) -> builtins.bool: ... 40 | def ClearField(self, field_name: typing_extensions.Literal["frame_id",b"frame_id","poses",b"poses","timestamp",b"timestamp"]) -> None: ... 41 | global___PosesInFrame = PosesInFrame 42 | -------------------------------------------------------------------------------- /foxglove/CompressedImage_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.message 8 | import google.protobuf.timestamp_pb2 9 | import typing 10 | import typing_extensions 11 | 12 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 13 | 14 | class CompressedImage(google.protobuf.message.Message): 15 | """A compressed image""" 16 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 17 | TIMESTAMP_FIELD_NUMBER: builtins.int 18 | FRAME_ID_FIELD_NUMBER: builtins.int 19 | DATA_FIELD_NUMBER: builtins.int 20 | FORMAT_FIELD_NUMBER: builtins.int 21 | @property 22 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 23 | """Timestamp of image""" 24 | pass 25 | frame_id: typing.Text 26 | """Frame of reference for the image. The origin of the frame is the optical center of the camera. +x points to the right in the image, +y points down, and +z points into the plane of the image.""" 27 | 28 | data: builtins.bytes 29 | """Compressed image data""" 30 | 31 | format: typing.Text 32 | """Image format""" 33 | 34 | def __init__(self, 35 | *, 36 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 37 | frame_id: typing.Text = ..., 38 | data: builtins.bytes = ..., 39 | format: typing.Text = ..., 40 | ) -> None: ... 41 | def HasField(self, field_name: typing_extensions.Literal["timestamp",b"timestamp"]) -> builtins.bool: ... 42 | def ClearField(self, field_name: typing_extensions.Literal["data",b"data","format",b"format","frame_id",b"frame_id","timestamp",b"timestamp"]) -> None: ... 43 | global___CompressedImage = CompressedImage 44 | -------------------------------------------------------------------------------- /foxglove/Grid_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/Grid.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import PackedElementField_pb2 as foxglove_dot_PackedElementField__pb2 15 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 16 | from foxglove import Vector2_pb2 as foxglove_dot_Vector2__pb2 17 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 18 | 19 | 20 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13\x66oxglove/Grid.proto\x12\x08\x66oxglove\x1a!foxglove/PackedElementField.proto\x1a\x13\x66oxglove/Pose.proto\x1a\x16\x66oxglove/Vector2.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x86\x02\n\x04Grid\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x66rame_id\x18\x02 \x01(\t\x12\x1c\n\x04pose\x18\x03 \x01(\x0b\x32\x0e.foxglove.Pose\x12\x14\n\x0c\x63olumn_count\x18\x04 \x01(\x07\x12$\n\tcell_size\x18\x05 \x01(\x0b\x32\x11.foxglove.Vector2\x12\x12\n\nrow_stride\x18\x06 \x01(\x07\x12\x13\n\x0b\x63\x65ll_stride\x18\x07 \x01(\x07\x12,\n\x06\x66ields\x18\x08 \x03(\x0b\x32\x1c.foxglove.PackedElementField\x12\x0c\n\x04\x64\x61ta\x18\t \x01(\x0c\x62\x06proto3') 21 | 22 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 23 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.Grid_pb2', globals()) 24 | if _descriptor._USE_C_DESCRIPTORS == False: 25 | 26 | DESCRIPTOR._options = None 27 | _GRID._serialized_start=147 28 | _GRID._serialized_end=409 29 | # @@protoc_insertion_point(module_scope) 30 | -------------------------------------------------------------------------------- /foxglove/LinePrimitive_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/LinePrimitive.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Color_pb2 as foxglove_dot_Color__pb2 15 | from foxglove import Point3_pb2 as foxglove_dot_Point3__pb2 16 | from foxglove import Pose_pb2 as foxglove_dot_Pose__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66oxglove/LinePrimitive.proto\x12\x08\x66oxglove\x1a\x14\x66oxglove/Color.proto\x1a\x15\x66oxglove/Point3.proto\x1a\x13\x66oxglove/Pose.proto\"\xaf\x02\n\rLinePrimitive\x12*\n\x04type\x18\x01 \x01(\x0e\x32\x1c.foxglove.LinePrimitive.Type\x12\x1c\n\x04pose\x18\x02 \x01(\x0b\x32\x0e.foxglove.Pose\x12\x11\n\tthickness\x18\x03 \x01(\x01\x12\x17\n\x0fscale_invariant\x18\x04 \x01(\x08\x12 \n\x06points\x18\x05 \x03(\x0b\x32\x10.foxglove.Point3\x12\x1e\n\x05\x63olor\x18\x06 \x01(\x0b\x32\x0f.foxglove.Color\x12\x1f\n\x06\x63olors\x18\x07 \x03(\x0b\x32\x0f.foxglove.Color\x12\x0f\n\x07indices\x18\x08 \x03(\x07\"4\n\x04Type\x12\x0e\n\nLINE_STRIP\x10\x00\x12\r\n\tLINE_LOOP\x10\x01\x12\r\n\tLINE_LIST\x10\x02\x62\x06proto3') 20 | 21 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 22 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.LinePrimitive_pb2', globals()) 23 | if _descriptor._USE_C_DESCRIPTORS == False: 24 | 25 | DESCRIPTOR._options = None 26 | _LINEPRIMITIVE._serialized_start=109 27 | _LINEPRIMITIVE._serialized_end=412 28 | _LINEPRIMITIVE_TYPE._serialized_start=360 29 | _LINEPRIMITIVE_TYPE._serialized_end=412 30 | # @@protoc_insertion_point(module_scope) 31 | -------------------------------------------------------------------------------- /ProtobufWriter.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Dict, Optional 2 | from mcap_protobuf.schema import register_schema 3 | 4 | 5 | class ProtobufWriter: 6 | def __init__(self, output): 7 | self.__writer = output 8 | self.__schema_ids: Dict[str, int] = {} 9 | self.__channel_ids: Dict[str, int] = {} 10 | 11 | def write_message( 12 | self, 13 | topic: str, 14 | message: Any, 15 | log_time: Optional[int] = None, 16 | publish_time: Optional[int] = None, 17 | sequence: int = 0, 18 | ): 19 | """ 20 | Writes a message to the MCAP stream, automatically registering schemas and channels as 21 | needed. 22 | @param topic: The topic of the message. 23 | @param message: The message to write. 24 | @param log_time: The time at which the message was logged. 25 | Will default to the current time if not specified. 26 | @param publish_time: The time at which the message was published. 27 | Will default to the current time if not specified. 28 | @param sequence: An optional sequence number. 29 | """ 30 | msg_typename = type(message).DESCRIPTOR.full_name 31 | schema_id = self.__schema_ids.get(msg_typename) 32 | if schema_id is None: 33 | schema_id = register_schema(self.__writer, type(message)) 34 | self.__schema_ids[msg_typename] = schema_id 35 | 36 | channel_id = self.__channel_ids.get(topic) 37 | if channel_id is None: 38 | channel_id = self.__writer.register_channel( 39 | topic=topic, 40 | message_encoding="protobuf", 41 | schema_id=schema_id, 42 | ) 43 | self.__channel_ids[topic] = channel_id 44 | 45 | self.__writer.add_message( 46 | channel_id=channel_id, 47 | log_time=log_time, 48 | publish_time=publish_time or log_time, 49 | sequence=sequence, 50 | data=message.SerializeToString(), 51 | ) 52 | -------------------------------------------------------------------------------- /foxglove/PointsAnnotation_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/PointsAnnotation.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import Color_pb2 as foxglove_dot_Color__pb2 15 | from foxglove import Point2_pb2 as foxglove_dot_Point2__pb2 16 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 17 | 18 | 19 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1f\x66oxglove/PointsAnnotation.proto\x12\x08\x66oxglove\x1a\x14\x66oxglove/Color.proto\x1a\x15\x66oxglove/Point2.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xea\x02\n\x10PointsAnnotation\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12-\n\x04type\x18\x02 \x01(\x0e\x32\x1f.foxglove.PointsAnnotation.Type\x12 \n\x06points\x18\x03 \x03(\x0b\x32\x10.foxglove.Point2\x12&\n\routline_color\x18\x04 \x01(\x0b\x32\x0f.foxglove.Color\x12\'\n\x0eoutline_colors\x18\x05 \x03(\x0b\x32\x0f.foxglove.Color\x12#\n\nfill_color\x18\x06 \x01(\x0b\x32\x0f.foxglove.Color\x12\x11\n\tthickness\x18\x07 \x01(\x01\"M\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06POINTS\x10\x01\x12\r\n\tLINE_LOOP\x10\x02\x12\x0e\n\nLINE_STRIP\x10\x03\x12\r\n\tLINE_LIST\x10\x04\x62\x06proto3') 20 | 21 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 22 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.PointsAnnotation_pb2', globals()) 23 | if _descriptor._USE_C_DESCRIPTORS == False: 24 | 25 | DESCRIPTOR._options = None 26 | _POINTSANNOTATION._serialized_start=124 27 | _POINTSANNOTATION._serialized_end=486 28 | _POINTSANNOTATION_TYPE._serialized_start=409 29 | _POINTSANNOTATION_TYPE._serialized_end=486 30 | # @@protoc_insertion_point(module_scope) 31 | -------------------------------------------------------------------------------- /foxglove/RawImage_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.message 8 | import google.protobuf.timestamp_pb2 9 | import typing 10 | import typing_extensions 11 | 12 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 13 | 14 | class RawImage(google.protobuf.message.Message): 15 | """A raw image""" 16 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 17 | TIMESTAMP_FIELD_NUMBER: builtins.int 18 | FRAME_ID_FIELD_NUMBER: builtins.int 19 | WIDTH_FIELD_NUMBER: builtins.int 20 | HEIGHT_FIELD_NUMBER: builtins.int 21 | ENCODING_FIELD_NUMBER: builtins.int 22 | STEP_FIELD_NUMBER: builtins.int 23 | DATA_FIELD_NUMBER: builtins.int 24 | @property 25 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 26 | """Timestamp of image""" 27 | pass 28 | frame_id: typing.Text 29 | """Frame of reference for the image. The origin of the frame is the optical center of the camera. +x points to the right in the image, +y points down, and +z points into the plane of the image.""" 30 | 31 | width: builtins.int 32 | """Image width""" 33 | 34 | height: builtins.int 35 | """Image height""" 36 | 37 | encoding: typing.Text 38 | """Encoding of the raw image data""" 39 | 40 | step: builtins.int 41 | """Byte length of a single row""" 42 | 43 | data: builtins.bytes 44 | """Raw image data""" 45 | 46 | def __init__(self, 47 | *, 48 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 49 | frame_id: typing.Text = ..., 50 | width: builtins.int = ..., 51 | height: builtins.int = ..., 52 | encoding: typing.Text = ..., 53 | step: builtins.int = ..., 54 | data: builtins.bytes = ..., 55 | ) -> None: ... 56 | def HasField(self, field_name: typing_extensions.Literal["timestamp",b"timestamp"]) -> builtins.bool: ... 57 | def ClearField(self, field_name: typing_extensions.Literal["data",b"data","encoding",b"encoding","frame_id",b"frame_id","height",b"height","step",b"step","timestamp",b"timestamp","width",b"width"]) -> None: ... 58 | global___RawImage = RawImage 59 | -------------------------------------------------------------------------------- /vm_helpers/ready_scratch_disk.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | import json 4 | import os 5 | import sys 6 | import subprocess 7 | 8 | 9 | def fail(msg): 10 | print(msg, file=sys.stderr) 11 | sys.exit(1) 12 | 13 | 14 | def get_device_state(serial): 15 | lsblk_result = subprocess.run(["lsblk", "-Jo", "FSTYPE,SERIAL,MOUNTPOINT,PATH"], capture_output=True, check=True) 16 | block_devices = json.loads(lsblk_result.stdout) 17 | for device in block_devices["blockdevices"]: 18 | if device["serial"] == serial: 19 | return device 20 | fail(f"block device with serial '{serial}' not found in: {block_devices}") 21 | 22 | 23 | def check_root(): 24 | euid = os.geteuid() 25 | if euid != 0: 26 | fail(f"this script should be run as root, found euid {euid}") 27 | 28 | 29 | def run(args, commit=False): 30 | if commit: 31 | subprocess.run(args, check=True) 32 | else: 33 | print(f"Would have executed: {args}") 34 | 35 | 36 | def main(): 37 | parser = argparse.ArgumentParser() 38 | parser.add_argument("--commit", action="store_true", help="make destructive changes") 39 | parser.add_argument("--serial", default="nuscenes-scratch", help="device serial to use as scratch disk") 40 | parser.add_argument("--mountpoint", default="/media/scratch", help="mountpoint for scratch disk") 41 | args = parser.parse_args() 42 | if args.commit: 43 | check_root() 44 | state = get_device_state(args.serial) 45 | if state["fstype"] is None: 46 | run(["mkfs.ext4", "-F", state["path"]], commit=args.commit) 47 | 48 | state = get_device_state(args.serial) 49 | if state["mountpoint"] is None: 50 | if not os.path.isdir(args.mountpoint): 51 | if args.commit: 52 | os.makedirs(args.mountpoint, exist_ok=True, mode=0o777) 53 | else: 54 | print(f"Would have created directory {args.mountpoint}") 55 | run(["mount", state["path"], args.mountpoint], commit=args.commit) 56 | 57 | state = get_device_state(args.serial) 58 | if state["fstype"] != "ext4" and state["mountpoint"] != args.mountpoint: 59 | fail(f"could not completely set up device: {state}") 60 | 61 | 62 | if __name__ == "__main__": 63 | main() 64 | -------------------------------------------------------------------------------- /foxglove/FrameTransform_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Quaternion_pb2 7 | import foxglove.Vector3_pb2 8 | import google.protobuf.descriptor 9 | import google.protobuf.message 10 | import google.protobuf.timestamp_pb2 11 | import typing 12 | import typing_extensions 13 | 14 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 15 | 16 | class FrameTransform(google.protobuf.message.Message): 17 | """A transform between two reference frames in 3D space""" 18 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 19 | TIMESTAMP_FIELD_NUMBER: builtins.int 20 | PARENT_FRAME_ID_FIELD_NUMBER: builtins.int 21 | CHILD_FRAME_ID_FIELD_NUMBER: builtins.int 22 | TRANSLATION_FIELD_NUMBER: builtins.int 23 | ROTATION_FIELD_NUMBER: builtins.int 24 | @property 25 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 26 | """Timestamp of transform""" 27 | pass 28 | parent_frame_id: typing.Text 29 | """Name of the parent frame""" 30 | 31 | child_frame_id: typing.Text 32 | """Name of the child frame""" 33 | 34 | @property 35 | def translation(self) -> foxglove.Vector3_pb2.Vector3: 36 | """Translation component of the transform""" 37 | pass 38 | @property 39 | def rotation(self) -> foxglove.Quaternion_pb2.Quaternion: 40 | """Rotation component of the transform""" 41 | pass 42 | def __init__(self, 43 | *, 44 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 45 | parent_frame_id: typing.Text = ..., 46 | child_frame_id: typing.Text = ..., 47 | translation: typing.Optional[foxglove.Vector3_pb2.Vector3] = ..., 48 | rotation: typing.Optional[foxglove.Quaternion_pb2.Quaternion] = ..., 49 | ) -> None: ... 50 | def HasField(self, field_name: typing_extensions.Literal["rotation",b"rotation","timestamp",b"timestamp","translation",b"translation"]) -> builtins.bool: ... 51 | def ClearField(self, field_name: typing_extensions.Literal["child_frame_id",b"child_frame_id","parent_frame_id",b"parent_frame_id","rotation",b"rotation","timestamp",b"timestamp","translation",b"translation"]) -> None: ... 52 | global___FrameTransform = FrameTransform 53 | -------------------------------------------------------------------------------- /nuscenes2bag/can_utils.py: -------------------------------------------------------------------------------- 1 | from utils import * 2 | 3 | def get_imu_msg(imu_data): 4 | msg = Imu() 5 | msg.header.frame_id = 'base_link' 6 | msg.header.stamp = get_utime(imu_data) 7 | msg.angular_velocity.x = imu_data['rotation_rate'][0]; 8 | msg.angular_velocity.y = imu_data['rotation_rate'][1]; 9 | msg.angular_velocity.z = imu_data['rotation_rate'][2]; 10 | 11 | msg.linear_acceleration.x = imu_data['linear_accel'][0]; 12 | msg.linear_acceleration.y = imu_data['linear_accel'][1]; 13 | msg.linear_acceleration.z = imu_data['linear_accel'][2]; 14 | 15 | msg.orientation.w = imu_data['q'][0]; 16 | msg.orientation.x = imu_data['q'][1]; 17 | msg.orientation.y = imu_data['q'][2]; 18 | msg.orientation.z = imu_data['q'][3]; 19 | 20 | return (msg.header.stamp, '/imu', msg) 21 | 22 | def get_odom_msg(pose_data): 23 | msg = Odometry() 24 | msg.header.frame_id = 'map' 25 | msg.header.stamp = get_utime(pose_data) 26 | msg.child_frame_id = 'base_link' 27 | msg.pose.pose.position.x = pose_data['pos'][0] 28 | msg.pose.pose.position.y = pose_data['pos'][1] 29 | msg.pose.pose.position.z = pose_data['pos'][2] 30 | msg.pose.pose.orientation.w = pose_data['orientation'][0] 31 | msg.pose.pose.orientation.x = pose_data['orientation'][1] 32 | msg.pose.pose.orientation.y = pose_data['orientation'][2] 33 | msg.pose.pose.orientation.z = pose_data['orientation'][3] 34 | msg.twist.twist.linear.x = pose_data['vel'][0] 35 | msg.twist.twist.linear.y = pose_data['vel'][1] 36 | msg.twist.twist.linear.z = pose_data['vel'][2] 37 | msg.twist.twist.angular.x = pose_data['rotation_rate'][0] 38 | msg.twist.twist.angular.y = pose_data['rotation_rate'][1] 39 | msg.twist.twist.angular.z = pose_data['rotation_rate'][2] 40 | 41 | return (msg.header.stamp, '/odom', msg) 42 | 43 | def get_basic_can_msg(name, diag_data): 44 | values = [] 45 | for (key, value) in diag_data.items(): 46 | if key != 'utime': 47 | values.append(KeyValue(key=key, value=str(round(value, 4)))) 48 | 49 | msg = DiagnosticArray() 50 | msg.header.stamp = get_utime(diag_data) 51 | msg.status.append(DiagnosticStatus(name=name, level=DiagnosticStatus.OK, message='OK', values=values)) 52 | 53 | return (msg.header.stamp, '/diagnostics', msg) -------------------------------------------------------------------------------- /foxglove/ArrowPrimitive_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Color_pb2 7 | import foxglove.Pose_pb2 8 | import google.protobuf.descriptor 9 | import google.protobuf.message 10 | import typing 11 | import typing_extensions 12 | 13 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 14 | 15 | class ArrowPrimitive(google.protobuf.message.Message): 16 | """(Experimental, subject to change) A primitive representing an arrow""" 17 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 18 | POSE_FIELD_NUMBER: builtins.int 19 | SHAFT_LENGTH_FIELD_NUMBER: builtins.int 20 | SHAFT_DIAMETER_FIELD_NUMBER: builtins.int 21 | HEAD_LENGTH_FIELD_NUMBER: builtins.int 22 | HEAD_DIAMETER_FIELD_NUMBER: builtins.int 23 | COLOR_FIELD_NUMBER: builtins.int 24 | @property 25 | def pose(self) -> foxglove.Pose_pb2.Pose: 26 | """Position of the arrow's tail and orientation of the arrow. Identity orientation means the arrow points in the +x direction.""" 27 | pass 28 | shaft_length: builtins.float 29 | """Length of the arrow shaft""" 30 | 31 | shaft_diameter: builtins.float 32 | """Diameter of the arrow shaft""" 33 | 34 | head_length: builtins.float 35 | """Length of the arrow head""" 36 | 37 | head_diameter: builtins.float 38 | """Diameter of the arrow head""" 39 | 40 | @property 41 | def color(self) -> foxglove.Color_pb2.Color: 42 | """Color of the arrow""" 43 | pass 44 | def __init__(self, 45 | *, 46 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 47 | shaft_length: builtins.float = ..., 48 | shaft_diameter: builtins.float = ..., 49 | head_length: builtins.float = ..., 50 | head_diameter: builtins.float = ..., 51 | color: typing.Optional[foxglove.Color_pb2.Color] = ..., 52 | ) -> None: ... 53 | def HasField(self, field_name: typing_extensions.Literal["color",b"color","pose",b"pose"]) -> builtins.bool: ... 54 | def ClearField(self, field_name: typing_extensions.Literal["color",b"color","head_diameter",b"head_diameter","head_length",b"head_length","pose",b"pose","shaft_diameter",b"shaft_diameter","shaft_length",b"shaft_length"]) -> None: ... 55 | global___ArrowPrimitive = ArrowPrimitive 56 | -------------------------------------------------------------------------------- /RosmsgWriter.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Dict, Optional 2 | from io import BytesIO 3 | 4 | import rospy 5 | 6 | 7 | class RosmsgWriter: 8 | def __init__(self, output): 9 | self.__writer = output 10 | self.__schema_ids: Dict[str, int] = {} 11 | self.__channel_ids: Dict[str, int] = {} 12 | 13 | def write_message( 14 | self, 15 | topic: str, 16 | message: Any, 17 | log_time: Optional[int] = None, 18 | publish_time: Optional[int] = None, 19 | sequence: int = 0, 20 | ): 21 | """ 22 | Writes a message to the MCAP stream, automatically registering schemas and channels as 23 | needed. 24 | @param topic: The topic of the message. 25 | @param message: The message to write. 26 | @param log_time: The time at which the message was logged. 27 | Will default to the current time if not specified. 28 | @param publish_time: The time at which the message was published. 29 | Will default to the current time if not specified. 30 | @param sequence: An optional sequence number. 31 | """ 32 | if message._type not in self.__schema_ids.keys(): 33 | schema_id = self.__writer.register_schema( 34 | name=message._type, 35 | data=message.__class__._full_text.encode(), 36 | encoding="ros1msg", 37 | ) 38 | self.__schema_ids[message._type] = schema_id 39 | schema_id = self.__schema_ids[message._type] 40 | 41 | if topic not in self.__channel_ids.keys(): 42 | channel_id = self.__writer.register_channel( 43 | topic=topic, 44 | message_encoding="ros1", 45 | schema_id=schema_id, 46 | ) 47 | self.__channel_ids[topic] = channel_id 48 | channel_id = self.__channel_ids[topic] 49 | 50 | buffer = BytesIO() 51 | message.serialize(buffer) 52 | if isinstance(log_time, rospy.Time): 53 | log_time = int((log_time.secs * int(1e9)) + log_time.nsecs) 54 | self.__writer.add_message( 55 | channel_id=channel_id, 56 | log_time=log_time, 57 | publish_time=publish_time or log_time, 58 | sequence=sequence, 59 | data=buffer.getvalue(), 60 | ) 61 | -------------------------------------------------------------------------------- /foxglove/CylinderPrimitive_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Color_pb2 7 | import foxglove.Pose_pb2 8 | import foxglove.Vector3_pb2 9 | import google.protobuf.descriptor 10 | import google.protobuf.message 11 | import typing 12 | import typing_extensions 13 | 14 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 15 | 16 | class CylinderPrimitive(google.protobuf.message.Message): 17 | """(Experimental, subject to change) A primitive representing a cylinder, elliptic cylinder, or truncated cone""" 18 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 19 | POSE_FIELD_NUMBER: builtins.int 20 | SIZE_FIELD_NUMBER: builtins.int 21 | BOTTOM_SCALE_FIELD_NUMBER: builtins.int 22 | TOP_SCALE_FIELD_NUMBER: builtins.int 23 | COLOR_FIELD_NUMBER: builtins.int 24 | @property 25 | def pose(self) -> foxglove.Pose_pb2.Pose: 26 | """Position of the center of the cylinder and orientation of the cylinder. The flat face(s) are perpendicular to the z-axis.""" 27 | pass 28 | @property 29 | def size(self) -> foxglove.Vector3_pb2.Vector3: 30 | """Size of the cylinder's bounding box""" 31 | pass 32 | bottom_scale: builtins.float 33 | """0-1, ratio of the diameter of the cylinder's bottom face (min z) to the bottom of the bounding box""" 34 | 35 | top_scale: builtins.float 36 | """0-1, ratio of the diameter of the cylinder's top face (max z) to the top of the bounding box""" 37 | 38 | @property 39 | def color(self) -> foxglove.Color_pb2.Color: 40 | """Color of the cylinder""" 41 | pass 42 | def __init__(self, 43 | *, 44 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 45 | size: typing.Optional[foxglove.Vector3_pb2.Vector3] = ..., 46 | bottom_scale: builtins.float = ..., 47 | top_scale: builtins.float = ..., 48 | color: typing.Optional[foxglove.Color_pb2.Color] = ..., 49 | ) -> None: ... 50 | def HasField(self, field_name: typing_extensions.Literal["color",b"color","pose",b"pose","size",b"size"]) -> builtins.bool: ... 51 | def ClearField(self, field_name: typing_extensions.Literal["bottom_scale",b"bottom_scale","color",b"color","pose",b"pose","size",b"size","top_scale",b"top_scale"]) -> None: ... 52 | global___CylinderPrimitive = CylinderPrimitive 53 | -------------------------------------------------------------------------------- /foxglove/TextPrimitive_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Color_pb2 7 | import foxglove.Pose_pb2 8 | import google.protobuf.descriptor 9 | import google.protobuf.message 10 | import typing 11 | import typing_extensions 12 | 13 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 14 | 15 | class TextPrimitive(google.protobuf.message.Message): 16 | """(Experimental, subject to change) A primitive representing a text label""" 17 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 18 | POSE_FIELD_NUMBER: builtins.int 19 | BILLBOARD_FIELD_NUMBER: builtins.int 20 | FONT_SIZE_FIELD_NUMBER: builtins.int 21 | SCALE_INVARIANT_FIELD_NUMBER: builtins.int 22 | COLOR_FIELD_NUMBER: builtins.int 23 | TEXT_FIELD_NUMBER: builtins.int 24 | @property 25 | def pose(self) -> foxglove.Pose_pb2.Pose: 26 | """Position of the center of the text box and orientation of the text. Identity orientation means the text is oriented in the xy-plane and flows from -x to +x.""" 27 | pass 28 | billboard: builtins.bool 29 | """Whether the text should respect `pose.orientation` (false) or always face the camera (true)""" 30 | 31 | font_size: builtins.float 32 | """Font size (height of one line of text)""" 33 | 34 | scale_invariant: builtins.bool 35 | """Indicates whether `font_size` is a fixed size in screen pixels (true), or specified in world coordinates and scales with distance from the camera (false)""" 36 | 37 | @property 38 | def color(self) -> foxglove.Color_pb2.Color: 39 | """Color of the text""" 40 | pass 41 | text: typing.Text 42 | """Text""" 43 | 44 | def __init__(self, 45 | *, 46 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 47 | billboard: builtins.bool = ..., 48 | font_size: builtins.float = ..., 49 | scale_invariant: builtins.bool = ..., 50 | color: typing.Optional[foxglove.Color_pb2.Color] = ..., 51 | text: typing.Text = ..., 52 | ) -> None: ... 53 | def HasField(self, field_name: typing_extensions.Literal["color",b"color","pose",b"pose"]) -> builtins.bool: ... 54 | def ClearField(self, field_name: typing_extensions.Literal["billboard",b"billboard","color",b"color","font_size",b"font_size","pose",b"pose","scale_invariant",b"scale_invariant","text",b"text"]) -> None: ... 55 | global___TextPrimitive = TextPrimitive 56 | -------------------------------------------------------------------------------- /foxglove/CircleAnnotation_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Color_pb2 7 | import foxglove.Point2_pb2 8 | import google.protobuf.descriptor 9 | import google.protobuf.message 10 | import google.protobuf.timestamp_pb2 11 | import typing 12 | import typing_extensions 13 | 14 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 15 | 16 | class CircleAnnotation(google.protobuf.message.Message): 17 | """A circle annotation on a 2D image""" 18 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 19 | TIMESTAMP_FIELD_NUMBER: builtins.int 20 | POSITION_FIELD_NUMBER: builtins.int 21 | DIAMETER_FIELD_NUMBER: builtins.int 22 | THICKNESS_FIELD_NUMBER: builtins.int 23 | FILL_COLOR_FIELD_NUMBER: builtins.int 24 | OUTLINE_COLOR_FIELD_NUMBER: builtins.int 25 | @property 26 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 27 | """Timestamp of circle""" 28 | pass 29 | @property 30 | def position(self) -> foxglove.Point2_pb2.Point2: 31 | """Center of the circle in 2D image coordinates""" 32 | pass 33 | diameter: builtins.float 34 | """Circle diameter""" 35 | 36 | thickness: builtins.float 37 | """Line thickness""" 38 | 39 | @property 40 | def fill_color(self) -> foxglove.Color_pb2.Color: 41 | """Fill color""" 42 | pass 43 | @property 44 | def outline_color(self) -> foxglove.Color_pb2.Color: 45 | """Outline color""" 46 | pass 47 | def __init__(self, 48 | *, 49 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 50 | position: typing.Optional[foxglove.Point2_pb2.Point2] = ..., 51 | diameter: builtins.float = ..., 52 | thickness: builtins.float = ..., 53 | fill_color: typing.Optional[foxglove.Color_pb2.Color] = ..., 54 | outline_color: typing.Optional[foxglove.Color_pb2.Color] = ..., 55 | ) -> None: ... 56 | def HasField(self, field_name: typing_extensions.Literal["fill_color",b"fill_color","outline_color",b"outline_color","position",b"position","timestamp",b"timestamp"]) -> builtins.bool: ... 57 | def ClearField(self, field_name: typing_extensions.Literal["diameter",b"diameter","fill_color",b"fill_color","outline_color",b"outline_color","position",b"position","thickness",b"thickness","timestamp",b"timestamp"]) -> None: ... 58 | global___CircleAnnotation = CircleAnnotation 59 | -------------------------------------------------------------------------------- /foxglove/PointCloud_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.PackedElementField_pb2 7 | import foxglove.Pose_pb2 8 | import google.protobuf.descriptor 9 | import google.protobuf.internal.containers 10 | import google.protobuf.message 11 | import google.protobuf.timestamp_pb2 12 | import typing 13 | import typing_extensions 14 | 15 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 16 | 17 | class PointCloud(google.protobuf.message.Message): 18 | """A collection of N-dimensional points, which may contain additional fields with information like normals, intensity, etc.""" 19 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 20 | TIMESTAMP_FIELD_NUMBER: builtins.int 21 | FRAME_ID_FIELD_NUMBER: builtins.int 22 | POSE_FIELD_NUMBER: builtins.int 23 | POINT_STRIDE_FIELD_NUMBER: builtins.int 24 | FIELDS_FIELD_NUMBER: builtins.int 25 | DATA_FIELD_NUMBER: builtins.int 26 | @property 27 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 28 | """Timestamp of point cloud""" 29 | pass 30 | frame_id: typing.Text 31 | """Frame of reference""" 32 | 33 | @property 34 | def pose(self) -> foxglove.Pose_pb2.Pose: 35 | """The origin of the point cloud relative to the frame of reference""" 36 | pass 37 | point_stride: builtins.int 38 | """Number of bytes between points in the `data`""" 39 | 40 | @property 41 | def fields(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.PackedElementField_pb2.PackedElementField]: 42 | """Fields in the `data`""" 43 | pass 44 | data: builtins.bytes 45 | """Point data, interpreted using `fields`""" 46 | 47 | def __init__(self, 48 | *, 49 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 50 | frame_id: typing.Text = ..., 51 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 52 | point_stride: builtins.int = ..., 53 | fields: typing.Optional[typing.Iterable[foxglove.PackedElementField_pb2.PackedElementField]] = ..., 54 | data: builtins.bytes = ..., 55 | ) -> None: ... 56 | def HasField(self, field_name: typing_extensions.Literal["pose",b"pose","timestamp",b"timestamp"]) -> builtins.bool: ... 57 | def ClearField(self, field_name: typing_extensions.Literal["data",b"data","fields",b"fields","frame_id",b"frame_id","point_stride",b"point_stride","pose",b"pose","timestamp",b"timestamp"]) -> None: ... 58 | global___PointCloud = PointCloud 59 | -------------------------------------------------------------------------------- /foxglove/SceneEntityDeletion_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.internal.enum_type_wrapper 8 | import google.protobuf.message 9 | import google.protobuf.timestamp_pb2 10 | import typing 11 | import typing_extensions 12 | 13 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 14 | 15 | class SceneEntityDeletion(google.protobuf.message.Message): 16 | """(Experimental, subject to change) Command to remove previously published entities""" 17 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 18 | class _Type: 19 | ValueType = typing.NewType('ValueType', builtins.int) 20 | V: typing_extensions.TypeAlias = ValueType 21 | class _TypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[SceneEntityDeletion._Type.ValueType], builtins.type): 22 | DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor 23 | MATCHING_ID: SceneEntityDeletion._Type.ValueType # 0 24 | """Delete the existing entity on the same topic that has the provided `id`""" 25 | 26 | ALL: SceneEntityDeletion._Type.ValueType # 1 27 | """Delete all existing entities on the same topic""" 28 | 29 | class Type(_Type, metaclass=_TypeEnumTypeWrapper): 30 | """(Experimental, subject to change) An enumeration indicating which entities should match a SceneEntityDeletion command""" 31 | pass 32 | 33 | MATCHING_ID: SceneEntityDeletion.Type.ValueType # 0 34 | """Delete the existing entity on the same topic that has the provided `id`""" 35 | 36 | ALL: SceneEntityDeletion.Type.ValueType # 1 37 | """Delete all existing entities on the same topic""" 38 | 39 | 40 | TIMESTAMP_FIELD_NUMBER: builtins.int 41 | TYPE_FIELD_NUMBER: builtins.int 42 | ID_FIELD_NUMBER: builtins.int 43 | @property 44 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 45 | """Timestamp of the deletion. Only matching entities earlier than this timestamp will be deleted.""" 46 | pass 47 | type: global___SceneEntityDeletion.Type.ValueType 48 | """Type of deletion action to perform""" 49 | 50 | id: typing.Text 51 | """Identifier which must match if `type` is `MATCHING_ID`.""" 52 | 53 | def __init__(self, 54 | *, 55 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 56 | type: global___SceneEntityDeletion.Type.ValueType = ..., 57 | id: typing.Text = ..., 58 | ) -> None: ... 59 | def HasField(self, field_name: typing_extensions.Literal["timestamp",b"timestamp"]) -> builtins.bool: ... 60 | def ClearField(self, field_name: typing_extensions.Literal["id",b"id","timestamp",b"timestamp","type",b"type"]) -> None: ... 61 | global___SceneEntityDeletion = SceneEntityDeletion 62 | -------------------------------------------------------------------------------- /foxglove/Log_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.internal.enum_type_wrapper 8 | import google.protobuf.message 9 | import google.protobuf.timestamp_pb2 10 | import typing 11 | import typing_extensions 12 | 13 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 14 | 15 | class Log(google.protobuf.message.Message): 16 | """A log message""" 17 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 18 | class _Level: 19 | ValueType = typing.NewType('ValueType', builtins.int) 20 | V: typing_extensions.TypeAlias = ValueType 21 | class _LevelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Log._Level.ValueType], builtins.type): 22 | DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor 23 | UNKNOWN: Log._Level.ValueType # 0 24 | DEBUG: Log._Level.ValueType # 1 25 | INFO: Log._Level.ValueType # 2 26 | WARNING: Log._Level.ValueType # 3 27 | ERROR: Log._Level.ValueType # 4 28 | FATAL: Log._Level.ValueType # 5 29 | class Level(_Level, metaclass=_LevelEnumTypeWrapper): 30 | """Log level""" 31 | pass 32 | 33 | UNKNOWN: Log.Level.ValueType # 0 34 | DEBUG: Log.Level.ValueType # 1 35 | INFO: Log.Level.ValueType # 2 36 | WARNING: Log.Level.ValueType # 3 37 | ERROR: Log.Level.ValueType # 4 38 | FATAL: Log.Level.ValueType # 5 39 | 40 | TIMESTAMP_FIELD_NUMBER: builtins.int 41 | LEVEL_FIELD_NUMBER: builtins.int 42 | MESSAGE_FIELD_NUMBER: builtins.int 43 | NAME_FIELD_NUMBER: builtins.int 44 | FILE_FIELD_NUMBER: builtins.int 45 | LINE_FIELD_NUMBER: builtins.int 46 | @property 47 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 48 | """Timestamp of log message""" 49 | pass 50 | level: global___Log.Level.ValueType 51 | """Log level""" 52 | 53 | message: typing.Text 54 | """Log message""" 55 | 56 | name: typing.Text 57 | """Process or node name""" 58 | 59 | file: typing.Text 60 | """Filename""" 61 | 62 | line: builtins.int 63 | """Line number in the file""" 64 | 65 | def __init__(self, 66 | *, 67 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 68 | level: global___Log.Level.ValueType = ..., 69 | message: typing.Text = ..., 70 | name: typing.Text = ..., 71 | file: typing.Text = ..., 72 | line: builtins.int = ..., 73 | ) -> None: ... 74 | def HasField(self, field_name: typing_extensions.Literal["timestamp",b"timestamp"]) -> builtins.bool: ... 75 | def ClearField(self, field_name: typing_extensions.Literal["file",b"file","level",b"level","line",b"line","message",b"message","name",b"name","timestamp",b"timestamp"]) -> None: ... 76 | global___Log = Log 77 | -------------------------------------------------------------------------------- /foxglove/LaserScan_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Pose_pb2 7 | import google.protobuf.descriptor 8 | import google.protobuf.internal.containers 9 | import google.protobuf.message 10 | import google.protobuf.timestamp_pb2 11 | import typing 12 | import typing_extensions 13 | 14 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 15 | 16 | class LaserScan(google.protobuf.message.Message): 17 | """A single scan from a planar laser range-finder""" 18 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 19 | TIMESTAMP_FIELD_NUMBER: builtins.int 20 | FRAME_ID_FIELD_NUMBER: builtins.int 21 | POSE_FIELD_NUMBER: builtins.int 22 | START_ANGLE_FIELD_NUMBER: builtins.int 23 | END_ANGLE_FIELD_NUMBER: builtins.int 24 | RANGES_FIELD_NUMBER: builtins.int 25 | INTENSITIES_FIELD_NUMBER: builtins.int 26 | @property 27 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 28 | """Timestamp of scan""" 29 | pass 30 | frame_id: typing.Text 31 | """Frame of reference""" 32 | 33 | @property 34 | def pose(self) -> foxglove.Pose_pb2.Pose: 35 | """Origin of scan relative to frame of reference; points are positioned in the x-y plane relative to this origin; angles are interpreted as counterclockwise rotations around the z axis with 0 rad being in the +x direction""" 36 | pass 37 | start_angle: builtins.float 38 | """Bearing of first point, in radians""" 39 | 40 | end_angle: builtins.float 41 | """Bearing of last point, in radians""" 42 | 43 | @property 44 | def ranges(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: 45 | """Distance of detections from origin; assumed to be at equally-spaced angles between `start_angle` and `end_angle`""" 46 | pass 47 | @property 48 | def intensities(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: 49 | """Intensity of detections""" 50 | pass 51 | def __init__(self, 52 | *, 53 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 54 | frame_id: typing.Text = ..., 55 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 56 | start_angle: builtins.float = ..., 57 | end_angle: builtins.float = ..., 58 | ranges: typing.Optional[typing.Iterable[builtins.float]] = ..., 59 | intensities: typing.Optional[typing.Iterable[builtins.float]] = ..., 60 | ) -> None: ... 61 | def HasField(self, field_name: typing_extensions.Literal["pose",b"pose","timestamp",b"timestamp"]) -> builtins.bool: ... 62 | def ClearField(self, field_name: typing_extensions.Literal["end_angle",b"end_angle","frame_id",b"frame_id","intensities",b"intensities","pose",b"pose","ranges",b"ranges","start_angle",b"start_angle","timestamp",b"timestamp"]) -> None: ... 63 | global___LaserScan = LaserScan 64 | -------------------------------------------------------------------------------- /foxglove/ModelPrimitive_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Color_pb2 7 | import foxglove.Pose_pb2 8 | import foxglove.Vector3_pb2 9 | import google.protobuf.descriptor 10 | import google.protobuf.message 11 | import typing 12 | import typing_extensions 13 | 14 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 15 | 16 | class ModelPrimitive(google.protobuf.message.Message): 17 | """(Experimental, subject to change) A primitive representing a 3D model file loaded from an external URL or embedded data""" 18 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 19 | POSE_FIELD_NUMBER: builtins.int 20 | SCALE_FIELD_NUMBER: builtins.int 21 | COLOR_FIELD_NUMBER: builtins.int 22 | OVERRIDE_COLOR_FIELD_NUMBER: builtins.int 23 | URL_FIELD_NUMBER: builtins.int 24 | MEDIA_TYPE_FIELD_NUMBER: builtins.int 25 | DATA_FIELD_NUMBER: builtins.int 26 | @property 27 | def pose(self) -> foxglove.Pose_pb2.Pose: 28 | """Origin of model relative to reference frame""" 29 | pass 30 | @property 31 | def scale(self) -> foxglove.Vector3_pb2.Vector3: 32 | """Scale factor to apply to the model along each axis""" 33 | pass 34 | @property 35 | def color(self) -> foxglove.Color_pb2.Color: 36 | """Solid color to use for the whole model if `override_color` is true.""" 37 | pass 38 | override_color: builtins.bool 39 | """Whether to use the color specified in `color` instead of any materials embedded in the original model.""" 40 | 41 | url: typing.Text 42 | """URL pointing to model file. One of `url` or `data` should be provided.""" 43 | 44 | media_type: typing.Text 45 | """[Media type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) of embedded model (e.g. `model/gltf-binary`). Required if `data` is provided instead of `url`. Overrides the inferred media type if `url` is provided.""" 46 | 47 | data: builtins.bytes 48 | """Embedded model. One of `url` or `data` should be provided. If `data` is provided, `media_type` must be set to indicate the type of the data.""" 49 | 50 | def __init__(self, 51 | *, 52 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 53 | scale: typing.Optional[foxglove.Vector3_pb2.Vector3] = ..., 54 | color: typing.Optional[foxglove.Color_pb2.Color] = ..., 55 | override_color: builtins.bool = ..., 56 | url: typing.Text = ..., 57 | media_type: typing.Text = ..., 58 | data: builtins.bytes = ..., 59 | ) -> None: ... 60 | def HasField(self, field_name: typing_extensions.Literal["color",b"color","pose",b"pose","scale",b"scale"]) -> builtins.bool: ... 61 | def ClearField(self, field_name: typing_extensions.Literal["color",b"color","data",b"data","media_type",b"media_type","override_color",b"override_color","pose",b"pose","scale",b"scale","url",b"url"]) -> None: ... 62 | global___ModelPrimitive = ModelPrimitive 63 | -------------------------------------------------------------------------------- /foxglove/PackedElementField_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.internal.enum_type_wrapper 8 | import google.protobuf.message 9 | import typing 10 | import typing_extensions 11 | 12 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 13 | 14 | class PackedElementField(google.protobuf.message.Message): 15 | """A field present within each element in a byte array of packed elements.""" 16 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 17 | class _NumericType: 18 | ValueType = typing.NewType('ValueType', builtins.int) 19 | V: typing_extensions.TypeAlias = ValueType 20 | class _NumericTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[PackedElementField._NumericType.ValueType], builtins.type): 21 | DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor 22 | UNKNOWN: PackedElementField._NumericType.ValueType # 0 23 | UINT8: PackedElementField._NumericType.ValueType # 1 24 | INT8: PackedElementField._NumericType.ValueType # 2 25 | UINT16: PackedElementField._NumericType.ValueType # 3 26 | INT16: PackedElementField._NumericType.ValueType # 4 27 | UINT32: PackedElementField._NumericType.ValueType # 5 28 | INT32: PackedElementField._NumericType.ValueType # 6 29 | FLOAT32: PackedElementField._NumericType.ValueType # 7 30 | FLOAT64: PackedElementField._NumericType.ValueType # 8 31 | class NumericType(_NumericType, metaclass=_NumericTypeEnumTypeWrapper): 32 | """Numeric type""" 33 | pass 34 | 35 | UNKNOWN: PackedElementField.NumericType.ValueType # 0 36 | UINT8: PackedElementField.NumericType.ValueType # 1 37 | INT8: PackedElementField.NumericType.ValueType # 2 38 | UINT16: PackedElementField.NumericType.ValueType # 3 39 | INT16: PackedElementField.NumericType.ValueType # 4 40 | UINT32: PackedElementField.NumericType.ValueType # 5 41 | INT32: PackedElementField.NumericType.ValueType # 6 42 | FLOAT32: PackedElementField.NumericType.ValueType # 7 43 | FLOAT64: PackedElementField.NumericType.ValueType # 8 44 | 45 | NAME_FIELD_NUMBER: builtins.int 46 | OFFSET_FIELD_NUMBER: builtins.int 47 | TYPE_FIELD_NUMBER: builtins.int 48 | name: typing.Text 49 | """Name of the field""" 50 | 51 | offset: builtins.int 52 | """Byte offset from start of data buffer""" 53 | 54 | type: global___PackedElementField.NumericType.ValueType 55 | """Type of data in the field. Integers are stored using little-endian byte order.""" 56 | 57 | def __init__(self, 58 | *, 59 | name: typing.Text = ..., 60 | offset: builtins.int = ..., 61 | type: global___PackedElementField.NumericType.ValueType = ..., 62 | ) -> None: ... 63 | def ClearField(self, field_name: typing_extensions.Literal["name",b"name","offset",b"offset","type",b"type"]) -> None: ... 64 | global___PackedElementField = PackedElementField 65 | -------------------------------------------------------------------------------- /foxglove/TriangleListPrimitive_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Color_pb2 7 | import foxglove.Point3_pb2 8 | import foxglove.Pose_pb2 9 | import google.protobuf.descriptor 10 | import google.protobuf.internal.containers 11 | import google.protobuf.message 12 | import typing 13 | import typing_extensions 14 | 15 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 16 | 17 | class TriangleListPrimitive(google.protobuf.message.Message): 18 | """(Experimental, subject to change) A primitive representing a set of triangles or a surface tiled by triangles""" 19 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 20 | POSE_FIELD_NUMBER: builtins.int 21 | POINTS_FIELD_NUMBER: builtins.int 22 | COLOR_FIELD_NUMBER: builtins.int 23 | COLORS_FIELD_NUMBER: builtins.int 24 | INDICES_FIELD_NUMBER: builtins.int 25 | @property 26 | def pose(self) -> foxglove.Pose_pb2.Pose: 27 | """Origin of triangles relative to reference frame""" 28 | pass 29 | @property 30 | def points(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.Point3_pb2.Point3]: 31 | """Vertices to use for triangles, interpreted as a list of triples (0-1-2, 3-4-5, ...)""" 32 | pass 33 | @property 34 | def color(self) -> foxglove.Color_pb2.Color: 35 | """Solid color to use for the whole shape. One of `color` or `colors` must be provided.""" 36 | pass 37 | @property 38 | def colors(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.Color_pb2.Color]: 39 | """Per-vertex colors (if specified, must have the same length as `points`). One of `color` or `colors` must be provided.""" 40 | pass 41 | @property 42 | def indices(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: 43 | """Indices into the `points` and `colors` attribute arrays, which can be used to avoid duplicating attribute data. 44 | 45 | If omitted or empty, indexing will not be used. This default behavior is equivalent to specifying [0, 1, ..., N-1] for the indices (where N is the number of `points` provided). 46 | """ 47 | pass 48 | def __init__(self, 49 | *, 50 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 51 | points: typing.Optional[typing.Iterable[foxglove.Point3_pb2.Point3]] = ..., 52 | color: typing.Optional[foxglove.Color_pb2.Color] = ..., 53 | colors: typing.Optional[typing.Iterable[foxglove.Color_pb2.Color]] = ..., 54 | indices: typing.Optional[typing.Iterable[builtins.int]] = ..., 55 | ) -> None: ... 56 | def HasField(self, field_name: typing_extensions.Literal["color",b"color","pose",b"pose"]) -> builtins.bool: ... 57 | def ClearField(self, field_name: typing_extensions.Literal["color",b"color","colors",b"colors","indices",b"indices","points",b"points","pose",b"pose"]) -> None: ... 58 | global___TriangleListPrimitive = TriangleListPrimitive 59 | -------------------------------------------------------------------------------- /nuscenes2bag/annotation_utils.py: -------------------------------------------------------------------------------- 1 | from utils import * 2 | 3 | def write_boxes_imagemarkers(nusc, bag, anns, sample_data, frame_id, topic_ns, stamp): 4 | # annotation boxes 5 | collector = Collector() 6 | _, boxes, camera_intrinsic = nusc.get_sample_data(sample_data['token']) 7 | for box in boxes: 8 | c = np.array(nusc.explorer.get_color(box.name)) / 255.0 9 | box.render(collector, view=camera_intrinsic, normalize=True, colors=(c, c, c)) 10 | 11 | marker = ImageMarker() 12 | marker.header.frame_id = frame_id 13 | marker.header.stamp = get_time(sample_data) 14 | marker.ns = 'annotations' 15 | marker.id = 0 16 | marker.type = ImageMarker.LINE_LIST 17 | marker.action = ImageMarker.ADD 18 | marker.scale = 2.0 19 | marker.points = [make_point2d(p) for p in collector.points] 20 | marker.outline_colors = [make_color(c) for c in collector.colors] 21 | 22 | bag.write(topic_ns + '/image_markers_annotations', serialize_message(marker), stamp) 23 | 24 | def get_lidar_imagemarkers(nusc, sample_lidar, sample_data, frame_id): 25 | # lidar image markers in camera frame 26 | points, coloring, _ = nusc.explorer.map_pointcloud_to_image( 27 | pointsensor_token=sample_lidar['token'], 28 | camera_token=sample_data['token'], 29 | render_intensity=True) 30 | points = points.transpose() 31 | coloring = [turbomap(c) for c in coloring] 32 | 33 | marker = ImageMarker() 34 | marker.header.frame_id = frame_id 35 | marker.header.stamp = get_time(sample_data) 36 | marker.ns = 'LIDAR_TOP' 37 | marker.id = 0 38 | marker.type = ImageMarker.POINTS 39 | marker.action = ImageMarker.ADD 40 | marker.scale = 2.0 41 | marker.points = [make_point2d(p) for p in points] 42 | marker.outline_colors = [make_color(c) for c in coloring] 43 | return marker 44 | 45 | def find_closest_lidar(nusc, lidar_start_token, stamp_nsec): 46 | candidates = [] 47 | 48 | next_lidar_token = nusc.get("sample_data", lidar_start_token)["next"] 49 | while next_lidar_token != "": 50 | lidar_data = nusc.get("sample_data", next_lidar_token) 51 | if lidar_data["is_key_frame"]: 52 | break 53 | 54 | dist_abs = abs(stamp_nsec - to_nano(get_time(lidar_data))) 55 | candidates.append((dist_abs, lidar_data)) 56 | next_lidar_token = lidar_data["next"] 57 | 58 | if len(candidates) == 0: 59 | return None 60 | 61 | return min(candidates, key=lambda x: x[0])[1] 62 | 63 | def get_marker(nusc, annotation_id, stamp): 64 | ann = nusc.get('sample_annotation', annotation_id) 65 | marker_id = int(ann['instance_token'][:4], 16) 66 | c = np.array(nusc.explorer.get_color(ann['category_name'])) / 255.0 67 | 68 | marker = Marker() 69 | marker.header.frame_id = 'map' 70 | marker.header.stamp = stamp 71 | marker.id = marker_id 72 | marker.text = ann['instance_token'][:4] 73 | marker.type = Marker.CUBE 74 | marker.pose = get_pose(ann) 75 | marker.frame_locked = True 76 | marker.scale.x = ann['size'][1] 77 | marker.scale.y = ann['size'][0] 78 | marker.scale.z = ann['size'][2] 79 | marker.color = make_color(c, 0.5) 80 | return marker -------------------------------------------------------------------------------- /foxglove/SceneEntity_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: foxglove/SceneEntity.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from foxglove import ArrowPrimitive_pb2 as foxglove_dot_ArrowPrimitive__pb2 15 | from foxglove import CubePrimitive_pb2 as foxglove_dot_CubePrimitive__pb2 16 | from foxglove import CylinderPrimitive_pb2 as foxglove_dot_CylinderPrimitive__pb2 17 | from foxglove import KeyValuePair_pb2 as foxglove_dot_KeyValuePair__pb2 18 | from foxglove import LinePrimitive_pb2 as foxglove_dot_LinePrimitive__pb2 19 | from foxglove import ModelPrimitive_pb2 as foxglove_dot_ModelPrimitive__pb2 20 | from foxglove import SpherePrimitive_pb2 as foxglove_dot_SpherePrimitive__pb2 21 | from foxglove import TextPrimitive_pb2 as foxglove_dot_TextPrimitive__pb2 22 | from foxglove import TriangleListPrimitive_pb2 as foxglove_dot_TriangleListPrimitive__pb2 23 | from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 24 | from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 25 | 26 | 27 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x66oxglove/SceneEntity.proto\x12\x08\x66oxglove\x1a\x1d\x66oxglove/ArrowPrimitive.proto\x1a\x1c\x66oxglove/CubePrimitive.proto\x1a foxglove/CylinderPrimitive.proto\x1a\x1b\x66oxglove/KeyValuePair.proto\x1a\x1c\x66oxglove/LinePrimitive.proto\x1a\x1d\x66oxglove/ModelPrimitive.proto\x1a\x1e\x66oxglove/SpherePrimitive.proto\x1a\x1c\x66oxglove/TextPrimitive.proto\x1a$foxglove/TriangleListPrimitive.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xa3\x04\n\x0bSceneEntity\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x08\x66rame_id\x18\x02 \x01(\t\x12\n\n\x02id\x18\x03 \x01(\t\x12+\n\x08lifetime\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x14\n\x0c\x66rame_locked\x18\x05 \x01(\x08\x12(\n\x08metadata\x18\x06 \x03(\x0b\x32\x16.foxglove.KeyValuePair\x12(\n\x06\x61rrows\x18\x07 \x03(\x0b\x32\x18.foxglove.ArrowPrimitive\x12&\n\x05\x63ubes\x18\x08 \x03(\x0b\x32\x17.foxglove.CubePrimitive\x12*\n\x07spheres\x18\t \x03(\x0b\x32\x19.foxglove.SpherePrimitive\x12.\n\tcylinders\x18\n \x03(\x0b\x32\x1b.foxglove.CylinderPrimitive\x12&\n\x05lines\x18\x0b \x03(\x0b\x32\x17.foxglove.LinePrimitive\x12\x32\n\ttriangles\x18\x0c \x03(\x0b\x32\x1f.foxglove.TriangleListPrimitive\x12&\n\x05texts\x18\r \x03(\x0b\x32\x17.foxglove.TextPrimitive\x12(\n\x06models\x18\x0e \x03(\x0b\x32\x18.foxglove.ModelPrimitiveb\x06proto3') 28 | 29 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 30 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'foxglove.SceneEntity_pb2', globals()) 31 | if _descriptor._USE_C_DESCRIPTORS == False: 32 | 33 | DESCRIPTOR._options = None 34 | _SCENEENTITY._serialized_start=391 35 | _SCENEENTITY._serialized_end=938 36 | # @@protoc_insertion_point(module_scope) 37 | -------------------------------------------------------------------------------- /upload_mcap.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import sys 3 | import os 4 | from pathlib import Path 5 | 6 | from foxglove_data_platform.client import Client 7 | from mcap.mcap0.reader import make_reader 8 | from device_name import make_device_name 9 | 10 | from tqdm import tqdm 11 | 12 | 13 | class UploadProgressBar(tqdm): 14 | def update_to(self, size, progress): 15 | self.total = size 16 | self.update(progress - self.n) 17 | 18 | 19 | def main(): 20 | parser = argparse.ArgumentParser() 21 | parser.add_argument("files", nargs="+", help="MCAP files to annotate") 22 | parser.add_argument( 23 | "--token", 24 | "-t", 25 | help="data platform secret token (if not provided, FOXGLOVE_DATA_PLATFORM_TOKEN from environment is used)", 26 | ) 27 | parser.add_argument("--host", default="api.foxglove.dev", help="custom host to send data to") 28 | args = parser.parse_args() 29 | if args.token is None: 30 | token = os.environ.get("FOXGLOVE_DATA_PLATFORM_TOKEN") 31 | if token is None: 32 | print("FOXGLOVE_DATA_PLATFORM_TOKEN not in environment", file=sys.stderr) 33 | return 1 34 | args.token = token 35 | 36 | client = Client(token=args.token, host=args.host) 37 | device_ids = {resp["name"]: resp["id"] for resp in client.get_devices()} 38 | 39 | filepaths = [] 40 | for name in args.files: 41 | path = Path(name) 42 | if path.is_dir(): 43 | filepaths.extend(path.glob("*.mcap")) 44 | elif path.is_file(): 45 | filepaths.append(path) 46 | else: 47 | raise RuntimeError(f"path does not exist: {name}") 48 | 49 | for filepath in filepaths: 50 | filename = filepath.name 51 | print(f"checking for previous imports of {filename} ...") 52 | previous_uploads = client.get_imports(filename=filename) 53 | with open(filepath, "rb") as f: 54 | reader = make_reader(f) 55 | scene_info = next(metadata for metadata in reader.iter_metadata() if metadata.name == "scene-info") 56 | device_name = make_device_name(scene_info.metadata) 57 | device_id = device_ids.get(device_name) 58 | if device_id is None: 59 | client.create_device(name=device_name) 60 | device_id = device_ids.get(device_name) 61 | device_ids[device_name] = device_id 62 | 63 | f.seek(0) 64 | print(f"uploading {filename} with device name {device_name} ...") 65 | 66 | with UploadProgressBar(unit="B", unit_scale=True) as progress_bar: 67 | client.upload_data( 68 | device_id=device_id, 69 | filename=filename, 70 | data=f, 71 | callback=progress_bar.update_to, 72 | ) 73 | 74 | if previous_uploads: 75 | print(f"removing {len(previous_uploads)} previously-uploaded instance(s) of {filename}") 76 | for upload in previous_uploads: 77 | client.delete_import( 78 | device_id=upload["device_id"], 79 | import_id=upload["import_id"], 80 | ) 81 | return 0 82 | 83 | 84 | if __name__ == "__main__": 85 | sys.exit(main()) 86 | -------------------------------------------------------------------------------- /foxglove/Grid_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.PackedElementField_pb2 7 | import foxglove.Pose_pb2 8 | import foxglove.Vector2_pb2 9 | import google.protobuf.descriptor 10 | import google.protobuf.internal.containers 11 | import google.protobuf.message 12 | import google.protobuf.timestamp_pb2 13 | import typing 14 | import typing_extensions 15 | 16 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 17 | 18 | class Grid(google.protobuf.message.Message): 19 | """A 2D grid of data""" 20 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 21 | TIMESTAMP_FIELD_NUMBER: builtins.int 22 | FRAME_ID_FIELD_NUMBER: builtins.int 23 | POSE_FIELD_NUMBER: builtins.int 24 | COLUMN_COUNT_FIELD_NUMBER: builtins.int 25 | CELL_SIZE_FIELD_NUMBER: builtins.int 26 | ROW_STRIDE_FIELD_NUMBER: builtins.int 27 | CELL_STRIDE_FIELD_NUMBER: builtins.int 28 | FIELDS_FIELD_NUMBER: builtins.int 29 | DATA_FIELD_NUMBER: builtins.int 30 | @property 31 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 32 | """Timestamp of grid""" 33 | pass 34 | frame_id: typing.Text 35 | """Frame of reference""" 36 | 37 | @property 38 | def pose(self) -> foxglove.Pose_pb2.Pose: 39 | """Origin of grid's corner relative to frame of reference; grid is positioned in the x-y plane relative to this origin""" 40 | pass 41 | column_count: builtins.int 42 | """Number of grid columns""" 43 | 44 | @property 45 | def cell_size(self) -> foxglove.Vector2_pb2.Vector2: 46 | """Size of single grid cell along x and y axes, relative to `pose`""" 47 | pass 48 | row_stride: builtins.int 49 | """Number of bytes between rows in `data`""" 50 | 51 | cell_stride: builtins.int 52 | """Number of bytes between cells within a row in `data`""" 53 | 54 | @property 55 | def fields(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.PackedElementField_pb2.PackedElementField]: 56 | """Fields in `data`""" 57 | pass 58 | data: builtins.bytes 59 | """Grid cell data, interpreted using `fields`, in row-major (y-major) order""" 60 | 61 | def __init__(self, 62 | *, 63 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 64 | frame_id: typing.Text = ..., 65 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 66 | column_count: builtins.int = ..., 67 | cell_size: typing.Optional[foxglove.Vector2_pb2.Vector2] = ..., 68 | row_stride: builtins.int = ..., 69 | cell_stride: builtins.int = ..., 70 | fields: typing.Optional[typing.Iterable[foxglove.PackedElementField_pb2.PackedElementField]] = ..., 71 | data: builtins.bytes = ..., 72 | ) -> None: ... 73 | def HasField(self, field_name: typing_extensions.Literal["cell_size",b"cell_size","pose",b"pose","timestamp",b"timestamp"]) -> builtins.bool: ... 74 | def ClearField(self, field_name: typing_extensions.Literal["cell_size",b"cell_size","cell_stride",b"cell_stride","column_count",b"column_count","data",b"data","fields",b"fields","frame_id",b"frame_id","pose",b"pose","row_stride",b"row_stride","timestamp",b"timestamp"]) -> None: ... 75 | global___Grid = Grid 76 | -------------------------------------------------------------------------------- /foxglove/LocationFix_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.internal.containers 8 | import google.protobuf.internal.enum_type_wrapper 9 | import google.protobuf.message 10 | import typing 11 | import typing_extensions 12 | 13 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 14 | 15 | class LocationFix(google.protobuf.message.Message): 16 | """A navigation satellite fix for any Global Navigation Satellite System""" 17 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 18 | class _PositionCovarianceType: 19 | ValueType = typing.NewType('ValueType', builtins.int) 20 | V: typing_extensions.TypeAlias = ValueType 21 | class _PositionCovarianceTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[LocationFix._PositionCovarianceType.ValueType], builtins.type): 22 | DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor 23 | UNKNOWN: LocationFix._PositionCovarianceType.ValueType # 0 24 | APPROXIMATED: LocationFix._PositionCovarianceType.ValueType # 1 25 | DIAGONAL_KNOWN: LocationFix._PositionCovarianceType.ValueType # 2 26 | KNOWN: LocationFix._PositionCovarianceType.ValueType # 3 27 | class PositionCovarianceType(_PositionCovarianceType, metaclass=_PositionCovarianceTypeEnumTypeWrapper): 28 | """Type of position covariance""" 29 | pass 30 | 31 | UNKNOWN: LocationFix.PositionCovarianceType.ValueType # 0 32 | APPROXIMATED: LocationFix.PositionCovarianceType.ValueType # 1 33 | DIAGONAL_KNOWN: LocationFix.PositionCovarianceType.ValueType # 2 34 | KNOWN: LocationFix.PositionCovarianceType.ValueType # 3 35 | 36 | LATITUDE_FIELD_NUMBER: builtins.int 37 | LONGITUDE_FIELD_NUMBER: builtins.int 38 | ALTITUDE_FIELD_NUMBER: builtins.int 39 | POSITION_COVARIANCE_FIELD_NUMBER: builtins.int 40 | POSITION_COVARIANCE_TYPE_FIELD_NUMBER: builtins.int 41 | latitude: builtins.float 42 | """Latitude in degrees""" 43 | 44 | longitude: builtins.float 45 | """Longitude in degrees""" 46 | 47 | altitude: builtins.float 48 | """Altitude in meters""" 49 | 50 | @property 51 | def position_covariance(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: 52 | """Position covariance (m^2) defined relative to a tangential plane through the reported position. The components are East, North, and Up (ENU), in row-major order. 53 | length 9 54 | """ 55 | pass 56 | position_covariance_type: global___LocationFix.PositionCovarianceType.ValueType 57 | """If `position_covariance` is available, `position_covariance_type` must be set to indicate the type of covariance.""" 58 | 59 | def __init__(self, 60 | *, 61 | latitude: builtins.float = ..., 62 | longitude: builtins.float = ..., 63 | altitude: builtins.float = ..., 64 | position_covariance: typing.Optional[typing.Iterable[builtins.float]] = ..., 65 | position_covariance_type: global___LocationFix.PositionCovarianceType.ValueType = ..., 66 | ) -> None: ... 67 | def ClearField(self, field_name: typing_extensions.Literal["altitude",b"altitude","latitude",b"latitude","longitude",b"longitude","position_covariance",b"position_covariance","position_covariance_type",b"position_covariance_type"]) -> None: ... 68 | global___LocationFix = LocationFix 69 | -------------------------------------------------------------------------------- /can.py: -------------------------------------------------------------------------------- 1 | from diagnostic_msgs.msg import DiagnosticArray, DiagnosticStatus, KeyValue 2 | from sensor_msgs.msg import Imu 3 | from nav_msgs.msg import Odometry 4 | 5 | import rospy 6 | 7 | 8 | def get_utime(data): 9 | t = rospy.Time() 10 | t.secs, msecs = divmod(data["utime"], 1_000_000) 11 | t.nsecs = msecs * 1000 12 | 13 | return t 14 | 15 | 16 | def get_basic_can_msg(name, diag_data): 17 | values = [] 18 | for (key, value) in diag_data.items(): 19 | if key != "utime": 20 | values.append(KeyValue(key=key, value=str(round(value, 4)))) 21 | 22 | msg = DiagnosticArray() 23 | msg.header.stamp = get_utime(diag_data) 24 | msg.status.append(DiagnosticStatus(name=name, level=0, message="OK", values=values)) 25 | 26 | return (msg.header.stamp, "/diagnostics", msg) 27 | 28 | 29 | def get_odom_msg(pose_data): 30 | msg = Odometry() 31 | msg.header.frame_id = "map" 32 | msg.header.stamp = get_utime(pose_data) 33 | msg.child_frame_id = "base_link" 34 | msg.pose.pose.position.x = pose_data["pos"][0] 35 | msg.pose.pose.position.y = pose_data["pos"][1] 36 | msg.pose.pose.position.z = pose_data["pos"][2] 37 | msg.pose.pose.orientation.w = pose_data["orientation"][0] 38 | msg.pose.pose.orientation.x = pose_data["orientation"][1] 39 | msg.pose.pose.orientation.y = pose_data["orientation"][2] 40 | msg.pose.pose.orientation.z = pose_data["orientation"][3] 41 | msg.twist.twist.linear.x = pose_data["vel"][0] 42 | msg.twist.twist.linear.y = pose_data["vel"][1] 43 | msg.twist.twist.linear.z = pose_data["vel"][2] 44 | msg.twist.twist.angular.x = pose_data["rotation_rate"][0] 45 | msg.twist.twist.angular.y = pose_data["rotation_rate"][1] 46 | msg.twist.twist.angular.z = pose_data["rotation_rate"][2] 47 | 48 | return (msg.header.stamp, "/odom", msg) 49 | 50 | 51 | def get_imu_msg(imu_data): 52 | msg = Imu() 53 | msg.header.frame_id = "base_link" 54 | msg.header.stamp = get_utime(imu_data) 55 | msg.angular_velocity.x = imu_data["rotation_rate"][0] 56 | msg.angular_velocity.y = imu_data["rotation_rate"][1] 57 | msg.angular_velocity.z = imu_data["rotation_rate"][2] 58 | 59 | msg.linear_acceleration.x = imu_data["linear_accel"][0] 60 | msg.linear_acceleration.y = imu_data["linear_accel"][1] 61 | msg.linear_acceleration.z = imu_data["linear_accel"][2] 62 | 63 | msg.orientation.w = imu_data["q"][0] 64 | msg.orientation.x = imu_data["q"][1] 65 | msg.orientation.y = imu_data["q"][2] 66 | msg.orientation.z = imu_data["q"][3] 67 | 68 | return (msg.header.stamp, "/imu", msg) 69 | 70 | 71 | def get_can_parsers(nusc_can, scene_name): 72 | return [ 73 | [nusc_can.get_messages(scene_name, "ms_imu"), 0, get_imu_msg], 74 | [nusc_can.get_messages(scene_name, "pose"), 0, get_odom_msg], 75 | [ 76 | nusc_can.get_messages(scene_name, "steeranglefeedback"), 77 | 0, 78 | lambda x: get_basic_can_msg("Steering Angle", x), 79 | ], 80 | [ 81 | nusc_can.get_messages(scene_name, "vehicle_monitor"), 82 | 0, 83 | lambda x: get_basic_can_msg("Vehicle Monitor", x), 84 | ], 85 | [ 86 | nusc_can.get_messages(scene_name, "zoesensors"), 87 | 0, 88 | lambda x: get_basic_can_msg("Zoe Sensors", x), 89 | ], 90 | [ 91 | nusc_can.get_messages(scene_name, "zoe_veh_info"), 92 | 0, 93 | lambda x: get_basic_can_msg("Zoe Vehicle Info", x), 94 | ], 95 | ] 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nuscenes_to_ros2bag 2 | 3 | ## Usage 4 | 5 | ### Converting nuScenes data to ROS2 bag 6 | 1. Download the [nuScenes mini dataset](https://nuscenes.org/nuscenes). You will need to make 7 | an account and agree to the terms of use. 8 | 2. Extract the following files into the `data/` directory: 9 | 1. `can_bus.zip` to `data/` 10 | 2. `nuScenes-map-expansion-v1.3.zip` to `data/maps` 11 | 3. `v1.0-mini.tgz` to `data/` 12 | 3. Build and run the converter container with `./convert_to_ros2bag.sh` 13 | 14 | The file of `/data` structure is the same as that of [foxglove/nuscenes2mcap](https://github.com/foxglove/nuscenes2mcap) 15 | ``` 16 | /data 17 | ├── can_bus 18 | ├── maps 19 | │ ├── basemap 20 | │ ├── expansion 21 | │ └── prediction 22 | ├── samples 23 | │ ├── CAM_BACK 24 | │ ├── CAM_BACK_LEFT 25 | │ ├── CAM_BACK_RIGHT 26 | │ ├── CAM_FRONT 27 | │ ├── CAM_FRONT_LEFT 28 | │ ├── CAM_FRONT_RIGHT 29 | │ ├── LIDAR_TOP 30 | │ ├── RADAR_BACK_LEFT 31 | │ ├── RADAR_BACK_RIGHT 32 | │ ├── RADAR_FRONT 33 | │ ├── RADAR_FRONT_LEFT 34 | │ └── RADAR_FRONT_RIGHT 35 | ├── sweeps 36 | │ ├── CAM_BACK 37 | │ ├── CAM_BACK_LEFT 38 | │ ├── CAM_BACK_RIGHT 39 | │ ├── CAM_FRONT 40 | │ ├── CAM_FRONT_LEFT 41 | │ ├── CAM_FRONT_RIGHT 42 | │ ├── LIDAR_TOP 43 | │ ├── RADAR_BACK_LEFT 44 | │ ├── RADAR_BACK_RIGHT 45 | │ ├── RADAR_FRONT 46 | │ ├── RADAR_FRONT_LEFT 47 | │ └── RADAR_FRONT_RIGHT 48 | └── v1.0-mini 49 | ``` 50 | 51 | 52 | 53 | --- 54 | From [foxglove/nuscenes2mcap](https://github.com/foxglove/nuscenes2mcap) 55 | # nuscenes2mcap 56 | 57 | > _Convert [nuScenes](https://www.nuscenes.org/) data into [MCAP](https://mcap.dev/) format_ 58 | 59 | ## Introduction 60 | 61 | nuScenes is a large-scale dataset of autonomous driving in urban environments, provided free for non-commercial use. This project provides helper scripts to download the nuScenes dataset and convert scenes into [MCAP](https://mcap.dev) files for easy viewing in tools such as [Foxglove Studio](https://foxglove.dev/). 62 | 63 | ## Usage 64 | 65 | ### Converting the nuScenes data to MCAP 66 | 1. Download the [nuScenes mini dataset](https://nuscenes.org/nuscenes). You will need to make 67 | an account and agree to the terms of use. 68 | 1. Extract the following files into the `data/` directory: 69 | 1. `can_bus.zip` to `data/` 70 | 1. `nuScenes-map-expansion-v1.3.zip` to `data/maps` 71 | 1. `v1.0-mini.tgz` to `data/` 72 | 1. Build and run the converter container with `./convert_mini_scenes.sh` 73 | 74 | ### Uploading data and events to Foxglove Data Platform 75 | 76 | If you have a Foxglove Data Platform API key, you can use it to upload your scene data with: 77 | ``` 78 | docker build -t mcap_converter . 79 | export FOXGLOVE_DATA_PLATFORM_TOKEN= 80 | docker run -e FOXGLOVE_DATA_PLATFORM_TOKEN -v $(pwd)/output:/output \ 81 | mcap_converter python3 upload_mcap.py /output 82 | ``` 83 | 84 | This repo also contains a script that can create synthetic events from the MCAP data. 85 | ``` 86 | docker run -e FOXGLOVE_DATA_PLATFORM_TOKEN -v $(pwd)/output:/output \ 87 | mcap_converter python3 upload_events.py /output 88 | ``` 89 | 90 | ### Updating Protobuf definitions 91 | ``` 92 | pip install mypy-protobuf 93 | protoc --python_out=. --mypy_out=. --proto_path /path/to/foxglove/schemas/schemas/proto/ /path/to/foxglove/schemas/schemas/proto/foxglove/*.proto 94 | ``` 95 | 96 | ## License 97 | 98 | nuscenes2mcap is licensed under the [MIT License](https://opensource.org/licenses/MIT). 99 | 100 | ## Stay in touch 101 | 102 | Join our [Slack channel](https://foxglove.dev/join-slack) to ask questions, share feedback, and stay up to date on what our team is working on. 103 | -------------------------------------------------------------------------------- /foxglove/PointsAnnotation_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Color_pb2 7 | import foxglove.Point2_pb2 8 | import google.protobuf.descriptor 9 | import google.protobuf.internal.containers 10 | import google.protobuf.internal.enum_type_wrapper 11 | import google.protobuf.message 12 | import google.protobuf.timestamp_pb2 13 | import typing 14 | import typing_extensions 15 | 16 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 17 | 18 | class PointsAnnotation(google.protobuf.message.Message): 19 | """An array of points on a 2D image""" 20 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 21 | class _Type: 22 | ValueType = typing.NewType('ValueType', builtins.int) 23 | V: typing_extensions.TypeAlias = ValueType 24 | class _TypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[PointsAnnotation._Type.ValueType], builtins.type): 25 | DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor 26 | UNKNOWN: PointsAnnotation._Type.ValueType # 0 27 | POINTS: PointsAnnotation._Type.ValueType # 1 28 | LINE_LOOP: PointsAnnotation._Type.ValueType # 2 29 | LINE_STRIP: PointsAnnotation._Type.ValueType # 3 30 | LINE_LIST: PointsAnnotation._Type.ValueType # 4 31 | class Type(_Type, metaclass=_TypeEnumTypeWrapper): 32 | """Type of points annotation""" 33 | pass 34 | 35 | UNKNOWN: PointsAnnotation.Type.ValueType # 0 36 | POINTS: PointsAnnotation.Type.ValueType # 1 37 | LINE_LOOP: PointsAnnotation.Type.ValueType # 2 38 | LINE_STRIP: PointsAnnotation.Type.ValueType # 3 39 | LINE_LIST: PointsAnnotation.Type.ValueType # 4 40 | 41 | TIMESTAMP_FIELD_NUMBER: builtins.int 42 | TYPE_FIELD_NUMBER: builtins.int 43 | POINTS_FIELD_NUMBER: builtins.int 44 | OUTLINE_COLOR_FIELD_NUMBER: builtins.int 45 | OUTLINE_COLORS_FIELD_NUMBER: builtins.int 46 | FILL_COLOR_FIELD_NUMBER: builtins.int 47 | THICKNESS_FIELD_NUMBER: builtins.int 48 | @property 49 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 50 | """Timestamp of annotation""" 51 | pass 52 | type: global___PointsAnnotation.Type.ValueType 53 | """Type of points annotation to draw""" 54 | 55 | @property 56 | def points(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.Point2_pb2.Point2]: 57 | """Points in 2D image coordinates""" 58 | pass 59 | @property 60 | def outline_color(self) -> foxglove.Color_pb2.Color: 61 | """Outline color""" 62 | pass 63 | @property 64 | def outline_colors(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.Color_pb2.Color]: 65 | """Per-point colors, if `type` is `POINTS`, or per-segment stroke colors, if `type` is `LINE_LIST`.""" 66 | pass 67 | @property 68 | def fill_color(self) -> foxglove.Color_pb2.Color: 69 | """Fill color""" 70 | pass 71 | thickness: builtins.float 72 | """Stroke thickness""" 73 | 74 | def __init__(self, 75 | *, 76 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 77 | type: global___PointsAnnotation.Type.ValueType = ..., 78 | points: typing.Optional[typing.Iterable[foxglove.Point2_pb2.Point2]] = ..., 79 | outline_color: typing.Optional[foxglove.Color_pb2.Color] = ..., 80 | outline_colors: typing.Optional[typing.Iterable[foxglove.Color_pb2.Color]] = ..., 81 | fill_color: typing.Optional[foxglove.Color_pb2.Color] = ..., 82 | thickness: builtins.float = ..., 83 | ) -> None: ... 84 | def HasField(self, field_name: typing_extensions.Literal["fill_color",b"fill_color","outline_color",b"outline_color","timestamp",b"timestamp"]) -> builtins.bool: ... 85 | def ClearField(self, field_name: typing_extensions.Literal["fill_color",b"fill_color","outline_color",b"outline_color","outline_colors",b"outline_colors","points",b"points","thickness",b"thickness","timestamp",b"timestamp","type",b"type"]) -> None: ... 86 | global___PointsAnnotation = PointsAnnotation 87 | -------------------------------------------------------------------------------- /vm_helpers/Makefile: -------------------------------------------------------------------------------- 1 | SCRATCH_DISK_MOUNTPOINT = /media/scratch 2 | ZIP_DOWNLOAD_PATH = $(SCRATCH_DISK_MOUNTPOINT)/zip 3 | DATASET_PATH = $(SCRATCH_DISK_MOUNTPOINT)/dataset 4 | OUTPUT_PATH = $(SCRATCH_DISK_MOUNTPOINT)/output 5 | DATA_PLATFORM_HOST ?= api.foxglove.dev 6 | 7 | INPUT_BUCKET = gs://nuscenes-all/full/s3.amazonaws.com/data.nuscenes.org/public/v1.0 8 | 9 | AUX_INPUTS = can_bus.zip nuScenes-map-expansion-v1.3.zip 10 | 11 | MINI_DATASET_INPUTS = v1.0-mini.tgz 12 | 13 | FULL_DATASET_INPUTS = \ 14 | v1.0-trainval01_blobs.tgz \ 15 | v1.0-trainval02_blobs.tgz \ 16 | v1.0-trainval03_blobs.tgz \ 17 | v1.0-trainval04_blobs.tgz \ 18 | v1.0-trainval05_blobs.tgz \ 19 | v1.0-trainval06_blobs.tgz \ 20 | v1.0-trainval07_blobs.tgz \ 21 | v1.0-trainval08_blobs.tgz \ 22 | v1.0-trainval09_blobs.tgz \ 23 | v1.0-trainval10_blobs.tgz \ 24 | v1.0-trainval_meta.tgz 25 | 26 | CONVERTER_IMAGE_NAME = "mcap_converter" 27 | 28 | .apt-install.stamp: 29 | sudo apt-get install -y --no-install-recommends \ 30 | unzip build-essential docker.io e2fsprogs tmux pv 31 | touch $@ 32 | 33 | .PHONY: apt-install 34 | apt-install: .apt-install.stamp 35 | 36 | .PHONY: scratch-disk 37 | scratch-disk: apt-install 38 | sudo python3 ready_scratch_disk.py --commit 39 | 40 | .download-aux-inputs.stamp: scratch-disk 41 | @echo downloading CAN and map data 42 | mkdir -p $(ZIP_DOWNLOAD_PATH) $(DATASET_PATH) 43 | gsutil cp "$(INPUT_BUCKET)/can_bus.zip" "$(ZIP_DOWNLOAD_PATH)/can_bus.zip" 44 | unzip "$(ZIP_DOWNLOAD_PATH)/can_bus.zip" -d $(DATASET_PATH) 45 | gsutil cp "$(INPUT_BUCKET)/nuScenes-map-expansion-v1.3.zip" "$(ZIP_DOWNLOAD_PATH)/nuScenes-map-expansion-v1.3.zip" 46 | unzip "$(ZIP_DOWNLOAD_PATH)/nuScenes-map-expansion-v1.3.zip" -d "$(DATASET_PATH)/maps" 47 | touch $@ 48 | 49 | .download-mini-dataset.stamp: .download-aux-inputs.stamp 50 | @echo downloading mini dataset 51 | mkdir -p $(DATASET_PATH) 52 | for tgz in $(MINI_DATASET_INPUTS); do \ 53 | gsutil cp "$(INPUT_BUCKET)/$${tgz}" - | pv | tar -xzC $(DATASET_PATH); \ 54 | done 55 | touch $@ 56 | 57 | .PHONY: download-mini-dataset 58 | download-mini-dataset: .download-mini-dataset.stamp 59 | 60 | .download-full-dataset.stamp: scratch-disk 61 | @echo "downloading full dataset" 62 | mkdir -p $(DATASET_PATH) 63 | for tgz in $(FULL_DATASET_INPUTS); do \ 64 | gsutil cp "$(INPUT_BUCKET)/$${tgz}" - | pv | tar -xzC $(DATASET_PATH); \ 65 | done 66 | touch $@ 67 | 68 | .PHONY: download-full-dataset 69 | download-full-dataset: .download-full-dataset.stamp .download-aux-inputs.stamp 70 | 71 | .PHONY: convert-mini-dataset 72 | convert-mini-dataset: converter-image download-mini-dataset 73 | docker run -t --rm \ 74 | --user $(id -u):$(id -g) \ 75 | -v $(DATASET_PATH):/data \ 76 | -v $(OUTPUT_PATH):/output \ 77 | $(CONVERTER_IMAGE_NAME) \ 78 | python3 convert_to_mcap.py \ 79 | --dataset-name "v1.0-mini" \ 80 | --data-dir /data \ 81 | --output-dir /output 82 | 83 | .PHONY: convert-full-dataset 84 | convert-full-dataset: converter-image download-full-dataset 85 | docker run -t --rm \ 86 | --user $(id -u):$(id -g) \ 87 | -v $(DATASET_PATH):/data \ 88 | -v $(OUTPUT_PATH):/output \ 89 | $(CONVERTER_IMAGE_NAME) \ 90 | python3 convert_to_mcap.py \ 91 | --dataset-name "v1.0-trainval" \ 92 | --data-dir /data \ 93 | --output-dir /output 94 | 95 | .PHONY: upload-mcaps 96 | upload-mcaps: converter-image 97 | docker run -t --rm \ 98 | -v $(OUTPUT_PATH):/output \ 99 | -e FOXGLOVE_DATA_PLATFORM_TOKEN \ 100 | $(CONVERTER_IMAGE_NAME) \ 101 | python3 upload_mcap.py /output --host $(DATA_PLATFORM_HOST) 102 | 103 | 104 | .PHONY: upload-events 105 | upload-events: converter-image 106 | docker run -t --rm \ 107 | -v $(OUTPUT_PATH):/output \ 108 | -e FOXGLOVE_DATA_PLATFORM_TOKEN \ 109 | $(CONVERTER_IMAGE_NAME) \ 110 | python3 upload_events.py /output --host $(DATA_PLATFORM_HOST) --commit 111 | 112 | 113 | .PHONY: delete-all-events 114 | delete-all-events: converter-image 115 | docker run -t --rm \ 116 | -e FOXGLOVE_DATA_PLATFORM_TOKEN \ 117 | $(CONVERTER_IMAGE_NAME) \ 118 | python3 delete_all_events.py --host $(DATA_PLATFORM_HOST) --commit 119 | 120 | 121 | .PHONY: converter-image 122 | converter-image: 123 | docker build -t $(CONVERTER_IMAGE_NAME) .. 124 | 125 | .PHONY: clean 126 | clean: 127 | rm -rf $(ZIP_DOWNLOAD_PATH) $(DATASET_PATH) $(OUTPUT_PATH) 128 | rm -f .*.stamp 129 | -------------------------------------------------------------------------------- /upload_events.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from datetime import datetime 3 | import os 4 | import sys 5 | from pathlib import Path 6 | 7 | from foxglove_data_platform.client import Client 8 | from mcap.mcap0.reader import make_reader 9 | 10 | from sensor_msgs.msg import Imu 11 | from foxglove.SceneUpdate_pb2 import SceneUpdate 12 | 13 | from device_name import make_device_name 14 | from event_helpers.annotators import Annotator 15 | from event_helpers.client_utils import get_all_events_for_device 16 | 17 | 18 | def main(): 19 | parser = argparse.ArgumentParser() 20 | parser.add_argument("files", nargs="+", help="MCAP files to annotate") 21 | parser.add_argument( 22 | "--token", 23 | "-t", 24 | help="data platform secret token (if not provided, FOXGLOVE_DATA_PLATFORM_TOKEN from environment is used)", 25 | ) 26 | parser.add_argument("--host", default="api.foxglove.dev", help="custom host to direct API requests to") 27 | parser.add_argument("--commit", "-y", action="store_true", help="actually send the events") 28 | args = parser.parse_args() 29 | if args.token is None: 30 | token = os.environ.get("FOXGLOVE_DATA_PLATFORM_TOKEN") 31 | if token is None: 32 | print("FOXGLOVE_DATA_PLATFORM_TOKEN not in environment", file=sys.stderr) 33 | return 1 34 | args.token = token 35 | 36 | client = Client(token=args.token, host=args.host) 37 | device_ids = {resp["name"]: resp["id"] for resp in client.get_devices()} 38 | 39 | filepaths = [] 40 | for name in args.files: 41 | path = Path(name) 42 | if path.is_dir(): 43 | filepaths.extend(path.glob("*.mcap")) 44 | elif path.is_file(): 45 | filepaths.append(path) 46 | else: 47 | raise RuntimeError(f"path does not exist: {name}") 48 | 49 | for filepath in filepaths: 50 | print(f"scanning {filepath} for events...") 51 | annotator = Annotator() 52 | events = [] 53 | device_id = None 54 | summary = None 55 | with open(filepath, "rb") as f: 56 | reader = make_reader(f) 57 | summary = reader.get_summary() 58 | scene_info = next( 59 | (metadata for metadata in reader.iter_metadata() if metadata.name == "scene-info"), 60 | None, 61 | ) 62 | device_name = make_device_name(scene_info.metadata) 63 | try: 64 | device_id = device_ids[device_name] 65 | except KeyError: 66 | print( 67 | f"device ID not found for '{device_name}' - has this MCAP been uploaded?", 68 | file=sys.stderr, 69 | ) 70 | return 1 71 | 72 | events.extend(annotator.on_mcap_start(summary, scene_info)) 73 | for schema, _, message in reader.iter_messages(topics=["/markers/annotations", "/imu"]): 74 | if schema.name == "sensor_msgs/Imu": 75 | imu = Imu() 76 | imu.deserialize(message.data) 77 | events.extend(annotator.on_imu(imu)) 78 | 79 | if schema.name == "foxglove.SceneUpdate": 80 | scene_update = SceneUpdate() 81 | scene_update.ParseFromString(message.data) 82 | events.extend(annotator.on_scene_update(scene_update)) 83 | 84 | events.extend(annotator.on_mcap_end()) 85 | 86 | # save existing events 87 | old_events = get_all_events_for_device( 88 | client=client, 89 | device_id=device_id, 90 | start=datetime.fromtimestamp(float(summary.statistics.message_start_time) / 1e9), 91 | end=datetime.fromtimestamp(float(summary.statistics.message_end_time) / 1e9), 92 | ) 93 | 94 | print(f"uploading {len(events)} events for {filepath} ...") 95 | for event in events: 96 | # create new events 97 | if args.commit: 98 | client.create_event( 99 | device_id=device_id, 100 | time=datetime.fromtimestamp(float(event.timestamp_ns) / 1e9), 101 | duration=event.duration_ns, 102 | metadata=event.metadata, 103 | ) 104 | else: 105 | print(f"would upload: {event}") 106 | 107 | # destroy old events once new events have been uploaded 108 | print(f"deleting {len(old_events)} old events for {filepath} ...") 109 | for old_event in old_events: 110 | if args.commit: 111 | client.delete_event(event_id=old_event["id"]) 112 | else: 113 | print(f"would delete: {old_event}") 114 | return 0 115 | 116 | 117 | if __name__ == "__main__": 118 | sys.exit(main()) 119 | -------------------------------------------------------------------------------- /foxglove/LinePrimitive_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.Color_pb2 7 | import foxglove.Point3_pb2 8 | import foxglove.Pose_pb2 9 | import google.protobuf.descriptor 10 | import google.protobuf.internal.containers 11 | import google.protobuf.internal.enum_type_wrapper 12 | import google.protobuf.message 13 | import typing 14 | import typing_extensions 15 | 16 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 17 | 18 | class LinePrimitive(google.protobuf.message.Message): 19 | """(Experimental, subject to change) A primitive representing a series of points connected by lines""" 20 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 21 | class _Type: 22 | ValueType = typing.NewType('ValueType', builtins.int) 23 | V: typing_extensions.TypeAlias = ValueType 24 | class _TypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[LinePrimitive._Type.ValueType], builtins.type): 25 | DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor 26 | LINE_STRIP: LinePrimitive._Type.ValueType # 0 27 | """0-1, 1-2, ..., (n-1)-n""" 28 | 29 | LINE_LOOP: LinePrimitive._Type.ValueType # 1 30 | """0-1, 1-2, ..., (n-1)-n, n-0""" 31 | 32 | LINE_LIST: LinePrimitive._Type.ValueType # 2 33 | """0-1, 2-3, 4-5, ...""" 34 | 35 | class Type(_Type, metaclass=_TypeEnumTypeWrapper): 36 | """(Experimental, subject to change) An enumeration indicating how input points should be interpreted to create lines""" 37 | pass 38 | 39 | LINE_STRIP: LinePrimitive.Type.ValueType # 0 40 | """0-1, 1-2, ..., (n-1)-n""" 41 | 42 | LINE_LOOP: LinePrimitive.Type.ValueType # 1 43 | """0-1, 1-2, ..., (n-1)-n, n-0""" 44 | 45 | LINE_LIST: LinePrimitive.Type.ValueType # 2 46 | """0-1, 2-3, 4-5, ...""" 47 | 48 | 49 | TYPE_FIELD_NUMBER: builtins.int 50 | POSE_FIELD_NUMBER: builtins.int 51 | THICKNESS_FIELD_NUMBER: builtins.int 52 | SCALE_INVARIANT_FIELD_NUMBER: builtins.int 53 | POINTS_FIELD_NUMBER: builtins.int 54 | COLOR_FIELD_NUMBER: builtins.int 55 | COLORS_FIELD_NUMBER: builtins.int 56 | INDICES_FIELD_NUMBER: builtins.int 57 | type: global___LinePrimitive.Type.ValueType 58 | """Drawing primitive to use for lines""" 59 | 60 | @property 61 | def pose(self) -> foxglove.Pose_pb2.Pose: 62 | """Origin of lines relative to reference frame""" 63 | pass 64 | thickness: builtins.float 65 | """Line thickness""" 66 | 67 | scale_invariant: builtins.bool 68 | """Indicates whether `thickness` is a fixed size in screen pixels (true), or specified in world coordinates and scales with distance from the camera (false)""" 69 | 70 | @property 71 | def points(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.Point3_pb2.Point3]: 72 | """Points along the line""" 73 | pass 74 | @property 75 | def color(self) -> foxglove.Color_pb2.Color: 76 | """Solid color to use for the whole line. One of `color` or `colors` must be provided.""" 77 | pass 78 | @property 79 | def colors(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.Color_pb2.Color]: 80 | """Per-point colors (if specified, must have the same length as `points`). One of `color` or `colors` must be provided.""" 81 | pass 82 | @property 83 | def indices(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: 84 | """Indices into the `points` and `colors` attribute arrays, which can be used to avoid duplicating attribute data. 85 | 86 | If omitted or empty, indexing will not be used. This default behavior is equivalent to specifying [0, 1, ..., N-1] for the indices (where N is the number of `points` provided). 87 | """ 88 | pass 89 | def __init__(self, 90 | *, 91 | type: global___LinePrimitive.Type.ValueType = ..., 92 | pose: typing.Optional[foxglove.Pose_pb2.Pose] = ..., 93 | thickness: builtins.float = ..., 94 | scale_invariant: builtins.bool = ..., 95 | points: typing.Optional[typing.Iterable[foxglove.Point3_pb2.Point3]] = ..., 96 | color: typing.Optional[foxglove.Color_pb2.Color] = ..., 97 | colors: typing.Optional[typing.Iterable[foxglove.Color_pb2.Color]] = ..., 98 | indices: typing.Optional[typing.Iterable[builtins.int]] = ..., 99 | ) -> None: ... 100 | def HasField(self, field_name: typing_extensions.Literal["color",b"color","pose",b"pose"]) -> builtins.bool: ... 101 | def ClearField(self, field_name: typing_extensions.Literal["color",b"color","colors",b"colors","indices",b"indices","points",b"points","pose",b"pose","scale_invariant",b"scale_invariant","thickness",b"thickness","type",b"type"]) -> None: ... 102 | global___LinePrimitive = LinePrimitive 103 | -------------------------------------------------------------------------------- /nuscenes2bag/sensor_utils.py: -------------------------------------------------------------------------------- 1 | from utils import * 2 | 3 | def get_radar(data_path, sample_data, frame_id): 4 | pc_filename = data_path / sample_data['filename'] 5 | pc = pypcd.PointCloud.from_path(pc_filename) 6 | msg = numpy_pc2.array_to_pointcloud2(pc.pc_data) 7 | msg.header.frame_id = frame_id 8 | msg.header.stamp = get_time(sample_data) 9 | return msg 10 | 11 | def get_lidar(data_path, sample_data, frame_id): 12 | pc_filename = data_path / sample_data['filename'] 13 | pc_filesize = os.stat(pc_filename).st_size 14 | 15 | with open(pc_filename, 'rb') as pc_file: 16 | msg = PointCloud2() 17 | msg.header.frame_id = frame_id 18 | msg.header.stamp = get_time(sample_data) 19 | 20 | msg.fields = [ 21 | PointField(name='x', offset=0, datatype=PointField.FLOAT32, count=1), 22 | PointField(name='y', offset=4, datatype=PointField.FLOAT32, count=1), 23 | PointField(name='z', offset=8, datatype=PointField.FLOAT32, count=1), 24 | PointField(name='intensity', offset=12, datatype=PointField.FLOAT32, count=1), 25 | PointField(name='ring', offset=16, datatype=PointField.FLOAT32, count=1), 26 | ] 27 | 28 | msg.is_bigendian = False 29 | msg.is_dense = True 30 | msg.point_step = len(msg.fields) * 4 # 4 bytes per field 31 | msg.row_step = pc_filesize 32 | msg.width = round(pc_filesize / msg.point_step) 33 | msg.height = 1 # unordered 34 | msg.data = pc_file.read() 35 | return msg 36 | 37 | def get_camera(data_path, sample_data, frame_id): 38 | jpg_filename = data_path / sample_data['filename'] 39 | msg = CompressedImage() 40 | msg.header.frame_id = frame_id 41 | msg.header.stamp = get_time(sample_data) 42 | msg.format = "jpeg" 43 | with open(jpg_filename, 'rb') as jpg_file: 44 | msg.data = jpg_file.read() 45 | return msg 46 | 47 | def get_camera_info(nusc, sample_data, frame_id): 48 | calib = nusc.get('calibrated_sensor', sample_data['calibrated_sensor_token']) 49 | 50 | msg_info = CameraInfo() 51 | msg_info.header.frame_id = frame_id 52 | msg_info.header.stamp = get_time(sample_data) 53 | msg_info.height = sample_data['height'] 54 | msg_info.width = sample_data['width'] 55 | msg_info.k[0] = calib['camera_intrinsic'][0][0] 56 | msg_info.k[1] = calib['camera_intrinsic'][0][1] 57 | msg_info.k[2] = calib['camera_intrinsic'][0][2] 58 | msg_info.k[3] = calib['camera_intrinsic'][1][0] 59 | msg_info.k[4] = calib['camera_intrinsic'][1][1] 60 | msg_info.k[5] = calib['camera_intrinsic'][1][2] 61 | msg_info.k[6] = calib['camera_intrinsic'][2][0] 62 | msg_info.k[7] = calib['camera_intrinsic'][2][1] 63 | msg_info.k[8] = calib['camera_intrinsic'][2][2] 64 | 65 | msg_info.r[0] = 1 66 | msg_info.r[3] = 1 67 | msg_info.r[6] = 1 68 | 69 | msg_info.p[0] = msg_info.k[0] 70 | msg_info.p[1] = msg_info.k[1] 71 | msg_info.p[2] = msg_info.k[2] 72 | msg_info.p[3] = 0 73 | msg_info.p[4] = msg_info.k[3] 74 | msg_info.p[5] = msg_info.k[4] 75 | msg_info.p[6] = msg_info.k[5] 76 | msg_info.p[7] = 0 77 | msg_info.p[8] = 0 78 | msg_info.p[9] = 0 79 | msg_info.p[10] = 1 80 | msg_info.p[11] = 0 81 | return msg_info 82 | 83 | def get_transform(data): 84 | t = Transform() 85 | t.translation.x = data['translation'][0] 86 | t.translation.y = data['translation'][1] 87 | t.translation.z = data['translation'][2] 88 | 89 | t.rotation.w = data['rotation'][0] 90 | t.rotation.x = data['rotation'][1] 91 | t.rotation.y = data['rotation'][2] 92 | t.rotation.z = data['rotation'][3] 93 | 94 | return t 95 | 96 | def get_tfs(nusc, sample): 97 | sample_lidar = nusc.get('sample_data', sample['data']['LIDAR_TOP']) 98 | ego_pose = nusc.get('ego_pose', sample_lidar['ego_pose_token']) 99 | stamp = get_time(ego_pose) 100 | 101 | transforms = [] 102 | 103 | # create ego transform 104 | ego_tf = TransformStamped() 105 | ego_tf.header.frame_id = 'map' 106 | ego_tf.header.stamp = stamp 107 | ego_tf.child_frame_id = 'base_link' 108 | ego_tf.transform = get_transform(ego_pose) 109 | transforms.append(ego_tf) 110 | 111 | for (sensor_id, sample_token) in sample['data'].items(): 112 | sample_data = nusc.get('sample_data', sample_token) 113 | 114 | # create sensor transform 115 | sensor_tf = TransformStamped() 116 | sensor_tf.header.frame_id = 'base_link' 117 | sensor_tf.header.stamp = stamp 118 | sensor_tf.child_frame_id = sensor_id 119 | sensor_tf.transform = get_transform( 120 | nusc.get('calibrated_sensor', sample_data['calibrated_sensor_token'])) 121 | transforms.append(sensor_tf) 122 | 123 | return transforms 124 | 125 | def get_tfmessage(nusc, sample): 126 | # get transforms for the current sample 127 | tf_array = TFMessage() 128 | tf_array.transforms = get_tfs(nusc, sample) 129 | 130 | # add transforms from the next sample to enable interpolation 131 | next_sample = nusc.get('sample', sample['next']) if sample.get('next') != '' else None 132 | if next_sample is not None: 133 | tf_array.transforms += get_tfs(nusc, next_sample) 134 | 135 | return tf_array -------------------------------------------------------------------------------- /foxglove/CameraCalibration_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import google.protobuf.descriptor 7 | import google.protobuf.internal.containers 8 | import google.protobuf.message 9 | import google.protobuf.timestamp_pb2 10 | import typing 11 | import typing_extensions 12 | 13 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 14 | 15 | class CameraCalibration(google.protobuf.message.Message): 16 | """Camera calibration parameters""" 17 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 18 | TIMESTAMP_FIELD_NUMBER: builtins.int 19 | FRAME_ID_FIELD_NUMBER: builtins.int 20 | WIDTH_FIELD_NUMBER: builtins.int 21 | HEIGHT_FIELD_NUMBER: builtins.int 22 | DISTORTION_MODEL_FIELD_NUMBER: builtins.int 23 | D_FIELD_NUMBER: builtins.int 24 | K_FIELD_NUMBER: builtins.int 25 | R_FIELD_NUMBER: builtins.int 26 | P_FIELD_NUMBER: builtins.int 27 | @property 28 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 29 | """Timestamp of calibration data""" 30 | pass 31 | frame_id: typing.Text 32 | """Frame of reference for the camera. The origin of the frame is the optical center of the camera. +x points to the right in the image, +y points down, and +z points into the plane of the image.""" 33 | 34 | width: builtins.int 35 | """Image width""" 36 | 37 | height: builtins.int 38 | """Image height""" 39 | 40 | distortion_model: typing.Text 41 | """Name of distortion model""" 42 | 43 | @property 44 | def D(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: 45 | """Distortion parameters""" 46 | pass 47 | @property 48 | def K(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: 49 | """Intrinsic camera matrix (3x3 row-major matrix) 50 | 51 | A 3x3 row-major matrix for the raw (distorted) image. 52 | 53 | Projects 3D points in the camera coordinate frame to 2D pixel coordinates using the focal lengths (fx, fy) and principal point (cx, cy). 54 | 55 | ``` 56 | [fx 0 cx] 57 | K = [ 0 fy cy] 58 | [ 0 0 1] 59 | ``` 60 | length 9 61 | """ 62 | pass 63 | @property 64 | def R(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: 65 | """Rectification matrix (3x3 row-major matrix) 66 | 67 | A rotation matrix aligning the camera coordinate system to the ideal stereo image plane so that epipolar lines in both stereo images are parallel. 68 | length 9 69 | """ 70 | pass 71 | @property 72 | def P(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: 73 | """Projection/camera matrix (3x4 row-major matrix) 74 | 75 | ``` 76 | [fx' 0 cx' Tx] 77 | P = [ 0 fy' cy' Ty] 78 | [ 0 0 1 0] 79 | ``` 80 | 81 | By convention, this matrix specifies the intrinsic (camera) matrix of the processed (rectified) image. That is, the left 3x3 portion is the normal camera intrinsic matrix for the rectified image. 82 | 83 | It projects 3D points in the camera coordinate frame to 2D pixel coordinates using the focal lengths (fx', fy') and principal point (cx', cy') - these may differ from the values in K. 84 | 85 | For monocular cameras, Tx = Ty = 0. Normally, monocular cameras will also have R = the identity and P[1:3,1:3] = K. 86 | 87 | For a stereo pair, the fourth column [Tx Ty 0]' is related to the position of the optical center of the second camera in the first camera's frame. We assume Tz = 0 so both cameras are in the same stereo image plane. The first camera always has Tx = Ty = 0. For the right (second) camera of a horizontal stereo pair, Ty = 0 and Tx = -fx' * B, where B is the baseline between the cameras. 88 | 89 | Given a 3D point [X Y Z]', the projection (x, y) of the point onto the rectified image is given by: 90 | 91 | ``` 92 | [u v w]' = P * [X Y Z 1]' 93 | x = u / w 94 | y = v / w 95 | ``` 96 | 97 | This holds for both images of a stereo pair. 98 | length 12 99 | """ 100 | pass 101 | def __init__(self, 102 | *, 103 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 104 | frame_id: typing.Text = ..., 105 | width: builtins.int = ..., 106 | height: builtins.int = ..., 107 | distortion_model: typing.Text = ..., 108 | D: typing.Optional[typing.Iterable[builtins.float]] = ..., 109 | K: typing.Optional[typing.Iterable[builtins.float]] = ..., 110 | R: typing.Optional[typing.Iterable[builtins.float]] = ..., 111 | P: typing.Optional[typing.Iterable[builtins.float]] = ..., 112 | ) -> None: ... 113 | def HasField(self, field_name: typing_extensions.Literal["timestamp",b"timestamp"]) -> builtins.bool: ... 114 | def ClearField(self, field_name: typing_extensions.Literal["D",b"D","K",b"K","P",b"P","R",b"R","distortion_model",b"distortion_model","frame_id",b"frame_id","height",b"height","timestamp",b"timestamp","width",b"width"]) -> None: ... 115 | global___CameraCalibration = CameraCalibration 116 | -------------------------------------------------------------------------------- /event_helpers/annotators.py: -------------------------------------------------------------------------------- 1 | from typing import List, Dict 2 | 3 | from . import Event 4 | 5 | 6 | def to_ns(rospy_time) -> int: 7 | """Converts a rospy.Time object to an integer nanosecond count.""" 8 | return rospy_time.nsecs + (1_000_000_000 * rospy_time.secs) 9 | 10 | 11 | class LatchingEventSource: 12 | def __init__(self, cooldown_period=100_000_000): 13 | """base class for any event source that implements""" 14 | self._start_time = None 15 | self._last_activated_time = None 16 | self._cooldown_period = cooldown_period 17 | 18 | def activate(self, value) -> bool: 19 | raise NotImplementedError(f"Implement this method, using {value}") 20 | 21 | def event_metadata(self) -> Dict[str, str]: 22 | raise NotImplementedError("Implement this method") 23 | 24 | def reset(self): 25 | raise NotImplementedError("Implement this method") 26 | 27 | def tick(self, value, timestamp_ns): 28 | if self.activate(value): 29 | if self._start_time is None: 30 | self._start_time = timestamp_ns 31 | self._last_activated_time = timestamp_ns 32 | return [] 33 | if self._last_activated_time is None: 34 | return [] 35 | if (timestamp_ns - self._last_activated_time) < self._cooldown_period: 36 | return [] 37 | result = Event( 38 | timestamp_ns=self._start_time, 39 | duration_ns=(self._last_activated_time - self._start_time), 40 | metadata=self.event_metadata(), 41 | ) 42 | self._start_time = None 43 | self._last_activated_time = None 44 | self.reset() 45 | return [result] 46 | 47 | def finish(self, end_timestamp_ns): 48 | if self._start_time is not None: 49 | return [ 50 | Event( 51 | timestamp_ns=self._start_time, 52 | duration_ns=(end_timestamp_ns - self._start_time), 53 | metadata=self.event_metadata(), 54 | ) 55 | ] 56 | return [] 57 | 58 | 59 | class PedestrianEventSource(LatchingEventSource): 60 | def __init__(self): 61 | super().__init__() 62 | self.max_pedestrians = 0 63 | 64 | def activate(self, value): 65 | self.max_pedestrians = max(self.max_pedestrians, value) 66 | return value > 10 67 | 68 | def event_metadata(self): 69 | return { 70 | "category": "many_pedestrians", 71 | "max_pedestrians": str(self.max_pedestrians), 72 | } 73 | 74 | def reset(self): 75 | self.max_pedestrians = 0 76 | 77 | 78 | class AccelerationEventSource(LatchingEventSource): 79 | def __init__(self): 80 | super().__init__() 81 | self.max_acceleration = 0 82 | 83 | def activate(self, value): 84 | if abs(value) > abs(self.max_acceleration): 85 | self.max_acceleration = value 86 | return abs(value) > 1.5 87 | 88 | def event_metadata(self): 89 | return { 90 | "category": "large_acceleration", 91 | "max": f"{self.max_acceleration:.2f}", 92 | } 93 | 94 | def reset(self): 95 | self.max_acceleration = 0 96 | 97 | 98 | class Annotator: 99 | def __init__(self): 100 | self.summary = None 101 | self.ped_event_source = PedestrianEventSource() 102 | self.acc_event_source = AccelerationEventSource() 103 | 104 | def on_mcap_start(self, summary, scene_info=None) -> List[Event]: 105 | self.summary = summary 106 | if scene_info is None: 107 | return [] 108 | tags = [tag.strip() for tag in scene_info.metadata["description"].split(",")] 109 | metadata = {tag: "true" for tag in tags} 110 | metadata["category"] = "scene_description" 111 | metadata["nuscene"] = scene_info.metadata["name"] 112 | metadata["city"] = scene_info.metadata["location"] 113 | 114 | return [ 115 | Event( 116 | timestamp_ns=summary.statistics.message_start_time, 117 | duration_ns=(summary.statistics.message_end_time - summary.statistics.message_start_time), 118 | metadata=metadata, 119 | ) 120 | ] 121 | 122 | def on_imu(self, imu) -> List[Event]: 123 | longitudinal_acceleration = imu.linear_acceleration.x 124 | return self.acc_event_source.tick(longitudinal_acceleration, to_ns(imu.header.stamp)) 125 | 126 | def on_scene_update(self, scene_update) -> List[Event]: 127 | num_peds = 0 128 | timestamp = None 129 | for entity in scene_update.entities: 130 | if timestamp is None: 131 | timestamp = entity.timestamp 132 | for metadata in entity.metadata: 133 | if metadata.key == "category" and metadata.value.startswith("human.pedestrian"): 134 | num_peds += 1 135 | 136 | stamp_ns = timestamp.nanos + (1_000_000_000 * timestamp.seconds) 137 | 138 | return self.ped_event_source.tick(num_peds, stamp_ns) 139 | 140 | def on_mcap_end(self) -> List[Event]: 141 | if self.summary is None: 142 | return [] 143 | final_ped_events = self.ped_event_source.finish(self.summary.statistics.message_end_time) 144 | final_acc_events = self.acc_event_source.finish(self.summary.statistics.message_end_time) 145 | return final_ped_events + final_acc_events 146 | -------------------------------------------------------------------------------- /foxglove/SceneEntity_pb2.pyi: -------------------------------------------------------------------------------- 1 | """ 2 | @generated by mypy-protobuf. Do not edit manually! 3 | isort:skip_file 4 | """ 5 | import builtins 6 | import foxglove.ArrowPrimitive_pb2 7 | import foxglove.CubePrimitive_pb2 8 | import foxglove.CylinderPrimitive_pb2 9 | import foxglove.KeyValuePair_pb2 10 | import foxglove.LinePrimitive_pb2 11 | import foxglove.ModelPrimitive_pb2 12 | import foxglove.SpherePrimitive_pb2 13 | import foxglove.TextPrimitive_pb2 14 | import foxglove.TriangleListPrimitive_pb2 15 | import google.protobuf.descriptor 16 | import google.protobuf.duration_pb2 17 | import google.protobuf.internal.containers 18 | import google.protobuf.message 19 | import google.protobuf.timestamp_pb2 20 | import typing 21 | import typing_extensions 22 | 23 | DESCRIPTOR: google.protobuf.descriptor.FileDescriptor 24 | 25 | class SceneEntity(google.protobuf.message.Message): 26 | """(Experimental, subject to change) A visual element in a 3D scene. An entity may be composed of multiple primitives which all share the same frame of reference.""" 27 | DESCRIPTOR: google.protobuf.descriptor.Descriptor 28 | TIMESTAMP_FIELD_NUMBER: builtins.int 29 | FRAME_ID_FIELD_NUMBER: builtins.int 30 | ID_FIELD_NUMBER: builtins.int 31 | LIFETIME_FIELD_NUMBER: builtins.int 32 | FRAME_LOCKED_FIELD_NUMBER: builtins.int 33 | METADATA_FIELD_NUMBER: builtins.int 34 | ARROWS_FIELD_NUMBER: builtins.int 35 | CUBES_FIELD_NUMBER: builtins.int 36 | SPHERES_FIELD_NUMBER: builtins.int 37 | CYLINDERS_FIELD_NUMBER: builtins.int 38 | LINES_FIELD_NUMBER: builtins.int 39 | TRIANGLES_FIELD_NUMBER: builtins.int 40 | TEXTS_FIELD_NUMBER: builtins.int 41 | MODELS_FIELD_NUMBER: builtins.int 42 | @property 43 | def timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: 44 | """Timestamp of the entity""" 45 | pass 46 | frame_id: typing.Text 47 | """Frame of reference""" 48 | 49 | id: typing.Text 50 | """Identifier for the entity. A entity will replace any prior entity on the same topic with the same `id`.""" 51 | 52 | @property 53 | def lifetime(self) -> google.protobuf.duration_pb2.Duration: 54 | """Length of time (relative to `timestamp`) after which the entity should be automatically removed. Zero value indicates the entity should remain visible until it is replaced or deleted.""" 55 | pass 56 | frame_locked: builtins.bool 57 | """Whether the entity should keep its location in the fixed frame (false) or follow the frame specified in `frame_id` as it moves relative to the fixed frame (true)""" 58 | 59 | @property 60 | def metadata(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.KeyValuePair_pb2.KeyValuePair]: 61 | """Additional user-provided metadata associated with the entity. Keys must be unique.""" 62 | pass 63 | @property 64 | def arrows(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.ArrowPrimitive_pb2.ArrowPrimitive]: 65 | """Arrow primitives""" 66 | pass 67 | @property 68 | def cubes(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.CubePrimitive_pb2.CubePrimitive]: 69 | """Cube primitives""" 70 | pass 71 | @property 72 | def spheres(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.SpherePrimitive_pb2.SpherePrimitive]: 73 | """Sphere primitives""" 74 | pass 75 | @property 76 | def cylinders(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.CylinderPrimitive_pb2.CylinderPrimitive]: 77 | """Cylinder primitives""" 78 | pass 79 | @property 80 | def lines(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.LinePrimitive_pb2.LinePrimitive]: 81 | """Line primitives""" 82 | pass 83 | @property 84 | def triangles(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.TriangleListPrimitive_pb2.TriangleListPrimitive]: 85 | """Triangle list primitives""" 86 | pass 87 | @property 88 | def texts(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.TextPrimitive_pb2.TextPrimitive]: 89 | """Text primitives""" 90 | pass 91 | @property 92 | def models(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[foxglove.ModelPrimitive_pb2.ModelPrimitive]: 93 | """Model primitives""" 94 | pass 95 | def __init__(self, 96 | *, 97 | timestamp: typing.Optional[google.protobuf.timestamp_pb2.Timestamp] = ..., 98 | frame_id: typing.Text = ..., 99 | id: typing.Text = ..., 100 | lifetime: typing.Optional[google.protobuf.duration_pb2.Duration] = ..., 101 | frame_locked: builtins.bool = ..., 102 | metadata: typing.Optional[typing.Iterable[foxglove.KeyValuePair_pb2.KeyValuePair]] = ..., 103 | arrows: typing.Optional[typing.Iterable[foxglove.ArrowPrimitive_pb2.ArrowPrimitive]] = ..., 104 | cubes: typing.Optional[typing.Iterable[foxglove.CubePrimitive_pb2.CubePrimitive]] = ..., 105 | spheres: typing.Optional[typing.Iterable[foxglove.SpherePrimitive_pb2.SpherePrimitive]] = ..., 106 | cylinders: typing.Optional[typing.Iterable[foxglove.CylinderPrimitive_pb2.CylinderPrimitive]] = ..., 107 | lines: typing.Optional[typing.Iterable[foxglove.LinePrimitive_pb2.LinePrimitive]] = ..., 108 | triangles: typing.Optional[typing.Iterable[foxglove.TriangleListPrimitive_pb2.TriangleListPrimitive]] = ..., 109 | texts: typing.Optional[typing.Iterable[foxglove.TextPrimitive_pb2.TextPrimitive]] = ..., 110 | models: typing.Optional[typing.Iterable[foxglove.ModelPrimitive_pb2.ModelPrimitive]] = ..., 111 | ) -> None: ... 112 | def HasField(self, field_name: typing_extensions.Literal["lifetime",b"lifetime","timestamp",b"timestamp"]) -> builtins.bool: ... 113 | def ClearField(self, field_name: typing_extensions.Literal["arrows",b"arrows","cubes",b"cubes","cylinders",b"cylinders","frame_id",b"frame_id","frame_locked",b"frame_locked","id",b"id","lifetime",b"lifetime","lines",b"lines","metadata",b"metadata","models",b"models","spheres",b"spheres","texts",b"texts","timestamp",b"timestamp","triangles",b"triangles"]) -> None: ... 114 | global___SceneEntity = SceneEntity 115 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "f1d7da676f684ccc6e4784fe0bd55bd6c12b7fe1ebec7934931e08049ad8a4f3" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": {}, 19 | "develop": { 20 | "black": { 21 | "hashes": [ 22 | "sha256:074458dc2f6e0d3dab7928d4417bb6957bb834434516f21514138437accdbe90", 23 | "sha256:187d96c5e713f441a5829e77120c269b6514418f4513a390b0499b0987f2ff1c", 24 | "sha256:2ea29072e954a4d55a2ff58971b83365eba5d3d357352a07a7a4df0d95f51c78", 25 | "sha256:4af5bc0e1f96be5ae9bd7aaec219c901a94d6caa2484c21983d043371c733fc4", 26 | "sha256:560558527e52ce8afba936fcce93a7411ab40c7d5fe8c2463e279e843c0328ee", 27 | "sha256:568ac3c465b1c8b34b61cd7a4e349e93f91abf0f9371eda1cf87194663ab684e", 28 | "sha256:6797f58943fceb1c461fb572edbe828d811e719c24e03375fd25170ada53825e", 29 | "sha256:6c1734ab264b8f7929cef8ae5f900b85d579e6cbfde09d7387da8f04771b51c6", 30 | "sha256:6c6d39e28aed379aec40da1c65434c77d75e65bb59a1e1c283de545fb4e7c6c9", 31 | "sha256:7ba9be198ecca5031cd78745780d65a3f75a34b2ff9be5837045dce55db83d1c", 32 | "sha256:94783f636bca89f11eb5d50437e8e17fbc6a929a628d82304c80fa9cd945f256", 33 | "sha256:a218d7e5856f91d20f04e931b6f16d15356db1c846ee55f01bac297a705ca24f", 34 | "sha256:a3db5b6409b96d9bd543323b23ef32a1a2b06416d525d27e0f67e74f1446c8f2", 35 | "sha256:ac609cf8ef5e7115ddd07d85d988d074ed00e10fbc3445aee393e70164a2219c", 36 | "sha256:b154e6bbde1e79ea3260c4b40c0b7b3109ffcdf7bc4ebf8859169a6af72cd70b", 37 | "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807", 38 | "sha256:b9fd45787ba8aa3f5e0a0a98920c1012c884622c6c920dbe98dbd05bc7c70fbf", 39 | "sha256:c85928b9d5f83b23cee7d0efcb310172412fbf7cb9d9ce963bd67fd141781def", 40 | "sha256:c9a3ac16efe9ec7d7381ddebcc022119794872abce99475345c5a61aa18c45ad", 41 | "sha256:cfaf3895a9634e882bf9d2363fed5af8888802d670f58b279b0bece00e9a872d", 42 | "sha256:e439798f819d49ba1c0bd9664427a05aab79bfba777a6db94fd4e56fae0cb849", 43 | "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69", 44 | "sha256:f6fe02afde060bbeef044af7996f335fbe90b039ccf3f5eb8f16df8b20f77666" 45 | ], 46 | "index": "pypi", 47 | "version": "==22.6.0" 48 | }, 49 | "click": { 50 | "hashes": [ 51 | "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", 52 | "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" 53 | ], 54 | "markers": "python_version >= '3.7'", 55 | "version": "==8.1.3" 56 | }, 57 | "flake8": { 58 | "hashes": [ 59 | "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db", 60 | "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248" 61 | ], 62 | "index": "pypi", 63 | "version": "==5.0.4" 64 | }, 65 | "mccabe": { 66 | "hashes": [ 67 | "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", 68 | "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" 69 | ], 70 | "markers": "python_version >= '3.6'", 71 | "version": "==0.7.0" 72 | }, 73 | "mypy-extensions": { 74 | "hashes": [ 75 | "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", 76 | "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" 77 | ], 78 | "version": "==0.4.3" 79 | }, 80 | "pathspec": { 81 | "hashes": [ 82 | "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a", 83 | "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1" 84 | ], 85 | "version": "==0.9.0" 86 | }, 87 | "platformdirs": { 88 | "hashes": [ 89 | "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788", 90 | "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19" 91 | ], 92 | "markers": "python_version >= '3.7'", 93 | "version": "==2.5.2" 94 | }, 95 | "pycodestyle": { 96 | "hashes": [ 97 | "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785", 98 | "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b" 99 | ], 100 | "markers": "python_version >= '3.6'", 101 | "version": "==2.9.1" 102 | }, 103 | "pyflakes": { 104 | "hashes": [ 105 | "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2", 106 | "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3" 107 | ], 108 | "markers": "python_version >= '3.6'", 109 | "version": "==2.5.0" 110 | }, 111 | "tomli": { 112 | "hashes": [ 113 | "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", 114 | "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" 115 | ], 116 | "markers": "python_full_version < '3.11.0a7'", 117 | "version": "==2.0.1" 118 | }, 119 | "typing-extensions": { 120 | "hashes": [ 121 | "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", 122 | "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6" 123 | ], 124 | "markers": "python_version < '3.10'", 125 | "version": "==4.3.0" 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /turbomap.json: -------------------------------------------------------------------------------- 1 | [[0.18995, 0.07176, 0.23217], [0.19483, 0.08339, 0.26149], [0.19956, 0.09498, 0.29024], [0.20415, 0.10652, 0.31844], [0.20860, 0.11802, 0.34607], [0.21291, 0.12947, 0.37314], [0.21708, 0.14087, 0.39964], [0.22111, 0.15223, 0.42558], [0.22500, 0.16354, 0.45096], [0.22875, 0.17481, 0.47578], [0.23236, 0.18603, 0.50004], [0.23582, 0.19720, 0.52373], [0.23915, 0.20833, 0.54686], [0.24234, 0.21941, 0.56942], [0.24539, 0.23044, 0.59142], [0.24830, 0.24143, 0.61286], [0.25107, 0.25237, 0.63374], [0.25369, 0.26327, 0.65406], [0.25618, 0.27412, 0.67381], [0.25853, 0.28492, 0.69300], [0.26074, 0.29568, 0.71162], [0.26280, 0.30639, 0.72968], [0.26473, 0.31706, 0.74718], [0.26652, 0.32768, 0.76412], [0.26816, 0.33825, 0.78050], [0.26967, 0.34878, 0.79631], [0.27103, 0.35926, 0.81156], [0.27226, 0.36970, 0.82624], [0.27334, 0.38008, 0.84037], [0.27429, 0.39043, 0.85393], [0.27509, 0.40072, 0.86692], [0.27576, 0.41097, 0.87936], [0.27628, 0.42118, 0.89123], [0.27667, 0.43134, 0.90254], [0.27691, 0.44145, 0.91328], [0.27701, 0.45152, 0.92347], [0.27698, 0.46153, 0.93309], [0.27680, 0.47151, 0.94214], [0.27648, 0.48144, 0.95064], [0.27603, 0.49132, 0.95857], [0.27543, 0.50115, 0.96594], [0.27469, 0.51094, 0.97275], [0.27381, 0.52069, 0.97899], [0.27273, 0.53040, 0.98461], [0.27106, 0.54015, 0.98930], [0.26878, 0.54995, 0.99303], [0.26592, 0.55979, 0.99583], [0.26252, 0.56967, 0.99773], [0.25862, 0.57958, 0.99876], [0.25425, 0.58950, 0.99896], [0.24946, 0.59943, 0.99835], [0.24427, 0.60937, 0.99697], [0.23874, 0.61931, 0.99485], [0.23288, 0.62923, 0.99202], [0.22676, 0.63913, 0.98851], [0.22039, 0.64901, 0.98436], [0.21382, 0.65886, 0.97959], [0.20708, 0.66866, 0.97423], [0.20021, 0.67842, 0.96833], [0.19326, 0.68812, 0.96190], [0.18625, 0.69775, 0.95498], [0.17923, 0.70732, 0.94761], [0.17223, 0.71680, 0.93981], [0.16529, 0.72620, 0.93161], [0.15844, 0.73551, 0.92305], [0.15173, 0.74472, 0.91416], [0.14519, 0.75381, 0.90496], [0.13886, 0.76279, 0.89550], [0.13278, 0.77165, 0.88580], [0.12698, 0.78037, 0.87590], [0.12151, 0.78896, 0.86581], [0.11639, 0.79740, 0.85559], [0.11167, 0.80569, 0.84525], [0.10738, 0.81381, 0.83484], [0.10357, 0.82177, 0.82437], [0.10026, 0.82955, 0.81389], [0.09750, 0.83714, 0.80342], [0.09532, 0.84455, 0.79299], [0.09377, 0.85175, 0.78264], [0.09287, 0.85875, 0.77240], [0.09267, 0.86554, 0.76230], [0.09320, 0.87211, 0.75237], [0.09451, 0.87844, 0.74265], [0.09662, 0.88454, 0.73316], [0.09958, 0.89040, 0.72393], [0.10342, 0.89600, 0.71500], [0.10815, 0.90142, 0.70599], [0.11374, 0.90673, 0.69651], [0.12014, 0.91193, 0.68660], [0.12733, 0.91701, 0.67627], [0.13526, 0.92197, 0.66556], [0.14391, 0.92680, 0.65448], [0.15323, 0.93151, 0.64308], [0.16319, 0.93609, 0.63137], [0.17377, 0.94053, 0.61938], [0.18491, 0.94484, 0.60713], [0.19659, 0.94901, 0.59466], [0.20877, 0.95304, 0.58199], [0.22142, 0.95692, 0.56914], [0.23449, 0.96065, 0.55614], [0.24797, 0.96423, 0.54303], [0.26180, 0.96765, 0.52981], [0.27597, 0.97092, 0.51653], [0.29042, 0.97403, 0.50321], [0.30513, 0.97697, 0.48987], [0.32006, 0.97974, 0.47654], [0.33517, 0.98234, 0.46325], [0.35043, 0.98477, 0.45002], [0.36581, 0.98702, 0.43688], [0.38127, 0.98909, 0.42386], [0.39678, 0.99098, 0.41098], [0.41229, 0.99268, 0.39826], [0.42778, 0.99419, 0.38575], [0.44321, 0.99551, 0.37345], [0.45854, 0.99663, 0.36140], [0.47375, 0.99755, 0.34963], [0.48879, 0.99828, 0.33816], [0.50362, 0.99879, 0.32701], [0.51822, 0.99910, 0.31622], [0.53255, 0.99919, 0.30581], [0.54658, 0.99907, 0.29581], [0.56026, 0.99873, 0.28623], [0.57357, 0.99817, 0.27712], [0.58646, 0.99739, 0.26849], [0.59891, 0.99638, 0.26038], [0.61088, 0.99514, 0.25280], [0.62233, 0.99366, 0.24579], [0.63323, 0.99195, 0.23937], [ 2 | 0.64362, 0.98999, 0.23356], [0.65394, 0.98775, 0.22835], [0.66428, 0.98524, 0.22370], [0.67462, 0.98246, 0.21960], [0.68494, 0.97941, 0.21602], [0.69525, 0.97610, 0.21294], [0.70553, 0.97255, 0.21032], [0.71577, 0.96875, 0.20815], [0.72596, 0.96470, 0.20640], [0.73610, 0.96043, 0.20504], [0.74617, 0.95593, 0.20406], [0.75617, 0.95121, 0.20343], [0.76608, 0.94627, 0.20311], [0.77591, 0.94113, 0.20310], [0.78563, 0.93579, 0.20336], [0.79524, 0.93025, 0.20386], [0.80473, 0.92452, 0.20459], [0.81410, 0.91861, 0.20552], [0.82333, 0.91253, 0.20663], [0.83241, 0.90627, 0.20788], [0.84133, 0.89986, 0.20926], [0.85010, 0.89328, 0.21074], [0.85868, 0.88655, 0.21230], [0.86709, 0.87968, 0.21391], [0.87530, 0.87267, 0.21555], [0.88331, 0.86553, 0.21719], [0.89112, 0.85826, 0.21880], [0.89870, 0.85087, 0.22038], [0.90605, 0.84337, 0.22188], [0.91317, 0.83576, 0.22328], [0.92004, 0.82806, 0.22456], [0.92666, 0.82025, 0.22570], [0.93301, 0.81236, 0.22667], [0.93909, 0.80439, 0.22744], [0.94489, 0.79634, 0.22800], [0.95039, 0.78823, 0.22831], [0.95560, 0.78005, 0.22836], [0.96049, 0.77181, 0.22811], [0.96507, 0.76352, 0.22754], [0.96931, 0.75519, 0.22663], [0.97323, 0.74682, 0.22536], [0.97679, 0.73842, 0.22369], [0.98000, 0.73000, 0.22161], [0.98289, 0.72140, 0.21918], [0.98549, 0.71250, 0.21650], [0.98781, 0.70330, 0.21358], [0.98986, 0.69382, 0.21043], [0.99163, 0.68408, 0.20706], [0.99314, 0.67408, 0.20348], [0.99438, 0.66386, 0.19971], [0.99535, 0.65341, 0.19577], [0.99607, 0.64277, 0.19165], [0.99654, 0.63193, 0.18738], [0.99675, 0.62093, 0.18297], [0.99672, 0.60977, 0.17842], [0.99644, 0.59846, 0.17376], [0.99593, 0.58703, 0.16899], [0.99517, 0.57549, 0.16412], [0.99419, 0.56386, 0.15918], [0.99297, 0.55214, 0.15417], [0.99153, 0.54036, 0.14910], [0.98987, 0.52854, 0.14398], [0.98799, 0.51667, 0.13883], [0.98590, 0.50479, 0.13367], [0.98360, 0.49291, 0.12849], [0.98108, 0.48104, 0.12332], [0.97837, 0.46920, 0.11817], [0.97545, 0.45740, 0.11305], [0.97234, 0.44565, 0.10797], [0.96904, 0.43399, 0.10294], [0.96555, 0.42241, 0.09798], [0.96187, 0.41093, 0.09310], [0.95801, 0.39958, 0.08831], [0.95398, 0.38836, 0.08362], [0.94977, 0.37729, 0.07905], [0.94538, 0.36638, 0.07461], [0.94084, 0.35566, 0.07031], [0.93612, 0.34513, 0.06616], [0.93125, 0.33482, 0.06218], [0.92623, 0.32473, 0.05837], [0.92105, 0.31489, 0.05475], [0.91572, 0.30530, 0.05134], [0.91024, 0.29599, 0.04814], [0.90463, 0.28696, 0.04516], [0.89888, 0.27824, 0.04243], [0.89298, 0.26981, 0.03993], [0.88691, 0.26152, 0.03753], [0.88066, 0.25334, 0.03521], [0.87422, 0.24526, 0.03297], [0.86760, 0.23730, 0.03082], [0.86079, 0.22945, 0.02875], [0.85380, 0.22170, 0.02677], [0.84662, 0.21407, 0.02487], [0.83926, 0.20654, 0.02305], [0.83172, 0.19912, 0.02131], [0.82399, 0.19182, 0.01966], [0.81608, 0.18462, 0.01809], [0.80799, 0.17753, 0.01660], [0.79971, 0.17055, 0.01520], [0.79125, 0.16368, 0.01387], [0.78260, 0.15693, 0.01264], [0.77377, 0.15028, 0.01148], [0.76476, 0.14374, 0.01041], [0.75556, 0.13731, 0.00942], [0.74617, 0.13098, 0.00851], [0.73661, 0.12477, 0.00769], [0.72686, 0.11867, 0.00695], [0.71692, 0.11268, 0.00629], [0.70680, 0.10680, 0.00571], [0.69650, 0.10102, 0.00522], [0.68602, 0.09536, 0.00481], [0.67535, 0.08980, 0.00449], [0.66449, 0.08436, 0.00424], [0.65345, 0.07902, 0.00408], [0.64223, 0.07380, 0.00401], [0.63082, 0.06868, 0.00401], [0.61923, 0.06367, 0.00410], [0.60746, 0.05878, 0.00427], [0.59550, 0.05399, 0.00453], [0.58336, 0.04931, 0.00486], [0.57103, 0.04474, 0.00529], [0.55852, 0.04028, 0.00579], [0.54583, 0.03593, 0.00638], [0.53295, 0.03169, 0.00705], [0.51989, 0.02756, 0.00780], [0.50664, 0.02354, 0.00863], [0.49321, 0.01963, 0.00955], [0.47960, 0.01583, 0.01055]] 3 | -------------------------------------------------------------------------------- /nuscenes2bag/map_utils.py: -------------------------------------------------------------------------------- 1 | from utils import * 2 | 3 | EARTH_RADIUS_METERS = 6.378137e6 4 | REFERENCE_COORDINATES = { 5 | "boston-seaport": [42.336849169438615, -71.05785369873047], 6 | "singapore-onenorth": [1.2882100868743724, 103.78475189208984], 7 | "singapore-hollandvillage": [1.2993652317780957, 103.78217697143555], 8 | "singapore-queenstown": [1.2782562240223188, 103.76741409301758], 9 | } 10 | 11 | def get_pose_stamped(stamp): 12 | msg = PoseStamped() 13 | msg.header.frame_id = 'base_link' 14 | msg.header.stamp = stamp 15 | msg.pose.orientation.w = 1.0 16 | return msg 17 | 18 | def get_coordinate(ref_lat, ref_lon, bearing, dist): 19 | """ 20 | Using a reference coordinate, extract the coordinates of another point in space given its distance and bearing 21 | to the reference coordinate. For reference, please see: https://www.movable-type.co.uk/scripts/latlong.html. 22 | :param ref_lat: Latitude of the reference coordinate in degrees, ie: 42.3368. 23 | :param ref_lon: Longitude of the reference coordinate in degrees, ie: 71.0578. 24 | :param bearing: The clockwise angle in radians between target point, reference point and the axis pointing north. 25 | :param dist: The distance in meters from the reference point to the target point. 26 | :return: A tuple of lat and lon. 27 | """ 28 | lat, lon = math.radians(ref_lat), math.radians(ref_lon) 29 | angular_distance = dist / EARTH_RADIUS_METERS 30 | 31 | target_lat = math.asin(math.sin(lat) * math.cos(angular_distance) + math.cos(lat) * math.sin(angular_distance) * math.cos(bearing)) 32 | target_lon = lon + math.atan2( 33 | math.sin(bearing) * math.sin(angular_distance) * math.cos(lat), 34 | math.cos(angular_distance) - math.sin(lat) * math.sin(target_lat), 35 | ) 36 | return math.degrees(target_lat), math.degrees(target_lon) 37 | 38 | 39 | def derive_latlon(location, pose): 40 | """ 41 | For each pose value, extract its respective lat/lon coordinate and timestamp. 42 | 43 | This makes the following two assumptions in order to work: 44 | 1. The reference coordinate for each map is in the south-western corner. 45 | 2. The origin of the global poses is also in the south-western corner (and identical to 1). 46 | :param location: The name of the map the poses correspond to, ie: 'boston-seaport'. 47 | :param poses: All nuScenes egopose dictionaries of a scene. 48 | :return: A list of dicts (lat/lon coordinates and timestamps) for each pose. 49 | """ 50 | assert location in REFERENCE_COORDINATES.keys(), f"Error: The given location: {location}, has no available reference." 51 | 52 | reference_lat, reference_lon = REFERENCE_COORDINATES[location] 53 | x, y = pose["translation"][:2] 54 | bearing = math.atan(x / y) 55 | distance = math.sqrt(x**2 + y**2) 56 | lat, lon = get_coordinate(reference_lat, reference_lon, bearing, distance) 57 | return lat, lon 58 | 59 | def get_transform(data): 60 | t = Transform() 61 | t.translation.x = data['translation'][0] 62 | t.translation.y = data['translation'][1] 63 | t.translation.z = data['translation'][2] 64 | 65 | t.rotation.w = data['rotation'][0] 66 | t.rotation.x = data['rotation'][1] 67 | t.rotation.y = data['rotation'][2] 68 | t.rotation.z = data['rotation'][3] 69 | 70 | return t 71 | 72 | def get_gps(location, ego_pose, stamp): 73 | gps = NavSatFix() 74 | gps.header.frame_id = 'base_link' 75 | gps.header.stamp = stamp 76 | gps.status.status = 1 77 | gps.status.service = 1 78 | lat, lon = derive_latlon(location, ego_pose) 79 | gps.latitude = lat 80 | gps.longitude = lon 81 | gps.altitude = get_transform(ego_pose).translation.z 82 | return gps 83 | 84 | def write_occupancy_grid(bag, nusc_map, ego_pose, stamp): 85 | translation = ego_pose['translation'] 86 | rotation = Quaternion(ego_pose['rotation']) 87 | yaw = quaternion_yaw(rotation) / np.pi * 180 88 | patch_box = (translation[0], translation[1], 32, 32) 89 | canvas_size = (patch_box[2] * 10, patch_box[3] * 10) 90 | 91 | drivable_area = nusc_map.get_map_mask(patch_box, yaw, ['drivable_area'], canvas_size)[0] 92 | drivable_area = (drivable_area * 100).astype(np.int8) 93 | 94 | msg = OccupancyGrid() 95 | msg.header.frame_id = 'base_link' 96 | msg.header.stamp = stamp 97 | msg.info.map_load_time = stamp 98 | msg.info.resolution = 0.1 99 | msg.info.width = drivable_area.shape[1] 100 | msg.info.height = drivable_area.shape[0] 101 | msg.info.origin.position.x = -16.0 102 | msg.info.origin.position.y = -16.0 103 | msg.info.origin.orientation.w = 1.0 104 | msg.data = drivable_area.flatten().tolist() 105 | 106 | bag.write('/drivable_area', serialize_message(msg), to_nano(stamp)) 107 | 108 | def load_bitmap(dataroot: str, map_name: str, layer_name: str) -> np.ndarray: 109 | """render bitmap map layers. Currently these are: 110 | - semantic_prior: The semantic prior (driveable surface and sidewalks) mask from nuScenes 1.0. 111 | - basemap: The HD lidar basemap used for localization and as general context. 112 | 113 | :param dataroot: Path of the nuScenes dataset. 114 | :param map_name: Which map out of `singapore-onenorth`, `singepore-hollandvillage`, `singapore-queenstown` and 115 | 'boston-seaport'. 116 | :param layer_name: The type of bitmap map, `semanitc_prior` or `basemap. 117 | """ 118 | # Load bitmap. 119 | if layer_name == "basemap": 120 | map_path = os.path.join(dataroot, "maps", "basemap", map_name + ".png") 121 | elif layer_name == "semantic_prior": 122 | map_hashes = { 123 | "singapore-onenorth": "53992ee3023e5494b90c316c183be829", 124 | "singapore-hollandvillage": "37819e65e09e5547b8a3ceaefba56bb2", 125 | "singapore-queenstown": "93406b464a165eaba6d9de76ca09f5da", 126 | "boston-seaport": "36092f0b03a857c6a3403e25b4b7aab3", 127 | } 128 | map_hash = map_hashes[map_name] 129 | map_path = os.path.join(dataroot, "maps", map_hash + ".png") 130 | else: 131 | raise Exception("Error: Invalid bitmap layer: %s" % layer_name) 132 | 133 | # Convert to numpy. 134 | if os.path.exists(map_path): 135 | image = np.array(Image.open(map_path).convert("L")) 136 | else: 137 | raise Exception("Error: Cannot find %s %s! Please make sure that the map is correctly installed." % (layer_name, map_path)) 138 | 139 | # Invert semantic prior colors. 140 | if layer_name == "semantic_prior": 141 | image = image.max() - image 142 | 143 | return image 144 | 145 | def scene_bounding_box(nusc, scene, nusc_map, padding=75.0): 146 | box = [np.inf, np.inf, -np.inf, -np.inf] 147 | cur_sample = nusc.get('sample', scene['first_sample_token']) 148 | while cur_sample is not None: 149 | sample_lidar = nusc.get('sample_data', cur_sample['data']['LIDAR_TOP']) 150 | ego_pose = nusc.get('ego_pose', sample_lidar['ego_pose_token']) 151 | x, y = ego_pose['translation'][:2] 152 | box[0] = min(box[0], x) 153 | box[1] = min(box[1], y) 154 | box[2] = max(box[2], x) 155 | box[3] = max(box[3], y) 156 | cur_sample = nusc.get('sample', cur_sample['next']) if cur_sample.get('next') != '' else None 157 | box[0] = max(box[0] - padding, 0.0) 158 | box[1] = max(box[1] - padding, 0.0) 159 | box[2] = min(box[2] + padding, nusc_map.canvas_edge[0]) - box[0] 160 | box[3] = min(box[3] + padding, nusc_map.canvas_edge[1]) - box[1] 161 | return box 162 | 163 | def get_scene_map(nusc, scene, nusc_map, image, stamp): 164 | x, y, w, h = scene_bounding_box(nusc, scene, nusc_map) 165 | img_x = int(x * 10) 166 | img_y = int(y * 10) 167 | img_w = int(w * 10) 168 | img_h = int(h * 10) 169 | img = np.flipud(image)[img_y:img_y+img_h, img_x:img_x+img_w] 170 | img = (img * (100.0 / 255.0)).astype(np.int8) 171 | 172 | msg = OccupancyGrid() 173 | msg.header.frame_id = 'map' 174 | msg.header.stamp = stamp 175 | msg.info.map_load_time = stamp 176 | msg.info.resolution = 0.1 177 | msg.info.width = img_w 178 | msg.info.height = img_h 179 | msg.info.origin.position.x = x 180 | msg.info.origin.position.y = y 181 | msg.info.origin.orientation.w = 1.0 182 | msg.data = img.flatten().tolist() 183 | 184 | return msg 185 | 186 | def get_centerline_markers(nusc, scene, nusc_map, stamp): 187 | pose_lists = nusc_map.discretize_centerlines(1) 188 | bbox = scene_bounding_box(nusc, scene, nusc_map) 189 | 190 | contained_pose_lists = [] 191 | for pose_list in pose_lists: 192 | new_pose_list = [] 193 | for pose in pose_list: 194 | if rectContains(bbox, pose): 195 | new_pose_list.append(pose) 196 | if len(new_pose_list) > 0: 197 | contained_pose_lists.append(new_pose_list) 198 | 199 | msg = MarkerArray() 200 | for i, pose_list in enumerate(contained_pose_lists): 201 | marker = Marker() 202 | marker.header.frame_id = 'map' 203 | marker.header.stamp = stamp 204 | marker.ns = 'centerline' 205 | marker.id = i 206 | marker.type = Marker.LINE_STRIP 207 | marker.action = Marker.ADD 208 | marker.frame_locked = True 209 | marker.scale.x = 0.1 210 | marker.color.r = 51.0 / 255.0 211 | marker.color.g = 160.0 / 255.0 212 | marker.color.b = 44.0 / 255.0 213 | marker.color.a = 1.0 214 | marker.pose.orientation.w = 1.0 215 | for pose in pose_list: 216 | p = Point() 217 | p.x = pose[0] 218 | p.y = pose[1] 219 | p.z = 0.0 220 | marker.points.append(p) 221 | msg.markers.append(marker) 222 | 223 | return msg --------------------------------------------------------------------------------