Open TZECHIN6 opened 1 year ago
The problem might comes from the data layout:
fields:
- name: x
offset: 0
datatype: 7
count: 1
- name: y
offset: 4
datatype: 7
count: 1
- name: z
offset: 8
datatype: 7
count: 1
- name: intensity
offset: 16
datatype: 7
count: 1
- name: t
offset: 20
datatype: 6
count: 1
- name: reflectivity
offset: 24
datatype: 4
count: 1
- name: ring
offset: 26
datatype: 4
count: 1
- name: ambient
offset: 28
datatype: 4
count: 1
- name: range
offset: 32
datatype: 6
count: 1
Point cloud data layout is defined here: https://autowarefoundation.github.io/autoware-documentation/main/design/autoware-architecture/sensing/data-types/point-cloud/#point-cloud-fields
Which is now implemented here: https://github.com/tier4/nebula/blob/main/nebula_common/include/nebula_common/point_types.hpp
struct PointXYZIRCAEDT
{
float x;
float y;
float z;
std::uint8_t intensity;
std::uint8_t return_type;
std::uint16_t channel;
float azimuth;
float elevation;
float distance;
std::uint32_t time_stamp;
};
As you can see, the layout is not exactly the same. There are some fields you don't have, and some you have that don't exist.
Unfortunately, the new nebula module seems not to support Ouster Lidar (yet), so you need to modify the driver you have (or add a conversion node) so you get the same fields than above.
Not all fields are equaly important. The most important are 'x', 'y', 'z' and 'time_stamp'. In your case you have a time field, but it is named 't'. You should also check what is the format used by this field and make sure it is what Autoware expect. AFAIK, 'channel', 'azimuth' and 'distance' are only used by the ring outlier filter (which is not that important so you could remove it), and the other fields are not used.
Thanks for the guidance, I will try modify the driver to match the data field.
Sorry but i have a question about 'channel', 'azimuth' and 'distance' are only used by the ring outlier filter
, as I saw the graph saying each node input points msg are all required XYZIRC
, channel seem cannot be ignored. Also, for the first cropbox filter node, XYZIRCADT
points is needed, does this mean I have to prepare all data field at the very beginning?
If i have three lidars combo, left-right velodyne lidar and top ouster lidar, whats the least required field to directly pass ouster lidar points to Cloud Transformer
and Cloud Concatenator
?
It is better to follow the expected format. That said, if you remove the ring outlier filter, I think you can fill fields you don't have with 0.
Understood. I am trying to work on that now
This pull request has been automatically marked as stale because it has not had recent activity.
@TZECHIN6 may I please ask if you managed to overcome this issue? I am facing the same issue and I believe it comes from the field type differences.
Currently, I don't have an ouster lidar with me. I will resume this integration task once I borrow one from the University.
In the meantime, you could check this out to see the difference between the published pointcloud type structure link.
Remark: there is no nubela driver when at the time I use autoware, so things might change right now.
@isouf
https://github.com/ouster-lidar/ouster-ros/issues/217
actually I have asked related question in ouster's repository, and seem they have merged a feature to allow selecting different presentation of point cloud type.
Please have a look at here: https://github.com/ouster-lidar/ouster-ros/pull/216
I haven't checked it out in detail. I will come back for this after receiving the lidar.
@isouf Great to hear from you about that. Actually I do not have experience on formatting the point cloud type before, would you mind sharing a bit how you able to do such transform? I would be very appreciated.
@TZECHIN6 Here is the "quick" method that I made to convert the pointcloud format. Any improvement recommendations are welcomed.
// Receive the pointcloud from ouster lidar and change the format of the message so that it matches
// the format the is used in autoware pointcloud_preprocessor filters
void PointcloudFormatAdaptorNode::onPointcloud(
const sensor_msgs::msg::PointCloud2::ConstSharedPtr pcd)
{
// Initiate output messages
auto pointcloud_msg = std::make_shared<sensor_msgs::msg::PointCloud2>();
// Initiate pcl pointcloud message for the input point cloud
pcl::PointCloud<pointcloud_format_adaptor::PointXYZITRRAR>::Ptr input_pointcloud(
new pcl::PointCloud<pointcloud_format_adaptor::PointXYZITRRAR>);
// Convert ros to pcl
pcl::fromROSMsg(*pcd, *input_pointcloud);
// Initiate pcl pointcloud message for the input point cloud
pcl::PointCloud<nebula::drivers::PointXYZIRADT>::Ptr output_pointcloud(
new pcl::PointCloud<nebula::drivers::PointXYZIRADT>);
output_pointcloud->reserve(input_pointcloud->points.size());
// Convert pcl ouster to pcl autoware
nebula::drivers::PointXYZIRADT point{};
for (const auto & p : input_pointcloud->points) {
point.x = p.x;
point.y = p.y;
point.z = p.z;
point.intensity = p.intensity;
point.return_type = 0;
point.ring = p.ring;
point.azimuth = std::atan2(p.y, p.x);
point.distance = p.range;
point.time_stamp = p.t;
output_pointcloud->points.emplace_back(point);
}
output_pointcloud->header = input_pointcloud->header;
output_pointcloud->height = 1;
output_pointcloud->width = output_pointcloud->points.size();
// Convert pcl to ros
pcl::toROSMsg(*output_pointcloud, *pointcloud_msg);
// Publish updated pointcloud message
pub_pcd_->publish(*pointcloud_msg);
}
The PointXYZITRRAR
point type is defined on a separate header file as follows:
struct PointXYZITRRAR
{
float x;
float y;
float z;
float intensity;
std::uint32_t t;
std::uint16_t reflectivity;
std::uint16_t ring;
std::uint16_t ambient;
uint32_t range;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
@isouf Thanks for your sharing! I will definitely have a look about it.
If there is any update or improvement I have made, I will let you know for sure.
Might I ask which ouster driver have you used for the raw point cloud?
@TZECHIN6 the official ROS2 driver: https://github.com/ouster-lidar/ouster-ros/tree/ros2
This pull request has been automatically marked as stale because it has not had recent activity.
@isouf Thanks for you sharing! Quick question, where in the autoware.universe code do you add this node and how do you run this node?
@isouf To follow up my last questions. Cause I'm using Ouster LiDAR with the following topic: However, autoware requires the following topic:
So, where in the autoware.universe code do you integrate the converter node?
@DarrenQu you will need to replace the default Velodyne drivers with Ouster and then feed the PointCloud2
message (output of Ouster drivers) directly to the pointcloud_preprocessos
.
@isouf Could you perhaps share what you lidar.launch.xml file looks like? I have incorporated a node that changes the format from ouster to autoware, and I have confirmed that it is outputting data in the correct format. I changed the input topics in pointcloud_preprocessor.launch.py to the output topic of my converter node, but I am still not getting any output from /sensing/lidar/concantenated/pointcloud
@DarrenQu you will need to replace the default Velodyne drivers with Ouster and then feed the
PointCloud2
message (output of Ouster drivers) directly to thepointcloud_preprocessos
.
@isouf if I directly pass the raw pointcloud from the modified driver to the pointcloud_proprocessors like the way you did, then what the nebula driver does? as seem like the raw pointcloud should firstly be published to the cropbox filter...outlier ring filter, then concatenated at the end. Right now seem it bypass all those preprocess steps.
@TZECHIN6 The point type that autoware expects is now this one https://github.com/autowarefoundation/autoware.universe/blob/14fa0f3692551ec6af460284537473c5c9be6d66/common/autoware_point_types/include/autoware_point_types/types.hpp#L95 So you may need to take extra steps
@TZECHIN6
The point type that autoware expects is now this one
So you may need to take extra steps
@knzo25 thanks for the update! I have switched to Livox lidar recently, and successfully publish the required point cloud structure after modifying the official driver.
However when blocking me now is the integration to the point cloud preprocessing component container nodes, I have posted a question about it in the discussion https://github.com/orgs/autowarefoundation/discussions/5048
I know it's a bit off the topic of this issue.
I've adapted the method from @isouf a bit for the current Autoware PointXYZIRCAEDT point type and built a package around it so that one can directly use a composable node to subscribe to the PointCloud from the Ouster driver and provide the output to the Crop Box Filter (and the Autoware point cloud preprocessing pipeline): https://github.com/FranzAlbers/ouster_point_type_adapter
Checklist
Description
I would like to integrate my ouster lidar (os-1 64 beam I believe) into autoware.universe project. However, I am having trouble to get the pointcloud data after the preprocessing node.
I first tried to pass the raw point cloud into the self cropped box node as below:
The output topic of /sensing/lidar/top/self_cropped/pointcloud has no response.
At this point, the issue might caused by the missing of required data field, thus I tried to just directly pass into
concatenate_data
as below:Sadly, no luck for me to see the pointcloud at topic
/sensing/lidar/concatenated/pointcloud
...I have checked the raw points topic
/ouster/points
, and ensure it has data output and can be seen in rviz.This is the tf qraph: frames_2023-09-13_17.16.22.pdf
It shows ouster_top do have a tf tree connect with base_link. So at this point I am not so sure how to fix the issue. And asking for help in here. Thanks to all who have paid kind attention to this.
Expected behavior
Able to use official ros2 ouster driver to launch ouster lidar and use it's outputed points in Autoware with preprocessing node.
Actual behavior
Error message capture from the console:
Right now I cannot review points from either
/sensing/lidar/top/self_cropped/pointcloud
or/sensing/lidar/concatenated/pointcloud
.Steps to reproduce
update the config of ouster driver launch as below: