more general pointcloud2 with into/from
This commit is contained in:
parent
36a8272e23
commit
1d9525147a
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ros_pointcloud2"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
authors = ["Christopher Sieh <stelzo@steado.de>"]
|
||||
description = "A library for working with pointcloud2 messages in Rust"
|
||||
|
|
@ -16,6 +16,9 @@ exclude = ["**/tests/**", "**/examples/**", "**/benches/**", "**/target/**", "**
|
|||
[dependencies]
|
||||
mem_macros = "1.0.1"
|
||||
num-traits = "0.2.15"
|
||||
rosrust_msg = "0.1.7"
|
||||
fallible-iterator = "0.2.0"
|
||||
rosrust_msg = { version = "0.1.0", optional = true }
|
||||
rosrust = { version = "0.9.0", optional = true }
|
||||
|
||||
[features]
|
||||
rosrust_msg = ["dep:rosrust_msg", "dep:rosrust"]
|
||||
|
|
|
|||
85
README.md
85
README.md
|
|
@ -1,18 +1,25 @@
|
|||
# ROS PointCloud2
|
||||
|
||||
A Rust implementation for fast, safe and customizable conversions to and from the `sensor_msgs/PointCloud2` ROS message.
|
||||
A lightweight Rust implementation for fast, safe and customizable conversions to and from the `sensor_msgs/PointCloud2` ROS message.
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
ros_pointcloud2 = "0.2.0"
|
||||
```
|
||||
|
||||
Providing a fast and memory efficient way for message conversion while allowing user defined types without the cost of iterations.
|
||||
|
||||
*Currently only supports [rosrust_msg](https:://github.com/adnanademovic/rosrust) with ROS1.*
|
||||
Instead of converting the entire cloud into a `Vec`, you get an `Iterator` that converts each point from the message on the fly.
|
||||
An example for using this crate is [this filter node](https://github.com/stelzo/cloudfilter). It is also a good starting point for
|
||||
implementing ROS1 nodes in Rust inside a catkin environment.
|
||||
|
||||
To keep the crate a general purpose library for the problem and support ROS1 and ROS2, it uses its own type for the message.
|
||||
```rust
|
||||
use ros_pointcloud2::ConvertXYZ;
|
||||
use ros_pointcloud2::pcl_utils::PointXYZ;
|
||||
use ros_pointcloud2::ros_types::PointCloud2Msg;
|
||||
use ros_pointcloud2::fallible_iterator::FallibleIterator;
|
||||
|
||||
use rosrust_msg::sensor_msgs::PointCloud2;
|
||||
|
||||
// Your points (here using the predefined type PointXYZ).
|
||||
let cloud_points = vec. It is also a good starting point for
|
||||
implementing ROS1 nodes in Rust inside a catkin environment.
|
||||
To use `ros_pointcloud2` in your favorite ROS crate, you can either use this crate's features (see Integration section below) or implement the `Into` and `From` traits for `PointCloud2Msg`.
|
||||
|
||||
Please avoid cloning the `data: Vec<u8>` of the message.
|
||||
```rust
|
||||
use ros_pointcloud2::ros_types::PointCloud2Msg;
|
||||
|
||||
struct YourROSPointCloud2 {} // Likely to be generated by your ROS crate.
|
||||
|
||||
impl Into<YourROSPointCloud2> for PointCloud2Msg {
|
||||
fn into(self) -> YourROSPointCloud2 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<YourROSPointCloud2> for PointCloud2Msg {
|
||||
fn from(msg: YourROSPointCloud2) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Integrations
|
||||
|
||||
Currently, we only implement a conversion for the following ROS crate:
|
||||
- [rosrust](https://github.com/adnanademovic/rosrust)
|
||||
|
||||
You can use one by enabling the corresponding feature.
|
||||
```toml
|
||||
[dependencies]
|
||||
ros_pointcloud2 = { version = "0.2.0", features = ["rosrust_msg"]}
|
||||
```
|
||||
|
||||
Please open an issue or PR if you want to see support for other crates.
|
||||
|
||||
## Features
|
||||
|
||||
- Full support for `sensor_msgs/PointCloud2` messages
|
||||
- Custom types with `From` and `Into` traits
|
||||
- Easy to integrate into your favorite ROS1 or ROS2 crate
|
||||
- Custom point types
|
||||
- Predefined types for common conversions (compared to PCL)
|
||||
- PointXYZ
|
||||
- PointXYZI
|
||||
|
|
@ -55,27 +98,17 @@ implementing ROS1 nodes in Rust inside a catkin environment.
|
|||
- PointXYZNormal
|
||||
- PointXYZINormal
|
||||
- PointXYZRGBNormal
|
||||
- 2D and 3D support
|
||||
|
||||
## Usage
|
||||
|
||||
Add this to your Cargo.toml:
|
||||
```toml
|
||||
[dependencies]
|
||||
ros_pointcloud2 = "0.1.0"
|
||||
```
|
||||
|
||||
When building, the `rosrust_msg` crate needs to have the ROS environment sourced or use `ROSRUST_MSG_PATH=/opt/ros/$ROS_DISTRO/share cargo build`.
|
||||
- 2D and 3D
|
||||
|
||||
## Custom Types
|
||||
|
||||
You can freely convert to your own types without reiterating the entire cloud.
|
||||
You can freely convert to your own point types without reiterating the entire cloud.
|
||||
|
||||
You just need to implement the `Into` and `From` traits.
|
||||
```rust
|
||||
use ros_pointcloud2::mem_macros::size_of;
|
||||
use ros_pointcloud2::{Convert, MetaNames, PointMeta, ConversionError, PointConvertible};
|
||||
use rosrust_msg::sensor_msgs::PointCloud2;
|
||||
use ros_pointcloud2::ros_types::PointCloud2Msg;
|
||||
|
||||
const DIM : usize = 3;
|
||||
const METADIM : usize = 4;
|
||||
|
|
@ -135,15 +168,13 @@ let custom_cloud = vec![
|
|||
|
||||
|
||||
// Cloud -> ROS message
|
||||
let custom_msg: PointCloud2 = MyConverter::try_from(custom_cloud).unwrap().try_into().unwrap();
|
||||
let custom_msg: PointCloud2Msg = MyConverter::try_from(custom_cloud).unwrap().try_into().unwrap();
|
||||
|
||||
// ROS message -> Cloud
|
||||
let to_custom_type = MyConverter::try_from(custom_msg).unwrap();
|
||||
```
|
||||
|
||||
## Future Work
|
||||
- ROS2 support(!)
|
||||
- Removing rosrust dependency
|
||||
- Benchmark vs PCL
|
||||
- Proper error passing to the iterator result (currently merged into `PointConversionError`)
|
||||
- remove allocations
|
||||
|
|
|
|||
50
src/lib.rs
50
src/lib.rs
|
|
@ -1,8 +1,10 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
pub mod pcl_utils;
|
||||
pub mod ros_types;
|
||||
|
||||
use num_traits::Zero;
|
||||
use crate::pcl_utils::*;
|
||||
use crate::ros_types::{PointCloud2Msg, PointFieldMsg};
|
||||
|
||||
#[macro_use]
|
||||
pub extern crate mem_macros;
|
||||
|
|
@ -21,7 +23,7 @@ pub enum ConversionError {
|
|||
MetaIndexLengthMismatch,
|
||||
EndOfBuffer,
|
||||
PointConversionError,
|
||||
MetaDatatypeMissmatch,
|
||||
MetaDatatypeMismatch,
|
||||
}
|
||||
|
||||
/// Trait to convert a point to a tuple of coordinates and meta data.
|
||||
|
|
@ -120,7 +122,7 @@ fn convert_msg_code_to_type(code: u8) -> Result<FieldDatatype, ConversionError>
|
|||
}
|
||||
}
|
||||
|
||||
fn check_coord(coord: Option<usize>, fields: &Vec<rosrust_msg::sensor_msgs::PointField>, xyz_field_type: &FieldDatatype) -> Result<rosrust_msg::sensor_msgs::PointField, ConversionError> {
|
||||
fn check_coord(coord: Option<usize>, fields: &Vec<PointFieldMsg>, xyz_field_type: &FieldDatatype) -> Result<PointFieldMsg, ConversionError> {
|
||||
match coord {
|
||||
Some(y_idx) => {
|
||||
let field = &fields[y_idx];
|
||||
|
|
@ -149,7 +151,8 @@ pub trait MetaNames<const METADIM: usize> {
|
|||
/// # Example
|
||||
/// ```
|
||||
/// use ros_pointcloud2::mem_macros::size_of;
|
||||
/// use ros_pointcloud2::{Convert, PointMeta};;
|
||||
/// use ros_pointcloud2::{Convert, PointMeta};
|
||||
/// use ros_pointcloud2::ros_types::PointCloud2Msg;
|
||||
/// const DIM : usize = 3; // how many dimensions your point has (e.g. x, y, z)
|
||||
/// const METADIM : usize = 4; // how many meta fields you have (e.g. r, g, b, a)
|
||||
/// type MyConverter = Convert<f32, { size_of!(f32) }, DIM, METADIM, ([f32; DIM], [PointMeta; METADIM])>;
|
||||
|
|
@ -157,7 +160,7 @@ pub trait MetaNames<const METADIM: usize> {
|
|||
pub struct Convert<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C: PointConvertible<T, SIZE, DIM, METADIM>> {
|
||||
iteration: usize,
|
||||
coordinates: Vec<C>,
|
||||
_phantom: std::marker::PhantomData<T>,
|
||||
phantom_t: std::marker::PhantomData<T>,
|
||||
data: Vec<u8>,
|
||||
point_step_size: usize,
|
||||
cloud_length: usize,
|
||||
|
|
@ -199,7 +202,6 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use rosrust_msg::sensor_msgs::PointCloud2;
|
||||
/// use ros_pointcloud2::{ConvertXYZ, ConversionError};
|
||||
/// use ros_pointcloud2::pcl_utils::PointXYZ;
|
||||
///
|
||||
|
|
@ -228,7 +230,7 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
}
|
||||
|
||||
Ok(Self {
|
||||
_phantom: std::marker::PhantomData,
|
||||
phantom_t: std::marker::PhantomData,
|
||||
iteration: usize::zero(),
|
||||
coordinates: cloud,
|
||||
data: Vec::new(),
|
||||
|
|
@ -312,7 +314,7 @@ impl PointMeta {
|
|||
/// ```
|
||||
pub fn get<T: FromBytes>(&self) -> Result<T, ConversionError> {
|
||||
if self.datatype != T::field_datatype() {
|
||||
return Err(ConversionError::MetaDatatypeMissmatch);
|
||||
return Err(ConversionError::MetaDatatypeMismatch);
|
||||
}
|
||||
let size = datatype_size(&T::field_datatype());
|
||||
if let Some(bytes) = self.bytes.get(0..size) {
|
||||
|
|
@ -323,7 +325,7 @@ impl PointMeta {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C: PointConvertible<T, SIZE, DIM, METADIM>> TryFrom<rosrust_msg::sensor_msgs::PointCloud2> for Convert<T, SIZE, DIM, METADIM, C>
|
||||
impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C: PointConvertible<T, SIZE, DIM, METADIM>> TryFrom<PointCloud2Msg> for Convert<T, SIZE, DIM, METADIM, C>
|
||||
{
|
||||
type Error = ConversionError;
|
||||
|
||||
|
|
@ -333,7 +335,7 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
/// # Example
|
||||
/// Since we do not have a ROS node here, we first create a PointCloud2 message and then convert back to a Convert struct.
|
||||
/// ```
|
||||
/// use rosrust_msg::sensor_msgs::PointCloud2;
|
||||
/// use ros_pointcloud2::ros_types::PointCloud2Msg;
|
||||
/// use ros_pointcloud2::ConvertXYZ;
|
||||
/// use ros_pointcloud2::pcl_utils::PointXYZ;
|
||||
///
|
||||
|
|
@ -341,12 +343,13 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
/// PointXYZ { x: 1.0, y: 2.0, z: 3.0 },
|
||||
/// PointXYZ { x: 4.0, y: 5.0, z: 6.0 },
|
||||
/// ];
|
||||
/// let msg: PointCloud2 = ConvertXYZ::try_from(cloud_points).unwrap().try_into().unwrap();
|
||||
/// let msg: PointCloud2Msg = ConvertXYZ::try_from(cloud_points).unwrap().try_into().unwrap();
|
||||
///
|
||||
/// let convert: ConvertXYZ = ConvertXYZ::try_from(msg).unwrap(); // parse message
|
||||
/// ```
|
||||
fn try_from(cloud: rosrust_msg::sensor_msgs::PointCloud2) -> Result<Self, Self::Error> {
|
||||
if cloud.fields.len() < 2 {
|
||||
fn try_from(cloud: PointCloud2Msg) -> Result<Self, Self::Error> {
|
||||
let cloud: PointCloud2Msg = cloud.into();
|
||||
if cloud.fields.len() < DIM {
|
||||
return Err(ConversionError::NotEnoughFields);
|
||||
}
|
||||
|
||||
|
|
@ -433,7 +436,7 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
}
|
||||
|
||||
Ok(Self {
|
||||
_phantom: std::marker::PhantomData,
|
||||
phantom_t: std::marker::PhantomData,
|
||||
iteration: usize::zero(),
|
||||
coordinates: Vec::new(),
|
||||
data: cloud.data,
|
||||
|
|
@ -460,7 +463,7 @@ fn datatype_size(datatype: &FieldDatatype) -> usize {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C: PointConvertible<T, SIZE, DIM, METADIM>> TryInto<rosrust_msg::sensor_msgs::PointCloud2> for Convert<T, SIZE, DIM, METADIM, C> {
|
||||
impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C: PointConvertible<T, SIZE, DIM, METADIM>> TryInto<PointCloud2Msg> for Convert<T, SIZE, DIM, METADIM, C> {
|
||||
type Error = ConversionError;
|
||||
|
||||
/// Convert the point cloud to a ROS message.
|
||||
|
|
@ -469,7 +472,7 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use rosrust_msg::sensor_msgs::PointCloud2;
|
||||
/// use ros_pointcloud2::ros_types::PointCloud2Msg;
|
||||
/// use ros_pointcloud2::ConvertXYZ;
|
||||
/// use ros_pointcloud2::pcl_utils::PointXYZ;
|
||||
///
|
||||
|
|
@ -477,10 +480,10 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
/// PointXYZ { x: 1.0, y: 2.0, z: 3.0 },
|
||||
/// PointXYZ { x: 4.0, y: 5.0, z: 6.0 },
|
||||
/// ];
|
||||
/// let msg_out: PointCloud2 = ConvertXYZ::try_from(cloud_points).unwrap().try_into().unwrap();
|
||||
/// let msg_out: PointCloud2Msg = ConvertXYZ::try_from(cloud_points).unwrap().try_into().unwrap();
|
||||
/// ```
|
||||
fn try_into(self) -> Result<rosrust_msg::sensor_msgs::PointCloud2, Self::Error> {
|
||||
let mut cloud = rosrust_msg::sensor_msgs::PointCloud2::default();
|
||||
fn try_into(self) -> Result<PointCloud2Msg, Self::Error> {
|
||||
let mut cloud = PointCloud2Msg::default();
|
||||
|
||||
// Define the message fields
|
||||
let mut fields = Vec::new();
|
||||
|
|
@ -491,13 +494,13 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
let datatype: u8 = convert_to_msg_code(&self.xyz_field_type);
|
||||
|
||||
if DIM > 1 {
|
||||
fields.push(rosrust_msg::sensor_msgs::PointField {
|
||||
fields.push(PointFieldMsg {
|
||||
name: "x".to_string(),
|
||||
offset: 0 * SIZE as u32,
|
||||
datatype,
|
||||
count: 1,
|
||||
});
|
||||
fields.push(rosrust_msg::sensor_msgs::PointField {
|
||||
fields.push(PointFieldMsg {
|
||||
name: "y".to_string(),
|
||||
offset: 1 * SIZE as u32,
|
||||
datatype,
|
||||
|
|
@ -506,7 +509,7 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
}
|
||||
|
||||
if DIM == 3 {
|
||||
fields.push(rosrust_msg::sensor_msgs::PointField {
|
||||
fields.push(PointFieldMsg {
|
||||
name: "z".to_string(),
|
||||
offset: 2 * SIZE as u32,
|
||||
datatype,
|
||||
|
|
@ -534,7 +537,7 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
let field_size = datatype_size(&field_type);
|
||||
offset += field_size as u32;
|
||||
}
|
||||
fields.push(rosrust_msg::sensor_msgs::PointField {
|
||||
fields.push(PointFieldMsg {
|
||||
name: meta_names[idx].to_string(),
|
||||
offset,
|
||||
datatype,
|
||||
|
|
@ -582,8 +585,7 @@ impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C:
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C: PointConvertible<T, SIZE, DIM, METADIM>> fallible_iterator::FallibleIterator
|
||||
for Convert<T, SIZE, DIM, METADIM, C>
|
||||
impl<T: FromBytes, const SIZE: usize, const DIM: usize, const METADIM: usize, C: PointConvertible<T, SIZE, DIM, METADIM>> fallible_iterator::FallibleIterator for Convert<T, SIZE, DIM, METADIM, C>
|
||||
{
|
||||
type Item = C;
|
||||
type Error = ConversionError;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,146 @@
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct TimeMsg {
|
||||
pub sec: u32,
|
||||
pub nsec: u32,
|
||||
}
|
||||
|
||||
impl Default for TimeMsg {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
sec: 0,
|
||||
nsec: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct HeaderMsg {
|
||||
pub seq: u32,
|
||||
pub stamp: TimeMsg,
|
||||
pub frame_id: String,
|
||||
}
|
||||
|
||||
impl Default for HeaderMsg {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
seq: 0,
|
||||
stamp: TimeMsg::default(),
|
||||
frame_id: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PointFieldMsg {
|
||||
pub name: String,
|
||||
pub offset: u32,
|
||||
pub datatype: u8,
|
||||
pub count: u32,
|
||||
}
|
||||
|
||||
impl Default for PointFieldMsg {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: String::new(),
|
||||
offset: 0,
|
||||
datatype: 0,
|
||||
count: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PointCloud2Msg {
|
||||
pub header: HeaderMsg,
|
||||
pub height: u32,
|
||||
pub width: u32,
|
||||
pub fields: Vec<PointFieldMsg>,
|
||||
pub is_bigendian: bool,
|
||||
pub point_step: u32,
|
||||
pub row_step: u32,
|
||||
pub data: Vec<u8>,
|
||||
pub is_dense: bool,
|
||||
}
|
||||
|
||||
impl Default for PointCloud2Msg {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
header: HeaderMsg::default(),
|
||||
height: 0,
|
||||
width: 0,
|
||||
fields: Vec::new(),
|
||||
is_bigendian: false,
|
||||
point_step: 0,
|
||||
row_step: 0,
|
||||
data: Vec::new(),
|
||||
is_dense: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "rosrust_msg")]
|
||||
impl From<rosrust_msg::sensor_msgs::PointCloud2> for PointCloud2Msg {
|
||||
fn from(msg: rosrust_msg::sensor_msgs::PointCloud2) -> Self {
|
||||
Self {
|
||||
header: HeaderMsg {
|
||||
seq: msg.header.seq,
|
||||
stamp: TimeMsg {
|
||||
sec: msg.header.stamp.sec,
|
||||
nsec: msg.header.stamp.nsec,
|
||||
},
|
||||
frame_id: msg.header.frame_id,
|
||||
},
|
||||
height: msg.height,
|
||||
width: msg.width,
|
||||
fields: msg
|
||||
.fields
|
||||
.into_iter()
|
||||
.map(|field| PointFieldMsg {
|
||||
name: field.name,
|
||||
offset: field.offset,
|
||||
datatype: field.datatype,
|
||||
count: field.count,
|
||||
})
|
||||
.collect(),
|
||||
is_bigendian: msg.is_bigendian,
|
||||
point_step: msg.point_step,
|
||||
row_step: msg.row_step,
|
||||
data: msg.data,
|
||||
is_dense: msg.is_dense,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "rosrust_msg")]
|
||||
impl Into<rosrust_msg::sensor_msgs::PointCloud2> for PointCloud2Msg {
|
||||
fn into(self) -> rosrust_msg::sensor_msgs::PointCloud2 {
|
||||
rosrust_msg::sensor_msgs::PointCloud2 {
|
||||
header: rosrust_msg::std_msgs::Header {
|
||||
seq: self.header.seq,
|
||||
stamp: rosrust::Time {
|
||||
sec: self.header.stamp.sec,
|
||||
nsec: self.header.stamp.nsec,
|
||||
},
|
||||
frame_id: self.header.frame_id,
|
||||
},
|
||||
height: self.height,
|
||||
width: self.width,
|
||||
fields: self
|
||||
.fields
|
||||
.into_iter()
|
||||
.map(|field| rosrust_msg::sensor_msgs::PointField {
|
||||
name: field.name,
|
||||
offset: field.offset,
|
||||
datatype: field.datatype,
|
||||
count: field.count,
|
||||
})
|
||||
.collect(),
|
||||
is_bigendian: self.is_bigendian,
|
||||
point_step: self.point_step,
|
||||
row_step: self.row_step,
|
||||
data: self.data,
|
||||
is_dense: self.is_dense,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ fn custom_xyz_f32() {
|
|||
CustomPoint { x: 7.0, y: 8.0, z: 9.0 },
|
||||
];
|
||||
let copy = custom_cloud.clone();
|
||||
let custom_msg: Result<rosrust_msg::sensor_msgs::PointCloud2, _> = MyConverter::try_from(custom_cloud).unwrap().try_into();
|
||||
let custom_msg: Result<ros_pointcloud2::ros_types::PointCloud2Msg, _> = MyConverter::try_from(custom_cloud).unwrap().try_into();
|
||||
assert!(custom_msg.is_ok());
|
||||
let to_custom_type = MyConverter::try_from(custom_msg.unwrap());
|
||||
assert!(to_custom_type.is_ok());
|
||||
|
|
@ -94,7 +94,7 @@ fn custom_xyzi_f32() {
|
|||
CustomPoint { x: f32::MAX, y: f32::MIN, z: f32::MAX, i: u8::MAX },
|
||||
];
|
||||
let copy = custom_cloud.clone();
|
||||
let custom_msg: Result<rosrust_msg::sensor_msgs::PointCloud2, _> = MyConverter::try_from(custom_cloud).unwrap().try_into();
|
||||
let custom_msg: Result<ros_pointcloud2::ros_types::PointCloud2Msg, _> = MyConverter::try_from(custom_cloud).unwrap().try_into();
|
||||
assert!(custom_msg.is_ok());
|
||||
let to_custom_type = MyConverter::try_from(custom_msg.unwrap());
|
||||
assert!(to_custom_type.is_ok());
|
||||
|
|
@ -150,7 +150,7 @@ fn custom_rgba_f32() {
|
|||
CustomPoint { x: f32::MAX, y: f32::MIN, z: f32::MAX, r: u8::MAX, g: u8::MAX, b: u8::MAX, a: u8::MAX },
|
||||
];
|
||||
let copy = custom_cloud.clone();
|
||||
let custom_msg: Result<rosrust_msg::sensor_msgs::PointCloud2, _> = MyConverter::try_from(custom_cloud).unwrap().try_into();
|
||||
let custom_msg: Result<ros_pointcloud2::ros_types::PointCloud2Msg, _> = MyConverter::try_from(custom_cloud).unwrap().try_into();
|
||||
assert!(custom_msg.is_ok());
|
||||
let to_custom_type = MyConverter::try_from(custom_msg.unwrap());
|
||||
assert!(to_custom_type.is_ok());
|
||||
|
|
@ -169,7 +169,7 @@ fn converterxyz() {
|
|||
];
|
||||
|
||||
let copy = cloud.clone();
|
||||
let msg: Result<rosrust_msg::sensor_msgs::PointCloud2, _> = ConvertXYZ::try_from(cloud).unwrap().try_into();
|
||||
let msg: Result<ros_pointcloud2::ros_types::PointCloud2Msg, _> = ConvertXYZ::try_from(cloud).unwrap().try_into();
|
||||
assert!(msg.is_ok());
|
||||
let to_xyz_type = ConvertXYZ::try_from(msg.unwrap());
|
||||
assert!(to_xyz_type.is_ok());
|
||||
|
|
@ -189,7 +189,7 @@ fn converterxyzrgba() {
|
|||
];
|
||||
|
||||
let copy = cloud.clone();
|
||||
let msg: Result<rosrust_msg::sensor_msgs::PointCloud2, _> = ConvertXYZRGBA::try_from(cloud).unwrap().try_into();
|
||||
let msg: Result<ros_pointcloud2::ros_types::PointCloud2Msg, _> = ConvertXYZRGBA::try_from(cloud).unwrap().try_into();
|
||||
assert!(msg.is_ok());
|
||||
let to_xyzrgba_type = ConvertXYZRGBA::try_from(msg.unwrap());
|
||||
assert!(to_xyzrgba_type.is_ok());
|
||||
|
|
@ -208,7 +208,7 @@ fn converterxyzinormal() {
|
|||
];
|
||||
|
||||
let copy = cloud.clone();
|
||||
let msg: Result<rosrust_msg::sensor_msgs::PointCloud2, _> = ConvertXYZINormal::try_from(cloud).unwrap().try_into();
|
||||
let msg: Result<ros_pointcloud2::ros_types::PointCloud2Msg, _> = ConvertXYZINormal::try_from(cloud).unwrap().try_into();
|
||||
assert!(msg.is_ok());
|
||||
let to_xyzinormal_type = ConvertXYZINormal::try_from(msg.unwrap());
|
||||
assert!(to_xyzinormal_type.is_ok());
|
||||
|
|
@ -227,7 +227,7 @@ fn converterxyzrgbnormal() {
|
|||
];
|
||||
|
||||
let copy = cloud.clone();
|
||||
let msg: Result<rosrust_msg::sensor_msgs::PointCloud2, _> = ConvertXYZRGBNormal::try_from(cloud).unwrap().try_into();
|
||||
let msg: Result<ros_pointcloud2::ros_types::PointCloud2Msg, _> = ConvertXYZRGBNormal::try_from(cloud).unwrap().try_into();
|
||||
assert!(msg.is_ok());
|
||||
let to_xyzrgbnormal_type = ConvertXYZRGBNormal::try_from(msg.unwrap());
|
||||
assert!(to_xyzrgbnormal_type.is_ok());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
#[cfg(feature = "rosrust_msg")]
|
||||
#[test]
|
||||
fn convertxyz_rosrust_msg() {
|
||||
use ros_pointcloud2::{ConvertXYZ};
|
||||
use ros_pointcloud2::pcl_utils::PointXYZ;
|
||||
use ros_pointcloud2::ros_types::PointCloud2Msg;
|
||||
use ros_pointcloud2::fallible_iterator::FallibleIterator;
|
||||
|
||||
let cloud = vec![
|
||||
PointXYZ { x: 1.0, y: 2.0, z: 3.0 },
|
||||
PointXYZ { x: 4.0, y: 5.0, z: 6.0 },
|
||||
PointXYZ { x: 7.0, y: 8.0, z: 9.0 },
|
||||
];
|
||||
let copy = cloud.clone();
|
||||
let internal_cloud: PointCloud2Msg = ConvertXYZ::try_from(cloud).unwrap().try_into().unwrap();
|
||||
let rosrust_msg_cloud: rosrust_msg::sensor_msgs::PointCloud2 = internal_cloud.into();
|
||||
let convert_back_internal: PointCloud2Msg = rosrust_msg_cloud.into();
|
||||
let to_convert: ConvertXYZ = ConvertXYZ::try_from(convert_back_internal).unwrap();
|
||||
let back_to_type = to_convert.map(|point| Ok(point)).collect::<Vec<PointXYZ>>();
|
||||
assert_eq!(copy, back_to_type.unwrap());
|
||||
}
|
||||
Loading…
Reference in New Issue