carla 0.14.1

Rust client library for Carla simulator
Documentation
use super::SemanticLidarDetection;
use crate::sensor::SensorData;
use carla_sys::carla_rust::sensor::data::FfiSemanticLidarMeasurement;
use cxx::SharedPtr;
use derivative::Derivative;
use ndarray::ArrayView2;
use static_assertions::assert_impl_all;
use std::slice;

#[derive(Clone, Derivative)]
#[derivative(Debug)]
#[repr(transparent)]
pub struct SemanticLidarMeasurement {
    #[derivative(Debug = "ignore")]
    inner: SharedPtr<FfiSemanticLidarMeasurement>,
}

impl SemanticLidarMeasurement {
    pub fn horizontal_angle(&self) -> f32 {
        self.inner.GetHorizontalAngle()
    }

    pub fn point_count(&self, channel: usize) -> Option<usize> {
        (channel < self.channel_count()).then(|| self.inner.GetPointCount(channel) as usize)
    }

    pub fn channel_count(&self) -> usize {
        self.inner.GetChannelCount() as usize
    }

    pub fn as_slice(&self) -> &[SemanticLidarDetection] {
        let ptr = self.inner.data();
        let len = self.len();

        debug_assert!(
            !ptr.is_null(),
            "SemanticLidarMeasurement data pointer is null"
        );
        debug_assert!(
            (ptr as usize).is_multiple_of(std::mem::align_of::<SemanticLidarDetection>()),
            "SemanticLidarMeasurement data pointer not properly aligned"
        );

        unsafe { slice::from_raw_parts(ptr, len) }
    }

    pub fn as_array(&self) -> ArrayView2<'_, SemanticLidarDetection> {
        let len = self.len();
        let ih = self.channel_count();
        assert!(ih > 0, "Channel count is zero, cannot create array");
        let iw = len / ih;
        assert!(
            ih * iw == len,
            "Invalid dimensions: length {} not evenly divisible by channel count {}",
            len,
            ih
        );
        ArrayView2::from_shape((iw, ih), self.as_slice())
            .expect("Failed to create array view with valid dimensions")
    }

    pub fn len(&self) -> usize {
        self.inner.size()
    }

    #[must_use]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub(crate) fn from_cxx(ptr: SharedPtr<FfiSemanticLidarMeasurement>) -> Option<Self> {
        if ptr.is_null() {
            None
        } else {
            Some(Self { inner: ptr })
        }
    }
}

impl TryFrom<SensorData> for SemanticLidarMeasurement {
    type Error = SensorData;

    fn try_from(value: SensorData) -> Result<Self, Self::Error> {
        let ptr = value.inner.to_semantic_lidar_measurement();
        Self::from_cxx(ptr).ok_or(value)
    }
}

assert_impl_all!(SemanticLidarMeasurement: Send, Sync);