From 4b304fbd4e7f348fca11edbcd53f3a7e48a8bc47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20P=C4=99dzich?= Date: Mon, 17 Feb 2025 13:21:30 +0100 Subject: [PATCH] feat: add 2022 spec motion packet parser --- .idea/.gitignore | 8 ++++ rustfmt.toml | 6 +++ src/constants/mod.rs | 36 +++++++++++++++ src/constants/wheel_index.rs | 4 ++ src/packets/mod.rs | 88 ++++++++++++++++++++++++++++++++++++ src/packets/motion.rs | 77 +++++++++++++++++++++++++++++++ 6 files changed, 219 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 rustfmt.toml create mode 100644 src/constants/mod.rs create mode 100644 src/constants/wheel_index.rs create mode 100644 src/packets/mod.rs create mode 100644 src/packets/motion.rs diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..9a3ee09 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,6 @@ +max_width = 80 +format_code_in_doc_comments = true +imports_granularity = "Crate" +imports_layout = "Vertical" +use_small_heuristics = "Max" +wrap_comments = true diff --git a/src/constants/mod.rs b/src/constants/mod.rs new file mode 100644 index 0000000..606e5ae --- /dev/null +++ b/src/constants/mod.rs @@ -0,0 +1,36 @@ +pub mod wheel_index; + +use binrw::BinRead; +use serde::{Deserialize, Serialize}; + +#[non_exhaustive] +#[derive( + BinRead, + Eq, + PartialEq, + Ord, + PartialOrd, + Copy, + Clone, + Debug, + Serialize, + Deserialize, +)] +#[br(little, repr(u8))] +pub enum PacketId { + Motion = 0, + Session = 1, + LapData = 2, + Event = 3, + Participants = 4, + CarSetups = 5, + CarTelemetry = 6, + CarStatus = 7, + FinalClassification = 8, + LobbyInfo = 9, + CarDamage = 10, + SessionHistory = 11, + TyreSets = 12, + MotionEx = 13, + TimeTrial = 14, +} diff --git a/src/constants/wheel_index.rs b/src/constants/wheel_index.rs new file mode 100644 index 0000000..1abeea7 --- /dev/null +++ b/src/constants/wheel_index.rs @@ -0,0 +1,4 @@ +pub const REAR_LEFT: usize = 0; +pub const REAR_RIGHT: usize = 1; +pub const FRONT_LEFT: usize = 2; +pub const FRONT_RIGHT: usize = 3; diff --git a/src/packets/mod.rs b/src/packets/mod.rs new file mode 100644 index 0000000..80cd06c --- /dev/null +++ b/src/packets/mod.rs @@ -0,0 +1,88 @@ +pub mod motion; + +use crate::packets::motion::CarMotionData; + +use binrw::BinRead; +use serde::{Deserialize, Serialize}; +use std::string::FromUtf8Error; + +/// Physics data for all the cars being driven. +#[non_exhaustive] +#[derive( + BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize, +)] +#[br(little, import(packet_format: u16))] +pub struct F1PacketMotionData { + /// Motion data for all cars on track. + #[br(count(22))] + pub car_motion_data: Vec, + /// Extra player car ONLY motion data (2022 format only). + #[br(if(packet_format == 2022))] + pub motion_ex_data: Option, +} + +/// Extended motion data for player's car. Available as a: +/// - part of [`F1PacketMotionData`] in the 2022 format +/// - standalone packet from the 2023 format onwards +#[non_exhaustive] +#[derive( + BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, +)] +#[br(little, import(_packet_format: u16))] +pub struct F1PacketMotionExData { + /// Positions of suspension for each wheel. + /// See [`wheel_index`](mod@crate::constants::wheel_index) + /// for wheel order. + pub suspension_position: [f32; 4], + /// Velocities of suspension. + /// See [`wheel_index`](mod@crate::constants::wheel_index) + /// for wheel order. + pub suspension_velocity: [f32; 4], + /// Accelerations of suspension in the following order: + /// See [`wheel_index`](mod@crate::constants::wheel_index) + /// for wheel order. + pub suspension_acceleration: [f32; 4], + /// Speed of each wheel in the following order: + /// See [`wheel_index`](mod@crate::constants::wheel_index) + /// for wheel order. + pub wheel_speed: [f32; 4], + /// Slip ratio of each wheel in the following order: + /// See [`wheel_index`](mod@crate::constants::wheel_index) + /// for wheel order. + pub wheel_slip: [f32; 4], + /// X velocity in local space. + pub local_velocity_x: f32, + /// Y velocity in local space. + pub local_velocity_y: f32, + /// Z velocity in local space. + pub local_velocity_z: f32, + /// Angular velocity X component. + pub angular_velocity_x: f32, + /// Angular velocity Y component. + pub angular_velocity_y: f32, + /// Angular velocity Z component. + pub angular_velocity_z: f32, + /// Angular acceleration X component. + pub angular_acceleration_x: f32, + /// Angular acceleration Y component. + pub angular_acceleration_y: f32, + /// Angular acceleration Z component. + pub angular_acceleration_z: f32, + /// Current front wheels angle in radians. + pub front_wheels_angle: f32, +} + +pub(crate) fn u8_to_bool(value: u8) -> bool { + value == 1 +} + +pub(crate) fn u8_to_usize(value: u8) -> usize { + value as usize +} + +pub(crate) fn read_name(bytes: [u8; 48]) -> Result { + let first_nul_index = + bytes.iter().position(|&byte| byte == b'\0').unwrap_or(bytes.len()); + + String::from_utf8(bytes[..first_nul_index].to_vec()) +} diff --git a/src/packets/motion.rs b/src/packets/motion.rs new file mode 100644 index 0000000..a4d6a1a --- /dev/null +++ b/src/packets/motion.rs @@ -0,0 +1,77 @@ +use binrw::BinRead; +use serde::{Deserialize, Serialize}; + +#[derive( + BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, +)] +#[br(little)] +pub struct CarMotionData { + /// World space X position in metres + pub world_position_x: f32, + /// World space Y position in metres + pub world_position_y: f32, + /// World space Z position in metres + pub world_position_z: f32, + /// Velocity in world space X position + pub world_velocity_x: f32, + /// Velocity in world space Y position + pub world_velocity_y: f32, + /// Velocity in world space Z position + pub world_velocity_z: f32, + /// World space forward X direction (normalised) + pub world_forward_dir_x: i16, + /// World space forward Y direction (normalised) + pub world_forward_dir_y: i16, + /// World space forward Z direction (normalised) + pub world_forward_dir_z: i16, + /// World space right X direction (normalised) + pub world_right_dir_x: i16, + /// World space right Y direction (normalised) + pub world_right_dir_y: i16, + /// World space right Z direction (normalised) + pub world_right_dir_z: i16, + /// Lateral G-Force component + pub g_force_lateral: f32, + /// Longitudinal G-Force component + pub g_force_longitudinal: f32, + /// Vertical G-Force component + pub g_force_vertical: f32, + /// Yaw angle in radians + pub yaw: f32, + /// Pitch angle in radians + pub pitch: f32, + /// Roll angle in radians + pub roll: f32, +} + +impl CarMotionData { + /// Returns [`self.world_forward_dir_x`] divided by `32767.0f32` + pub fn world_forward_dir_x_as_f32(&self) -> f32 { + self.world_forward_dir_x as f32 / 32767.0 + } + + /// Returns [`self.world_forward_dir_y`] divided by `32767.0f32` + pub fn world_forward_dir_y_as_f32(&self) -> f32 { + self.world_forward_dir_y as f32 / 32767.0 + } + + /// Returns [`self.world_forward_dir_z`] divided by `32767.0f32` + pub fn world_forward_dir_z_as_f32(&self) -> f32 { + self.world_forward_dir_z as f32 / 32767.0 + } + + /// Returns [`self.world_right_dir_x`] divided by `32767.0f32` + pub fn world_right_dir_x_as_f32(&self) -> f32 { + self.world_right_dir_x as f32 / 32767.0 + } + + /// Returns [`self.world_right_dir_y`] divided by `32767.0f32` + pub fn world_right_dir_y_as_f32(&self) -> f32 { + self.world_right_dir_y as f32 / 32767.0 + } + + /// Returns [`self.world_right_dir_z`] divided by `32767.0f32` + pub fn world_right_dir_z_as_f32(&self) -> f32 { + self.world_right_dir_z as f32 / 32767.0 + } +}