diff --git a/ros_foxglove_msgs/ros1/CameraCalibration.msg b/ros_foxglove_msgs/ros1/CameraCalibration.msg index eed8d50..fad3d78 100644 --- a/ros_foxglove_msgs/ros1/CameraCalibration.msg +++ b/ros_foxglove_msgs/ros1/CameraCalibration.msg @@ -6,6 +6,9 @@ # Timestamp of calibration data time timestamp +# 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. +string frame_id + # Image width uint32 width diff --git a/ros_foxglove_msgs/ros1/CompressedImage.msg b/ros_foxglove_msgs/ros1/CompressedImage.msg index f19cc78..f049b77 100644 --- a/ros_foxglove_msgs/ros1/CompressedImage.msg +++ b/ros_foxglove_msgs/ros1/CompressedImage.msg @@ -6,6 +6,9 @@ # Timestamp of image time timestamp +# 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. +string frame_id + # Compressed image data uint8[] data diff --git a/ros_foxglove_msgs/ros1/RawImage.msg b/ros_foxglove_msgs/ros1/RawImage.msg index 7a85e17..64b86ae 100644 --- a/ros_foxglove_msgs/ros1/RawImage.msg +++ b/ros_foxglove_msgs/ros1/RawImage.msg @@ -6,6 +6,9 @@ # Timestamp of image time timestamp +# 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. +string frame_id + # Image width uint32 width diff --git a/ros_foxglove_msgs/ros2/CameraCalibration.msg b/ros_foxglove_msgs/ros2/CameraCalibration.msg index 38894b5..8dabdf1 100644 --- a/ros_foxglove_msgs/ros2/CameraCalibration.msg +++ b/ros_foxglove_msgs/ros2/CameraCalibration.msg @@ -6,6 +6,9 @@ # Timestamp of calibration data builtin_interfaces/Time timestamp +# 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. +string frame_id + # Image width uint32 width diff --git a/ros_foxglove_msgs/ros2/CompressedImage.msg b/ros_foxglove_msgs/ros2/CompressedImage.msg index 8c0a6f1..afba021 100644 --- a/ros_foxglove_msgs/ros2/CompressedImage.msg +++ b/ros_foxglove_msgs/ros2/CompressedImage.msg @@ -6,6 +6,9 @@ # Timestamp of image builtin_interfaces/Time timestamp +# 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. +string frame_id + # Compressed image data uint8[] data diff --git a/ros_foxglove_msgs/ros2/RawImage.msg b/ros_foxglove_msgs/ros2/RawImage.msg index dd0343a..f6310c1 100644 --- a/ros_foxglove_msgs/ros2/RawImage.msg +++ b/ros_foxglove_msgs/ros2/RawImage.msg @@ -6,6 +6,9 @@ # Timestamp of image builtin_interfaces/Time timestamp +# 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. +string frame_id + # Image width uint32 width diff --git a/schemas/README.md b/schemas/README.md index 13ad6d9..a15be44 100644 --- a/schemas/README.md +++ b/schemas/README.md @@ -244,6 +244,19 @@ time Timestamp of calibration data + + + +frame_id + + +string + + + + +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. + @@ -552,6 +565,19 @@ time Timestamp of image + + + +frame_id + + +string + + + + +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. + @@ -2066,6 +2092,19 @@ time Timestamp of image + + + +frame_id + + +string + + + + +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. + diff --git a/schemas/jsonschema/CameraCalibration.json b/schemas/jsonschema/CameraCalibration.json index 2f52f77..ebef038 100644 --- a/schemas/jsonschema/CameraCalibration.json +++ b/schemas/jsonschema/CameraCalibration.json @@ -20,6 +20,10 @@ }, "description": "Timestamp of calibration data" }, + "frame_id": { + "type": "string", + "description": "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." + }, "width": { "type": "integer", "minimum": 0, diff --git a/schemas/jsonschema/CompressedImage.json b/schemas/jsonschema/CompressedImage.json index 09c6a69..cffb874 100644 --- a/schemas/jsonschema/CompressedImage.json +++ b/schemas/jsonschema/CompressedImage.json @@ -20,6 +20,10 @@ }, "description": "Timestamp of image" }, + "frame_id": { + "type": "string", + "description": "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." + }, "data": { "type": "string", "contentEncoding": "base64", diff --git a/schemas/jsonschema/RawImage.json b/schemas/jsonschema/RawImage.json index f2eab54..03ea61a 100644 --- a/schemas/jsonschema/RawImage.json +++ b/schemas/jsonschema/RawImage.json @@ -20,6 +20,10 @@ }, "description": "Timestamp of image" }, + "frame_id": { + "type": "string", + "description": "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." + }, "width": { "type": "integer", "minimum": 0, diff --git a/schemas/proto/foxglove/CameraCalibration.proto b/schemas/proto/foxglove/CameraCalibration.proto index bbfdfc8..d257f17 100644 --- a/schemas/proto/foxglove/CameraCalibration.proto +++ b/schemas/proto/foxglove/CameraCalibration.proto @@ -11,6 +11,9 @@ message CameraCalibration { // Timestamp of calibration data google.protobuf.Timestamp timestamp = 1; + // 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. + string frame_id = 9; + // Image width fixed32 width = 2; diff --git a/schemas/proto/foxglove/CompressedImage.proto b/schemas/proto/foxglove/CompressedImage.proto index 10e533b..a30296e 100644 --- a/schemas/proto/foxglove/CompressedImage.proto +++ b/schemas/proto/foxglove/CompressedImage.proto @@ -11,6 +11,9 @@ message CompressedImage { // Timestamp of image google.protobuf.Timestamp timestamp = 1; + // 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. + string frame_id = 4; + // Compressed image data bytes data = 2; diff --git a/schemas/proto/foxglove/RawImage.proto b/schemas/proto/foxglove/RawImage.proto index 275d442..40f4b89 100644 --- a/schemas/proto/foxglove/RawImage.proto +++ b/schemas/proto/foxglove/RawImage.proto @@ -11,6 +11,9 @@ message RawImage { // Timestamp of image google.protobuf.Timestamp timestamp = 1; + // 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. + string frame_id = 7; + // Image width fixed32 width = 2; diff --git a/schemas/ros1/CameraCalibration.msg b/schemas/ros1/CameraCalibration.msg index eed8d50..fad3d78 100644 --- a/schemas/ros1/CameraCalibration.msg +++ b/schemas/ros1/CameraCalibration.msg @@ -6,6 +6,9 @@ # Timestamp of calibration data time timestamp +# 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. +string frame_id + # Image width uint32 width diff --git a/schemas/ros1/CompressedImage.msg b/schemas/ros1/CompressedImage.msg index f19cc78..f049b77 100644 --- a/schemas/ros1/CompressedImage.msg +++ b/schemas/ros1/CompressedImage.msg @@ -6,6 +6,9 @@ # Timestamp of image time timestamp +# 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. +string frame_id + # Compressed image data uint8[] data diff --git a/schemas/ros1/RawImage.msg b/schemas/ros1/RawImage.msg index 7a85e17..64b86ae 100644 --- a/schemas/ros1/RawImage.msg +++ b/schemas/ros1/RawImage.msg @@ -6,6 +6,9 @@ # Timestamp of image time timestamp +# 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. +string frame_id + # Image width uint32 width diff --git a/schemas/ros2/CameraCalibration.msg b/schemas/ros2/CameraCalibration.msg index 38894b5..8dabdf1 100644 --- a/schemas/ros2/CameraCalibration.msg +++ b/schemas/ros2/CameraCalibration.msg @@ -6,6 +6,9 @@ # Timestamp of calibration data builtin_interfaces/Time timestamp +# 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. +string frame_id + # Image width uint32 width diff --git a/schemas/ros2/CompressedImage.msg b/schemas/ros2/CompressedImage.msg index 8c0a6f1..afba021 100644 --- a/schemas/ros2/CompressedImage.msg +++ b/schemas/ros2/CompressedImage.msg @@ -6,6 +6,9 @@ # Timestamp of image builtin_interfaces/Time timestamp +# 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. +string frame_id + # Compressed image data uint8[] data diff --git a/schemas/ros2/RawImage.msg b/schemas/ros2/RawImage.msg index dd0343a..f6310c1 100644 --- a/schemas/ros2/RawImage.msg +++ b/schemas/ros2/RawImage.msg @@ -6,6 +6,9 @@ # Timestamp of image builtin_interfaces/Time timestamp +# 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. +string frame_id + # Image width uint32 width diff --git a/schemas/typescript/CameraCalibration.ts b/schemas/typescript/CameraCalibration.ts index 519c11c..d70509d 100644 --- a/schemas/typescript/CameraCalibration.ts +++ b/schemas/typescript/CameraCalibration.ts @@ -7,6 +7,9 @@ export type CameraCalibration = { /** Timestamp of calibration data */ timestamp: Time; + /** 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. */ + frame_id: string; + /** Image width */ width: number; diff --git a/schemas/typescript/CompressedImage.ts b/schemas/typescript/CompressedImage.ts index f23d91b..cf3084b 100644 --- a/schemas/typescript/CompressedImage.ts +++ b/schemas/typescript/CompressedImage.ts @@ -7,6 +7,9 @@ export type CompressedImage = { /** Timestamp of image */ timestamp: Time; + /** 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. */ + frame_id: string; + /** Compressed image data */ data: Uint8Array; diff --git a/schemas/typescript/RawImage.ts b/schemas/typescript/RawImage.ts index e50350a..690fcce 100644 --- a/schemas/typescript/RawImage.ts +++ b/schemas/typescript/RawImage.ts @@ -7,6 +7,9 @@ export type RawImage = { /** Timestamp of image */ timestamp: Time; + /** 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. */ + frame_id: string; + /** Image width */ width: number; diff --git a/src/generateProto.test.ts b/src/generateProto.test.ts index 58fbc4e..99b7b78 100644 --- a/src/generateProto.test.ts +++ b/src/generateProto.test.ts @@ -37,67 +37,67 @@ describe("generateProto", () => { bool field_boolean = 3; // bytes field - bytes field_bytes = 4; + bytes field_bytes = 5; // float64 field - double field_float64 = 5; + double field_float64 = 6; // uint32 field - fixed32 field_uint32 = 6; + fixed32 field_uint32 = 7; // string field - string field_string = 7; + string field_string = 8; // duration array field - repeated google.protobuf.Duration field_duration_array = 8; + repeated google.protobuf.Duration field_duration_array = 9; // time array field - repeated google.protobuf.Timestamp field_time_array = 9; + repeated google.protobuf.Timestamp field_time_array = 10; // boolean array field - repeated bool field_boolean_array = 10; + repeated bool field_boolean_array = 11; // bytes array field - repeated bytes field_bytes_array = 11; + repeated bytes field_bytes_array = 12; // float64 array field - repeated double field_float64_array = 12; + repeated double field_float64_array = 13; // uint32 array field - repeated fixed32 field_uint32_array = 13; + repeated fixed32 field_uint32_array = 14; // string array field - repeated string field_string_array = 14; + repeated string field_string_array = 15; // duration fixed-length array field - repeated google.protobuf.Duration field_duration_fixed_array = 15; // length 3 + repeated google.protobuf.Duration field_duration_fixed_array = 16; // length 3 // time fixed-length array field - repeated google.protobuf.Timestamp field_time_fixed_array = 16; // length 3 + repeated google.protobuf.Timestamp field_time_fixed_array = 17; // length 3 // boolean fixed-length array field - repeated bool field_boolean_fixed_array = 17; // length 3 + repeated bool field_boolean_fixed_array = 18; // length 3 // bytes fixed-length array field - repeated bytes field_bytes_fixed_array = 18; // length 3 + repeated bytes field_bytes_fixed_array = 19; // length 3 // float64 fixed-length array field - repeated double field_float64_fixed_array = 19; // length 3 + repeated double field_float64_fixed_array = 20; // length 3 // uint32 fixed-length array field - repeated fixed32 field_uint32_fixed_array = 20; // length 3 + repeated fixed32 field_uint32_fixed_array = 21; // length 3 // string fixed-length array field - repeated string field_string_fixed_array = 21; // length 3 + repeated string field_string_fixed_array = 22; // length 3 // An enum field - ExampleProtoEnum field_enum = 22; + ExampleProtoEnum field_enum = 23; // An enum array field - repeated ExampleProtoEnum field_enum_array = 23; + repeated ExampleProtoEnum field_enum_array = 24; // A nested field - foxglove.NestedMessage field_nested = 24; + foxglove.NestedMessage field_nested = 25; // A nested array field // With @@ -105,7 +105,7 @@ describe("generateProto", () => { // very // long // description - repeated foxglove.NestedMessage field_nested_array = 25; + repeated foxglove.NestedMessage field_nested_array = 4; } " `); diff --git a/src/generateProto.ts b/src/generateProto.ts index cf09810..5cf6680 100644 --- a/src/generateProto.ts +++ b/src/generateProto.ts @@ -1,4 +1,9 @@ -import { FoxgloveEnumSchema, FoxgloveMessageSchema, FoxglovePrimitive } from "./types"; +import { + FoxgloveEnumSchema, + FoxgloveMessageField, + FoxgloveMessageSchema, + FoxglovePrimitive, +} from "./types"; function primitiveToProto(type: Exclude) { switch (type) { @@ -35,9 +40,33 @@ export function generateProto( ); } - let fieldNumber = 1; + const explicitFieldNumbers = new Set(); + for (const field of schema.fields) { + if (field.protobufFieldNumber != undefined) { + if (explicitFieldNumbers.has(field.protobufFieldNumber)) { + throw new Error( + `More than one field with protobufFieldNumber ${field.protobufFieldNumber}`, + ); + } + explicitFieldNumbers.add(field.protobufFieldNumber); + } + } + + let nextFieldNumber = 1; + const numberedFields = schema.fields.map( + (field): FoxgloveMessageField & { protobufFieldNumber: number } => { + if (field.protobufFieldNumber != undefined) { + return { ...field, protobufFieldNumber: field.protobufFieldNumber }; + } + while (explicitFieldNumbers.has(nextFieldNumber)) { + ++nextFieldNumber; + } + return { ...field, protobufFieldNumber: nextFieldNumber++ }; + }, + ); + const imports = new Set(); - const fields = schema.fields.map((field) => { + const fields = numberedFields.map((field) => { const lineComments: string[] = []; const qualifiers: string[] = []; if (field.array != undefined) { @@ -70,7 +99,7 @@ export function generateProto( .trim() .split("\n") .map((line) => ` // ${line}\n`) - .join("")} ${qualifiers.join(" ")} ${field.name} = ${fieldNumber++};${ + .join("")} ${qualifiers.join(" ")} ${field.name} = ${field.protobufFieldNumber};${ lineComments.length > 0 ? " // " + lineComments.join(", ") : "" }`; }); diff --git a/src/schemas.ts b/src/schemas.ts index 0863c2d..ea9cdbc 100644 --- a/src/schemas.ts +++ b/src/schemas.ts @@ -664,6 +664,13 @@ const CameraCalibration: FoxgloveMessageSchema = { type: { type: "primitive", name: "time" }, description: "Timestamp of calibration data", }, + { + name: "frame_id", + type: { type: "primitive", name: "string" }, + description: + "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.", + protobufFieldNumber: 9, + }, { name: "width", type: { type: "primitive", name: "uint32" }, @@ -754,6 +761,13 @@ const CompressedImage: FoxgloveMessageSchema = { type: { type: "primitive", name: "time" }, description: "Timestamp of image", }, + { + name: "frame_id", + type: { type: "primitive", name: "string" }, + description: + "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.", + protobufFieldNumber: 4, + }, { name: "data", type: { type: "primitive", name: "bytes" }, @@ -777,6 +791,13 @@ const RawImage: FoxgloveMessageSchema = { type: { type: "primitive", name: "time" }, description: "Timestamp of image", }, + { + name: "frame_id", + type: { type: "primitive", name: "string" }, + description: + "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.", + protobufFieldNumber: 7, + }, { name: "width", type: { type: "primitive", name: "uint32" }, diff --git a/src/testFixtures.ts b/src/testFixtures.ts index fc96998..62de11d 100644 --- a/src/testFixtures.ts +++ b/src/testFixtures.ts @@ -78,6 +78,7 @@ export const exampleMessage: FoxgloveMessageSchema = { description: "A nested array field\nWith\na\nvery\nlong\ndescription", type: { type: "nested", schema: exampleNestedMessage }, array: true, + protobufFieldNumber: 4, }, ], }; diff --git a/src/types.ts b/src/types.ts index aa35d4d..5f9973c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -20,21 +20,24 @@ export type FoxgloveEnumSchema = { }>; }; +export type FoxgloveMessageField = { + name: string; + type: + | { type: "primitive"; name: FoxglovePrimitive } + | { type: "nested"; schema: FoxgloveMessageSchema } + | { type: "enum"; enum: FoxgloveEnumSchema }; + array?: true | number; + required?: true; + description: string; + protobufFieldNumber?: number; +}; + export type FoxgloveMessageSchema = { type: "message"; name: string; description: string; rosEquivalent?: keyof typeof import("@foxglove/rosmsg-msgs-common").definitions; - fields: ReadonlyArray<{ - name: string; - type: - | { type: "primitive"; name: FoxglovePrimitive } - | { type: "nested"; schema: FoxgloveMessageSchema } - | { type: "enum"; enum: FoxgloveEnumSchema }; - array?: true | number; - required?: true; - description: string; - }>; + fields: ReadonlyArray; }; export type FoxgloveSchema = FoxgloveMessageSchema | FoxgloveEnumSchema;