diff --git a/c/cbindgen.toml b/c/cbindgen.toml index facb0c29a..107df120f 100644 --- a/c/cbindgen.toml +++ b/c/cbindgen.toml @@ -121,4 +121,5 @@ FoxgloveLogLevel = "foxglove_log_level" FoxgloveSceneEntityDeletionType = "foxglove_scene_entity_deletion_type" FoxgloveNumericType = "foxglove_numeric_type" FoxglovePointsAnnotationType = "foxglove_points_annotation_type" +FoxglovePointStyle = "foxglove_point_style" FoxglovePositionCovarianceType = "foxglove_position_covariance_type" \ No newline at end of file diff --git a/c/include/foxglove-c/foxglove-c.h b/c/include/foxglove-c/foxglove-c.h index 78e95dcc8..72d45c5a8 100644 --- a/c/include/foxglove-c/foxglove-c.h +++ b/c/include/foxglove-c/foxglove-c.h @@ -280,6 +280,22 @@ typedef uint8_t foxglove_parameter_value_tag; #endif // __cplusplus #endif +enum foxglove_point_style +#ifdef __cplusplus + : int32_t +#endif // __cplusplus + { + FOXGLOVE_POINT_STYLE_DOT = 0, + FOXGLOVE_POINT_STYLE_DIAMOND = 1, + FOXGLOVE_POINT_STYLE_SQUARE = 2, + FOXGLOVE_POINT_STYLE_PLUS = 3, + FOXGLOVE_POINT_STYLE_CROSS = 4, + FOXGLOVE_POINT_STYLE_PIN = 5, +}; +#ifndef __cplusplus +typedef int32_t foxglove_point_style; +#endif // __cplusplus + enum foxglove_points_annotation_type #ifdef __cplusplus : int32_t @@ -1245,6 +1261,10 @@ typedef struct foxglove_location_fix { * Color used to visualize the location */ const struct foxglove_color *color; + /** + * Style of the point used to visualize the location on the map + */ + const foxglove_point_style *point_style; } foxglove_location_fix; /** diff --git a/c/src/generated_types.rs b/c/src/generated_types.rs index 4fceacd77..9ac34115d 100644 --- a/c/src/generated_types.rs +++ b/c/src/generated_types.rs @@ -65,6 +65,17 @@ pub enum FoxglovePointsAnnotationType { LineList = 4, } +#[derive(Clone, Copy, Debug)] +#[repr(i32)] +pub enum FoxglovePointStyle { + Dot = 0, + Diamond = 1, + Square = 2, + Plus = 3, + Cross = 4, + Pin = 5, +} + #[derive(Clone, Copy, Debug)] #[repr(i32)] pub enum FoxglovePositionCovarianceType { @@ -3225,6 +3236,9 @@ pub struct LocationFix { /// Color used to visualize the location pub color: *const Color, + + /// Style of the point used to visualize the location on the map + pub point_style: *const FoxglovePointStyle, } #[cfg(not(target_family = "wasm"))] @@ -3286,6 +3300,7 @@ impl BorrowToNative for LocationFix { }), position_covariance_type: self.position_covariance_type as i32, color: color.map(ManuallyDrop::into_inner), + point_style: unsafe { self.point_style.as_ref() }.map(|&v| v as i32), })) } } diff --git a/cpp/foxglove/include/foxglove/schemas.hpp b/cpp/foxglove/include/foxglove/schemas.hpp index 5d2d8ea10..76865711d 100644 --- a/cpp/foxglove/include/foxglove/schemas.hpp +++ b/cpp/foxglove/include/foxglove/schemas.hpp @@ -1187,6 +1187,21 @@ struct LinePrimitive { /// @brief A navigation satellite fix for any Global Navigation Satellite System struct LocationFix { + /// @brief Style of point used for map visualization + enum class PointStyle : uint8_t { + /// @brief Dot marker + DOT = 0, + /// @brief Diamond-shaped marker + DIAMOND = 1, + /// @brief Square marker + SQUARE = 2, + /// @brief Plus-shaped marker (+) + PLUS = 3, + /// @brief Cross-shaped marker (x) + CROSS = 4, + /// @brief Pin marker + PIN = 5, + }; /// @brief Type of position covariance enum class PositionCovarianceType : uint8_t { /// @brief Unknown position covariance type @@ -1224,6 +1239,9 @@ struct LocationFix { /// @brief Color used to visualize the location std::optional color; + /// @brief Style of the point used to visualize the location on the map + std::optional point_style; + /// @brief Encoded the LocationFix as protobuf to the provided buffer. /// /// On success, writes the serialized length to *encoded_len. diff --git a/cpp/foxglove/src/schemas.cpp b/cpp/foxglove/src/schemas.cpp index 91d1b1ac7..6a5f4e997 100644 --- a/cpp/foxglove/src/schemas.cpp +++ b/cpp/foxglove/src/schemas.cpp @@ -1758,6 +1758,13 @@ void locationFixToC( dest.position_covariance_type = static_cast(src.position_covariance_type); dest.color = src.color ? reinterpret_cast(&*src.color) : nullptr; + if (src.point_style) { + auto* ptr = arena.alloc(1); + *ptr = static_cast(*src.point_style); + dest.point_style = ptr; + } else { + dest.point_style = nullptr; + } } void locationFixesToC( diff --git a/python/foxglove-sdk/python/foxglove/_foxglove_py/schemas.pyi b/python/foxglove-sdk/python/foxglove/_foxglove_py/schemas.pyi index 3ea643612..12835841c 100644 --- a/python/foxglove-sdk/python/foxglove/_foxglove_py/schemas.pyi +++ b/python/foxglove-sdk/python/foxglove/_foxglove_py/schemas.pyi @@ -19,6 +19,18 @@ class LinePrimitiveLineType(Enum): LineLoop = 1 LineList = 2 +class LocationFixPointStyle(Enum): + """ + Style of point used for map visualization + """ + + Dot = 0 + Diamond = 1 + Square = 2 + Plus = 3 + Cross = 4 + Pin = 5 + class LocationFixPositionCovarianceType(Enum): """ Type of position covariance @@ -448,6 +460,7 @@ class LocationFix: position_covariance: list[float] | None = None, position_covariance_type: LocationFixPositionCovarianceType = LocationFixPositionCovarianceType.Unknown, color: Color | None = None, + point_style: LocationFixPointStyle | None = None, ) -> None: ... @staticmethod def get_schema() -> Schema: diff --git a/python/foxglove-sdk/python/foxglove/schemas/__init__.py b/python/foxglove-sdk/python/foxglove/schemas/__init__.py index ba3790f6c..fad6edeed 100644 --- a/python/foxglove-sdk/python/foxglove/schemas/__init__.py +++ b/python/foxglove-sdk/python/foxglove/schemas/__init__.py @@ -32,6 +32,7 @@ LinePrimitiveLineType, LocationFix, LocationFixes, + LocationFixPointStyle, LocationFixPositionCovarianceType, Log, LogLevel, @@ -132,6 +133,7 @@ "LinePrimitive", "LinePrimitiveLineType", "LocationFix", + "LocationFixPointStyle", "LocationFixPositionCovarianceType", "LocationFixes", "Log", diff --git a/python/foxglove-sdk/src/generated/schemas.rs b/python/foxglove-sdk/src/generated/schemas.rs index 245aa086f..f273059fa 100644 --- a/python/foxglove-sdk/src/generated/schemas.rs +++ b/python/foxglove-sdk/src/generated/schemas.rs @@ -65,6 +65,18 @@ pub(crate) enum PointsAnnotationType { LineList = 4, } +/// Style of point used for map visualization +#[pyclass(eq, eq_int, module = "foxglove.schemas")] +#[derive(PartialEq, Clone)] +pub(crate) enum LocationFixPointStyle { + Dot = 0, + Diamond = 1, + Square = 2, + Plus = 3, + Cross = 4, + Pin = 5, +} + /// Type of position covariance #[pyclass(eq, eq_int, module = "foxglove.schemas")] #[derive(PartialEq, Clone)] @@ -1403,6 +1415,7 @@ impl From for foxglove::schemas::LinePrimitive { /// :param position_covariance: 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. /// :param position_covariance_type: If `position_covariance` is available, `position_covariance_type` must be set to indicate the type of covariance. /// :param color: Color used to visualize the location +/// :param point_style: Style of the point used to visualize the location on the map /// /// See https://docs.foxglove.dev/docs/visualization/message-schemas/location-fix #[pyclass(module = "foxglove.schemas")] @@ -1411,7 +1424,7 @@ pub(crate) struct LocationFix(pub(crate) foxglove::schemas::LocationFix); #[pymethods] impl LocationFix { #[new] - #[pyo3(signature = (*, timestamp=None, frame_id="", latitude=0.0, longitude=0.0, altitude=0.0, position_covariance=None, position_covariance_type=LocationFixPositionCovarianceType::Unknown, color=None) )] + #[pyo3(signature = (*, timestamp=None, frame_id="", latitude=0.0, longitude=0.0, altitude=0.0, position_covariance=None, position_covariance_type=LocationFixPositionCovarianceType::Unknown, color=None, point_style=None) )] fn new( timestamp: Option, frame_id: &str, @@ -1421,6 +1434,7 @@ impl LocationFix { position_covariance: Option>, position_covariance_type: LocationFixPositionCovarianceType, color: Option, + point_style: Option, ) -> Self { Self(foxglove::schemas::LocationFix { timestamp: timestamp.map(Into::into), @@ -1431,11 +1445,12 @@ impl LocationFix { position_covariance: position_covariance.unwrap_or_default(), position_covariance_type: position_covariance_type as i32, color: color.map(Into::into), + point_style: point_style.map(|s| s as i32), }) } fn __repr__(&self) -> String { format!( - "LocationFix(timestamp={:?}, frame_id={:?}, latitude={:?}, longitude={:?}, altitude={:?}, position_covariance={:?}, position_covariance_type={:?}, color={:?})", + "LocationFix(timestamp={:?}, frame_id={:?}, latitude={:?}, longitude={:?}, altitude={:?}, position_covariance={:?}, position_covariance_type={:?}, color={:?}, point_style={:?})", self.0.timestamp, self.0.frame_id, self.0.latitude, @@ -1444,6 +1459,7 @@ impl LocationFix { self.0.position_covariance, self.0.position_covariance_type, self.0.color, + self.0.point_style, ) } /// Returns the LocationFix schema. @@ -3108,6 +3124,7 @@ pub fn register_submodule(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_class::()?; module.add_class::()?; module.add_class::()?; + module.add_class::()?; module.add_class::()?; module.add_class::()?; module.add_class::()?; diff --git a/ros/src/foxglove_msgs/ros1/LocationFix.msg b/ros/src/foxglove_msgs/ros1/LocationFix.msg index 8f597b134..75be5cd09 100644 --- a/ros/src/foxglove_msgs/ros1/LocationFix.msg +++ b/ros/src/foxglove_msgs/ros1/LocationFix.msg @@ -38,3 +38,24 @@ uint8 position_covariance_type # Color used to visualize the location foxglove_msgs/Color color + +# Dot marker +uint8 DOT=0 + +# Diamond-shaped marker +uint8 DIAMOND=1 + +# Square marker +uint8 SQUARE=2 + +# Plus-shaped marker (+) +uint8 PLUS=3 + +# Cross-shaped marker (x) +uint8 CROSS=4 + +# Pin marker +uint8 PIN=5 + +# Style of the point used to visualize the location on the map +uint8 point_style diff --git a/ros/src/foxglove_msgs/ros2/LocationFix.msg b/ros/src/foxglove_msgs/ros2/LocationFix.msg index 9ed7144f8..2246d94eb 100644 --- a/ros/src/foxglove_msgs/ros2/LocationFix.msg +++ b/ros/src/foxglove_msgs/ros2/LocationFix.msg @@ -38,3 +38,24 @@ uint8 position_covariance_type # Color used to visualize the location foxglove_msgs/Color color + +# Dot marker +uint8 DOT=0 + +# Diamond-shaped marker +uint8 DIAMOND=1 + +# Square marker +uint8 SQUARE=2 + +# Plus-shaped marker (+) +uint8 PLUS=3 + +# Cross-shaped marker (x) +uint8 CROSS=4 + +# Pin marker +uint8 PIN=5 + +# Style of the point used to visualize the location on the map +uint8 point_style diff --git a/rust/foxglove/src/schemas.rs b/rust/foxglove/src/schemas.rs index 89348a5fb..0fe7bf225 100644 --- a/rust/foxglove/src/schemas.rs +++ b/rust/foxglove/src/schemas.rs @@ -130,6 +130,58 @@ macro_rules! serde_enum_mod { #[cfg(feature = "serde")] pub(crate) use serde_enum_mod; +/// Generates a serde module for an optional protobuf enum field. +/// +/// Uses string names for human-readable formats (JSON) and i32 for binary formats. +#[cfg(feature = "serde")] +macro_rules! serde_enum_mod_optional { + ($mod_name:ident, $enum_path:ty) => { + pub mod $mod_name { + use super::*; + + pub fn serialize(v: &Option, s: S) -> Result + where + S: Serializer, + { + match v { + Some(v) => { + if s.is_human_readable() { + let e = <$enum_path>::try_from(*v) + .map_err(|_| serde::ser::Error::custom("invalid enum value"))?; + s.serialize_some(e.as_str_name()) + } else { + s.serialize_some(v) + } + } + None => s.serialize_none(), + } + } + + pub fn deserialize<'de, D>(d: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + if d.is_human_readable() { + let opt: Option = Option::deserialize(d)?; + match opt { + Some(s) => { + let e = <$enum_path>::from_str_name(&s) + .ok_or_else(|| D::Error::custom("invalid enum string"))?; + Ok(Some(e as i32)) + } + None => Ok(None), + } + } else { + Option::::deserialize(d) + } + } + } + }; +} + +#[cfg(feature = "serde")] +pub(crate) use serde_enum_mod_optional; + #[cfg(test)] #[cfg(feature = "serde")] mod tests { @@ -200,4 +252,57 @@ mod tests { let parsed: Grid = serde_cbor::from_slice(&bytes).expect("failed to deserialize"); assert_eq!(grid, parsed); } + + #[test] + fn test_location_fix_json_roundtrip_with_point_style() { + use super::{location_fix::PointStyle, LocationFix}; + + let fix = LocationFix { + latitude: 37.7749, + longitude: -122.4194, + altitude: 10.0, + point_style: Some(PointStyle::Pin as i32), + ..Default::default() + }; + let json = serde_json::to_string(&fix).expect("failed to serialize"); + assert!(json.contains("\"point_style\":\"PIN\"")); + let parsed: LocationFix = serde_json::from_str(&json).expect("failed to deserialize"); + assert_eq!(fix, parsed); + } + + #[test] + fn test_location_fix_json_roundtrip_with_none_point_style() { + use super::LocationFix; + + let fix = LocationFix { + latitude: 37.7749, + longitude: -122.4194, + point_style: None, + ..Default::default() + }; + let json = serde_json::to_string(&fix).expect("failed to serialize"); + assert!(json.contains("\"point_style\":null")); + let parsed: LocationFix = serde_json::from_str(&json).expect("failed to deserialize"); + assert_eq!(fix, parsed); + } + + #[test] + fn test_location_fix_json_invalid_point_style() { + use super::LocationFix; + + let json = r#"{"point_style":"INVALID_VALUE","latitude":0.0,"longitude":0.0,"altitude":0.0,"position_covariance":[],"position_covariance_type":"UNKNOWN"}"#; + let result: Result = serde_json::from_str(json); + assert!(result.is_err()); + } + + #[test] + fn test_location_fix_json_missing_point_style() { + use super::LocationFix; + + // JSON without point_style field at all — must deserialize with point_style: None + let json = r#"{"latitude":37.7749,"longitude":-122.4194,"altitude":0.0,"frame_id":"","position_covariance":[],"position_covariance_type":"UNKNOWN"}"#; + let parsed: LocationFix = serde_json::from_str(json).expect("failed to deserialize"); + assert_eq!(parsed.point_style, None); + assert_eq!(parsed.latitude, 37.7749); + } } diff --git a/rust/foxglove/src/schemas/data/LocationFix.bin b/rust/foxglove/src/schemas/data/LocationFix.bin index ee5a76c6d..3ba7df14e 100644 Binary files a/rust/foxglove/src/schemas/data/LocationFix.bin and b/rust/foxglove/src/schemas/data/LocationFix.bin differ diff --git a/rust/foxglove/src/schemas/data/LocationFixes.bin b/rust/foxglove/src/schemas/data/LocationFixes.bin index 6714f9b4a..858339ae9 100644 Binary files a/rust/foxglove/src/schemas/data/LocationFixes.bin and b/rust/foxglove/src/schemas/data/LocationFixes.bin differ diff --git a/rust/foxglove/src/schemas/foxglove.rs b/rust/foxglove/src/schemas/foxglove.rs index 0a0386ef3..328422345 100644 --- a/rust/foxglove/src/schemas/foxglove.rs +++ b/rust/foxglove/src/schemas/foxglove.rs @@ -554,9 +554,71 @@ pub struct LocationFix { /// Color used to visualize the location #[prost(message, optional, tag = "8")] pub color: ::core::option::Option, + /// Style of the point used to visualize the location on the map + #[prost(enumeration = "location_fix::PointStyle", optional, tag = "9")] + #[cfg_attr( + feature = "serde", + serde(with = "serde_enum::location_fix_point_style", default) + )] + pub point_style: ::core::option::Option, } /// Nested message and enum types in `LocationFix`. pub mod location_fix { + /// Style of point used for map visualization + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum PointStyle { + /// Dot marker + Dot = 0, + /// Diamond-shaped marker + Diamond = 1, + /// Square marker + Square = 2, + /// Plus-shaped marker (+) + Plus = 3, + /// Cross-shaped marker (x) + Cross = 4, + /// Pin marker + Pin = 5, + } + impl PointStyle { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Dot => "DOT", + Self::Diamond => "DIAMOND", + Self::Square => "SQUARE", + Self::Plus => "PLUS", + Self::Cross => "CROSS", + Self::Pin => "PIN", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "DOT" => Some(Self::Dot), + "DIAMOND" => Some(Self::Diamond), + "SQUARE" => Some(Self::Square), + "PLUS" => Some(Self::Plus), + "CROSS" => Some(Self::Cross), + "PIN" => Some(Self::Pin), + _ => None, + } + } + } /// Type of position covariance #[derive( Clone, @@ -1439,6 +1501,7 @@ pub(crate) mod serde_enum { crate::schemas::serde_enum_mod!(line_primitive_type, line_primitive::Type); crate::schemas::serde_enum_mod!(location_fix_position_covariance_type, location_fix::PositionCovarianceType); + crate::schemas::serde_enum_mod_optional!(location_fix_point_style, location_fix::PointStyle); crate::schemas::serde_enum_mod!(log_level, log::Level); crate::schemas::serde_enum_mod!(packed_element_field_numeric_type, packed_element_field::NumericType); crate::schemas::serde_enum_mod!(points_annotation_type, points_annotation::Type); diff --git a/rust/foxglove_proto_gen/src/lib.rs b/rust/foxglove_proto_gen/src/lib.rs index f7ef9bd18..e04927522 100644 --- a/rust/foxglove_proto_gen/src/lib.rs +++ b/rust/foxglove_proto_gen/src/lib.rs @@ -93,6 +93,8 @@ struct EnumFieldInfo { enum_rust_path: String, /// Snake case name for the serde module (e.g., "log_level") serde_module_name: String, + /// Whether the field is optional in the protobuf definition + optional: bool, } /// Collect bytes fields and enum fields from the file descriptor set. @@ -192,10 +194,13 @@ fn collect_field_info( let serde_module_name = format!("{}_{}", msg_snake, camel_case_to_snake_case(enum_name)); + let optional = field.proto3_optional.unwrap_or(false); + enum_fields.push(EnumFieldInfo { field_path, enum_rust_path, serde_module_name, + optional, }); } } @@ -443,12 +448,13 @@ pub fn generate_protos(proto_path: &Path, out_dir: &Path) -> anyhow::Result<()> // Add serde attributes for enum fields. The serde implementations referenced here are appended // to the foxglove.rs by generate_serde_enum_module() below. for info in &enum_fields { + let mut serde_attrs = format!("with = \"serde_enum::{}\"", info.serde_module_name); + if info.optional { + serde_attrs.push_str(", default"); + } config.field_attribute( &info.field_path, - format!( - "#[cfg_attr(feature = \"serde\", serde(with = \"serde_enum::{}\"))]", - info.serde_module_name - ), + format!("#[cfg_attr(feature = \"serde\", serde({serde_attrs}))]",), ); } @@ -498,10 +504,15 @@ fn generate_serde_enum_module(out_dir: &Path, enum_fields: &[EnumFieldInfo]) -> writeln!(file)?; for info in unique_enums { + let macro_name = if info.optional { + "serde_enum_mod_optional" + } else { + "serde_enum_mod" + }; writeln!( file, - " crate::schemas::serde_enum_mod!({}, {});", - info.serde_module_name, info.enum_rust_path + " crate::schemas::{}!({}, {});", + macro_name, info.serde_module_name, info.enum_rust_path )?; } diff --git a/schemas/README.md b/schemas/README.md index 8a67a211b..6142fd4d5 100644 --- a/schemas/README.md +++ b/schemas/README.md @@ -16,6 +16,7 @@ If the IDL does not support optional fields (e.g. ROS) you must specify a value - [enum LogLevel](#enum-loglevel) - [enum NumericType](#enum-numerictype) - [enum PointsAnnotationType](#enum-pointsannotationtype) +- [enum PointStyle](#enum-pointstyle) - [enum PositionCovarianceType](#enum-positioncovariancetype) - [enum SceneEntityDeletionType](#enum-sceneentitydeletiontype) - [ArrowPrimitive](#arrowprimitive) @@ -124,6 +125,21 @@ name | value | description +## enum PointStyle + +Style of point used for map visualization + +name | value | description +---- | ----- | ----------- +`DOT` | 0 | Dot marker +`DIAMOND` | 1 | Diamond-shaped marker +`SQUARE` | 2 | Square marker +`PLUS` | 3 | Plus-shaped marker (+) +`CROSS` | 4 | Cross-shaped marker (x) +`PIN` | 5 | Pin marker + + + ## enum PositionCovarianceType Type of position covariance @@ -1613,6 +1629,19 @@ If `position_covariance` is available, `position_covariance_type` must be set to Color used to visualize the location + + + +point_style (optional) + + +[enum PointStyle](#enum-pointstyle) + + + + +Style of the point used to visualize the location on the map + diff --git a/schemas/flatbuffer/LocationFix.fbs b/schemas/flatbuffer/LocationFix.fbs index ff79ee3f7..653277dd1 100644 --- a/schemas/flatbuffer/LocationFix.fbs +++ b/schemas/flatbuffer/LocationFix.fbs @@ -5,6 +5,28 @@ include "Time.fbs"; namespace foxglove; +/// Style of point used for map visualization +enum PointStyle : ubyte { + /// Dot marker + DOT = 0, + + /// Diamond-shaped marker + DIAMOND = 1, + + /// Square marker + SQUARE = 2, + + /// Plus-shaped marker (+) + PLUS = 3, + + /// Cross-shaped marker (x) + CROSS = 4, + + /// Pin marker + PIN = 5, +} + + /// Type of position covariance enum PositionCovarianceType : ubyte { /// Unknown position covariance type @@ -45,6 +67,9 @@ table LocationFix { /// Color used to visualize the location color:foxglove.Color (id: 7); + + /// Style of the point used to visualize the location on the map + point_style:PointStyle (id: 8); } root_type LocationFix; diff --git a/schemas/jsonschema/LocationFix.json b/schemas/jsonschema/LocationFix.json index 0e0a85a71..18df69d72 100644 --- a/schemas/jsonschema/LocationFix.json +++ b/schemas/jsonschema/LocationFix.json @@ -99,6 +99,42 @@ "b", "a" ] + }, + "point_style": { + "title": "foxglove.PointStyle", + "description": "Style of the point used to visualize the location on the map", + "oneOf": [ + { + "title": "DOT", + "const": 0, + "description": "Dot marker" + }, + { + "title": "DIAMOND", + "const": 1, + "description": "Diamond-shaped marker" + }, + { + "title": "SQUARE", + "const": 2, + "description": "Square marker" + }, + { + "title": "PLUS", + "const": 3, + "description": "Plus-shaped marker (+)" + }, + { + "title": "CROSS", + "const": 4, + "description": "Cross-shaped marker (x)" + }, + { + "title": "PIN", + "const": 5, + "description": "Pin marker" + } + ] } }, "required": [ diff --git a/schemas/jsonschema/LocationFixes.json b/schemas/jsonschema/LocationFixes.json index 48d778fe7..309e3a956 100644 --- a/schemas/jsonschema/LocationFixes.json +++ b/schemas/jsonschema/LocationFixes.json @@ -106,6 +106,42 @@ "b", "a" ] + }, + "point_style": { + "title": "foxglove.PointStyle", + "description": "Style of the point used to visualize the location on the map", + "oneOf": [ + { + "title": "DOT", + "const": 0, + "description": "Dot marker" + }, + { + "title": "DIAMOND", + "const": 1, + "description": "Diamond-shaped marker" + }, + { + "title": "SQUARE", + "const": 2, + "description": "Square marker" + }, + { + "title": "PLUS", + "const": 3, + "description": "Plus-shaped marker (+)" + }, + { + "title": "CROSS", + "const": 4, + "description": "Cross-shaped marker (x)" + }, + { + "title": "PIN", + "const": 5, + "description": "Pin marker" + } + ] } }, "required": [ diff --git a/schemas/jsonschema/index.ts b/schemas/jsonschema/index.ts index 045afb01b..b028a0c08 100644 --- a/schemas/jsonschema/index.ts +++ b/schemas/jsonschema/index.ts @@ -2311,6 +2311,42 @@ export const LocationFix = { "b", "a" ] + }, + "point_style": { + "title": "foxglove.PointStyle", + "description": "Style of the point used to visualize the location on the map", + "oneOf": [ + { + "title": "DOT", + "const": 0, + "description": "Dot marker" + }, + { + "title": "DIAMOND", + "const": 1, + "description": "Diamond-shaped marker" + }, + { + "title": "SQUARE", + "const": 2, + "description": "Square marker" + }, + { + "title": "PLUS", + "const": 3, + "description": "Plus-shaped marker (+)" + }, + { + "title": "CROSS", + "const": 4, + "description": "Cross-shaped marker (x)" + }, + { + "title": "PIN", + "const": 5, + "description": "Pin marker" + } + ] } }, "required": [ @@ -2432,6 +2468,42 @@ export const LocationFixes = { "b", "a" ] + }, + "point_style": { + "title": "foxglove.PointStyle", + "description": "Style of the point used to visualize the location on the map", + "oneOf": [ + { + "title": "DOT", + "const": 0, + "description": "Dot marker" + }, + { + "title": "DIAMOND", + "const": 1, + "description": "Diamond-shaped marker" + }, + { + "title": "SQUARE", + "const": 2, + "description": "Square marker" + }, + { + "title": "PLUS", + "const": 3, + "description": "Plus-shaped marker (+)" + }, + { + "title": "CROSS", + "const": 4, + "description": "Cross-shaped marker (x)" + }, + { + "title": "PIN", + "const": 5, + "description": "Pin marker" + } + ] } }, "required": [ diff --git a/schemas/omgidl/foxglove/LocationFix.idl b/schemas/omgidl/foxglove/LocationFix.idl index fa857fb86..29f1df941 100644 --- a/schemas/omgidl/foxglove/LocationFix.idl +++ b/schemas/omgidl/foxglove/LocationFix.idl @@ -1,6 +1,7 @@ // Generated by https://github.com/foxglove/foxglove-sdk #include "foxglove/Color.idl" +#include "foxglove/PointStyle.idl" #include "foxglove/PositionCovarianceType.idl" #include "foxglove/Time.idl" @@ -32,6 +33,10 @@ struct LocationFix { // Color used to visualize the location @optional Color color; + + // Style of the point used to visualize the location on the map + @optional + PointStyle point_style; }; }; diff --git a/schemas/omgidl/foxglove/PointStyle.idl b/schemas/omgidl/foxglove/PointStyle.idl new file mode 100644 index 000000000..9ec2d8c17 --- /dev/null +++ b/schemas/omgidl/foxglove/PointStyle.idl @@ -0,0 +1,32 @@ +// Generated by https://github.com/foxglove/foxglove-sdk + +module foxglove { + +// Style of point used for map visualization +enum PointStyle { + // Dot marker + // Value: 0 + DOT, + + // Diamond-shaped marker + // Value: 1 + DIAMOND, + + // Square marker + // Value: 2 + SQUARE, + + // Plus-shaped marker (+) + // Value: 3 + PLUS, + + // Cross-shaped marker (x) + // Value: 4 + CROSS, + + // Pin marker + // Value: 5 + PIN +}; + +}; diff --git a/schemas/proto/foxglove/LocationFix.proto b/schemas/proto/foxglove/LocationFix.proto index aa87ad5cd..6e7a58460 100644 --- a/schemas/proto/foxglove/LocationFix.proto +++ b/schemas/proto/foxglove/LocationFix.proto @@ -9,6 +9,28 @@ package foxglove; // A navigation satellite fix for any Global Navigation Satellite System message LocationFix { + // Style of point used for map visualization + enum PointStyle { + // Dot marker + DOT = 0; + + // Diamond-shaped marker + DIAMOND = 1; + + // Square marker + SQUARE = 2; + + // Plus-shaped marker (+) + PLUS = 3; + + // Cross-shaped marker (x) + CROSS = 4; + + // Pin marker + PIN = 5; + } + + // Type of position covariance enum PositionCovarianceType { // Unknown position covariance type @@ -46,4 +68,7 @@ message LocationFix { // Color used to visualize the location optional foxglove.Color color = 8; + + // Style of the point used to visualize the location on the map + optional PointStyle point_style = 9; } diff --git a/schemas/ros1/LocationFix.msg b/schemas/ros1/LocationFix.msg index 8f597b134..75be5cd09 100644 --- a/schemas/ros1/LocationFix.msg +++ b/schemas/ros1/LocationFix.msg @@ -38,3 +38,24 @@ uint8 position_covariance_type # Color used to visualize the location foxglove_msgs/Color color + +# Dot marker +uint8 DOT=0 + +# Diamond-shaped marker +uint8 DIAMOND=1 + +# Square marker +uint8 SQUARE=2 + +# Plus-shaped marker (+) +uint8 PLUS=3 + +# Cross-shaped marker (x) +uint8 CROSS=4 + +# Pin marker +uint8 PIN=5 + +# Style of the point used to visualize the location on the map +uint8 point_style diff --git a/schemas/ros2/LocationFix.msg b/schemas/ros2/LocationFix.msg index 9ed7144f8..2246d94eb 100644 --- a/schemas/ros2/LocationFix.msg +++ b/schemas/ros2/LocationFix.msg @@ -38,3 +38,24 @@ uint8 position_covariance_type # Color used to visualize the location foxglove_msgs/Color color + +# Dot marker +uint8 DOT=0 + +# Diamond-shaped marker +uint8 DIAMOND=1 + +# Square marker +uint8 SQUARE=2 + +# Plus-shaped marker (+) +uint8 PLUS=3 + +# Cross-shaped marker (x) +uint8 CROSS=4 + +# Pin marker +uint8 PIN=5 + +# Style of the point used to visualize the location on the map +uint8 point_style diff --git a/typescript/schemas/src/internal/__snapshots__/exportTypeScriptSchemas.test.ts.snap b/typescript/schemas/src/internal/__snapshots__/exportTypeScriptSchemas.test.ts.snap index f33a019b0..a549ca9aa 100644 --- a/typescript/schemas/src/internal/__snapshots__/exportTypeScriptSchemas.test.ts.snap +++ b/typescript/schemas/src/internal/__snapshots__/exportTypeScriptSchemas.test.ts.snap @@ -586,6 +586,7 @@ export type LinePrimitive = { // Options: {} import { Color } from "./Color"; +import { PointStyle } from "./PointStyle"; import { PositionCovarianceType } from "./PositionCovarianceType"; import { Time } from "./Time"; @@ -614,6 +615,9 @@ export type LocationFix = { /** Color used to visualize the location */ color?: Color; + + /** Style of the point used to visualize the location on the map */ + point_style?: PointStyle; }; ", "LocationFixes" => "// Generated by https://github.com/foxglove/foxglove-sdk @@ -1315,6 +1319,30 @@ export enum PointsAnnotationType { /** Individual line segments: 0-1, 2-3, 4-5, ... */ LINE_LIST = 4, } +", + "PointStyle" => "// Generated by https://github.com/foxglove/foxglove-sdk +// Options: {} + +/** Style of point used for map visualization */ +export enum PointStyle { + /** Dot marker */ + DOT = 0, + + /** Diamond-shaped marker */ + DIAMOND = 1, + + /** Square marker */ + SQUARE = 2, + + /** Plus-shaped marker (+) */ + PLUS = 3, + + /** Cross-shaped marker (x) */ + CROSS = 4, + + /** Pin marker */ + PIN = 5, +} ", "PositionCovarianceType" => "// Generated by https://github.com/foxglove/foxglove-sdk // Options: {} @@ -1370,6 +1398,7 @@ export * from "./Point3InFrame"; export * from "./PointCloud"; export * from "./PointsAnnotation"; export * from "./PointsAnnotationType"; +export * from "./PointStyle"; export * from "./Pose"; export * from "./PoseInFrame"; export * from "./PosesInFrame"; diff --git a/typescript/schemas/src/internal/generateFlatbufferSchema.test.ts b/typescript/schemas/src/internal/generateFlatbufferSchema.test.ts index f60a5fc2a..33cebcc70 100644 --- a/typescript/schemas/src/internal/generateFlatbufferSchema.test.ts +++ b/typescript/schemas/src/internal/generateFlatbufferSchema.test.ts @@ -4,124 +4,127 @@ import { exampleEnum, exampleMessage } from "./testFixtures"; describe("generateFlatbuffers", () => { it("generates Message .fbs files", () => { expect(generateFlatbuffers(exampleMessage, [exampleEnum])).toMatchInlineSnapshot(` - "// Generated by https://github.com/foxglove/foxglove-sdk + "// Generated by https://github.com/foxglove/foxglove-sdk - include "ByteVector.fbs"; - include "Duration.fbs"; - include "NestedMessage.fbs"; - include "Time.fbs"; + include "ByteVector.fbs"; + include "Duration.fbs"; + include "NestedMessage.fbs"; + include "Time.fbs"; - namespace foxglove; + namespace foxglove; - /// An example enum - enum ExampleEnum : ubyte { - /// Value A - A = 0, + /// An example enum + enum ExampleEnum : ubyte { + /// Value A + A = 0, - /// Value B - B = 1, - } - /// An example type - table ExampleMessage { - /// duration field - field_duration:Duration (id: 0); + /// Value B + B = 1, + } + /// An example type + table ExampleMessage { + /// duration field + field_duration:Duration (id: 0); - /// time field - field_time:Time (id: 1); + /// time field + field_time:Time (id: 1); - /// boolean field - field_boolean:bool = true (id: 2); + /// boolean field + field_boolean:bool = true (id: 2); - /// bytes field - field_bytes:[uint8] (id: 3); + /// bytes field + field_bytes:[uint8] (id: 3); - /// float64 field - field_float64:double = 1.0 (id: 4); + /// float64 field + field_float64:double = 1.0 (id: 4); - /// uint32 field - field_uint32:uint32 = 5 (id: 5); + /// uint32 field + field_uint32:uint32 = 5 (id: 5); - /// string field - field_string:string = "string-type" (id: 6); + /// string field + field_string:string = "string-type" (id: 6); - /// duration array field - field_duration_array:[Duration] (id: 7); + /// duration array field + field_duration_array:[Duration] (id: 7); - /// time array field - field_time_array:[Time] (id: 8); + /// time array field + field_time_array:[Time] (id: 8); - /// boolean array field - field_boolean_array:[bool] (id: 9); + /// boolean array field + field_boolean_array:[bool] (id: 9); - /// bytes array field - field_bytes_array:[ByteVector] (id: 10); + /// bytes array field + field_bytes_array:[ByteVector] (id: 10); - /// float64 array field - field_float64_array:[double] (id: 11); + /// float64 array field + field_float64_array:[double] (id: 11); - /// uint32 array field - field_uint32_array:[uint32] (id: 12); + /// uint32 array field + field_uint32_array:[uint32] (id: 12); - /// string array field - field_string_array:[string] (id: 13); + /// string array field + field_string_array:[string] (id: 13); - /// duration fixed-length array field - /// length 3 - field_duration_fixed_array:[Duration] (id: 14); + /// duration fixed-length array field + /// length 3 + field_duration_fixed_array:[Duration] (id: 14); - /// time fixed-length array field - /// length 3 - field_time_fixed_array:[Time] (id: 15); + /// time fixed-length array field + /// length 3 + field_time_fixed_array:[Time] (id: 15); - /// boolean fixed-length array field - /// length 3 - field_boolean_fixed_array:[bool] (id: 16); + /// boolean fixed-length array field + /// length 3 + field_boolean_fixed_array:[bool] (id: 16); - /// bytes fixed-length array field - /// length 3 - field_bytes_fixed_array:[ByteVector] (id: 17); + /// bytes fixed-length array field + /// length 3 + field_bytes_fixed_array:[ByteVector] (id: 17); - /// float64 fixed-length array field - /// length 3 - field_float64_fixed_array:[double] (id: 18); + /// float64 fixed-length array field + /// length 3 + field_float64_fixed_array:[double] (id: 18); - /// uint32 fixed-length array field - /// length 3 - field_uint32_fixed_array:[uint32] (id: 19); + /// uint32 fixed-length array field + /// length 3 + field_uint32_fixed_array:[uint32] (id: 19); - /// string fixed-length array field - /// length 3 - field_string_fixed_array:[string] (id: 20); + /// string fixed-length array field + /// length 3 + field_string_fixed_array:[string] (id: 20); - /// An enum field - field_enum:ExampleEnum (id: 21); + /// An enum field + field_enum:ExampleEnum (id: 21); - /// An enum array field - field_enum_array:[ExampleEnum] (id: 22); + /// An enum array field + field_enum_array:[ExampleEnum] (id: 22); - /// A nested field - field_nested:foxglove.NestedMessage (id: 23); + /// A nested field + field_nested:foxglove.NestedMessage (id: 23); - /// A nested array field - /// With - /// a - /// very - /// long - /// description - field_nested_array:[foxglove.NestedMessage] (id: 24); + /// A nested array field + /// With + /// a + /// very + /// long + /// description + field_nested_array:[foxglove.NestedMessage] (id: 24); - /// An optional string field - field_optional_string:string (id: 25); + /// An optional string field + field_optional_string:string (id: 25); - /// An optional bool field - field_optional_bool:bool (id: 26); + /// An optional bool field + field_optional_bool:bool (id: 26); - /// An optional float64 field - field_optional_float64:double (id: 27); - } + /// An optional float64 field + field_optional_float64:double (id: 27); - root_type ExampleMessage; - " + /// An optional enum field + field_optional_enum:ExampleEnum (id: 28); + } + + root_type ExampleMessage; + " `); }); }); diff --git a/typescript/schemas/src/internal/generateJsonSchema.test.ts b/typescript/schemas/src/internal/generateJsonSchema.test.ts index 9f3aab350..63b68ad8c 100644 --- a/typescript/schemas/src/internal/generateJsonSchema.test.ts +++ b/typescript/schemas/src/internal/generateJsonSchema.test.ts @@ -206,6 +206,22 @@ describe("generateJsonSchema", () => { "description": "An optional bool field", "type": "boolean", }, + "field_optional_enum": { + "description": "An optional enum field", + "oneOf": [ + { + "const": 0, + "description": "Value A", + "title": "A", + }, + { + "const": 1, + "description": "Value B", + "title": "B", + }, + ], + "title": "foxglove.ExampleEnum", + }, "field_optional_float64": { "description": "An optional float64 field", "type": "number", diff --git a/typescript/schemas/src/internal/generateOmgIdl.test.ts b/typescript/schemas/src/internal/generateOmgIdl.test.ts index 2662896e3..a17825281 100644 --- a/typescript/schemas/src/internal/generateOmgIdl.test.ts +++ b/typescript/schemas/src/internal/generateOmgIdl.test.ts @@ -26,116 +26,120 @@ describe("generateOmgIdl", () => { " `); expect(generateOmgIdl(exampleMessage)).toMatchInlineSnapshot(` - "// Generated by https://github.com/foxglove/foxglove-sdk + "// Generated by https://github.com/foxglove/foxglove-sdk - #include "foxglove/Duration.idl" - #include "foxglove/ExampleEnum.idl" - #include "foxglove/NestedMessage.idl" - #include "foxglove/Time.idl" + #include "foxglove/Duration.idl" + #include "foxglove/ExampleEnum.idl" + #include "foxglove/NestedMessage.idl" + #include "foxglove/Time.idl" - module foxglove { + module foxglove { - // An example type - struct ExampleMessage { - // duration field - Duration field_duration; + // An example type + struct ExampleMessage { + // duration field + Duration field_duration; - // time field - Time field_time; + // time field + Time field_time; - // boolean field - @default(TRUE) - boolean field_boolean; + // boolean field + @default(TRUE) + boolean field_boolean; - // bytes field - sequence field_bytes; + // bytes field + sequence field_bytes; - // float64 field - @default(1.0) - double field_float64; + // float64 field + @default(1.0) + double field_float64; - // uint32 field - @default(5) - uint32 field_uint32; + // uint32 field + @default(5) + uint32 field_uint32; - // string field - @default("string-type") - string field_string; + // string field + @default("string-type") + string field_string; - // duration array field - sequence field_duration_array; + // duration array field + sequence field_duration_array; - // time array field - sequence