Skip to content
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
dcfd2b7
Update maintaner name in streampetr
KSeangTan Feb 16, 2026
22ef15e
Merge branch 'main' of github.com:KSeangTan/autoware_universe
KSeangTan Feb 16, 2026
9560c59
Update maintaner name in streampetr
KSeangTan Feb 16, 2026
2853bbd
Merge branch 'autowarefoundation:main' into main
KSeangTan Feb 17, 2026
51d98be
Merge branch 'autowarefoundation:main' into main
KSeangTan Feb 27, 2026
b251476
Merge branch 'autowarefoundation:main' into main
KSeangTan Mar 2, 2026
27214b9
Merge branch 'autowarefoundation:main' into main
KSeangTan Mar 3, 2026
01ee3d0
Merge branch 'autowarefoundation:main' into main
KSeangTan Mar 4, 2026
062c6b6
Merge branch 'autowarefoundation:main' into main
KSeangTan Mar 5, 2026
9998c05
Merge branch 'autowarefoundation:main' into main
KSeangTan Mar 6, 2026
eed5473
Merge branch 'autowarefoundation:main' into main
KSeangTan Mar 9, 2026
66e4c98
Merge branch 'autowarefoundation:main' into main
KSeangTan Mar 11, 2026
e000ea5
Add camera_data to bevfusion
KSeangTan Mar 11, 2026
8332d94
Update CMakeList in bevfusion
KSeangTan Mar 11, 2026
a51e3ed
Update CMakeList in bevfusion
KSeangTan Mar 11, 2026
68f32a1
Add camera_data in bevfusion
KSeangTan Mar 11, 2026
da57f46
Add camera_data in bevfusion
KSeangTan Mar 11, 2026
6e66a55
Add camera_data in bevfusion
KSeangTan Mar 12, 2026
d0c7f19
Add camera_data in bevfusion
KSeangTan Mar 12, 2026
82cb665
Add camera_data in bevfusion
KSeangTan Mar 12, 2026
4fdca91
Add camera_matrices in bevfusion
KSeangTan Mar 12, 2026
1b0b95b
Add camera_matrices in bevfusion
KSeangTan Mar 12, 2026
191ab67
Add undistrotion_image_buffer_d_ in bevfusion
KSeangTan Mar 12, 2026
051e692
Fix json schema in bevfusion
KSeangTan Mar 12, 2026
5506a37
Merge branch 'main' into feat/add_undistortion_to_bevfusion_camera
KSeangTan Mar 12, 2026
7436d81
Fix json schema in bevfusion
KSeangTan Mar 12, 2026
6e2bc5a
Resolve double deletion
KSeangTan Mar 12, 2026
f800394
Convert tabs to spaces
KSeangTan Mar 12, 2026
aa8ac26
Merge branch 'main' into feat/add_undistortion_to_bevfusion_camera
KSeangTan Mar 13, 2026
b69d6ed
Merge branch 'main' into feat/add_undistortion_to_bevfusion_camera
KSeangTan Mar 13, 2026
96d3f8f
Convert tabs to spaces
KSeangTan Mar 13, 2026
3f33721
Merge branch 'main' into feat/add_undistortion_to_bevfusion_camera
KSeangTan Mar 17, 2026
c5074e7
Merge branch 'main' into feat/add_undistortion_to_bevfusion_camera
KSeangTan Mar 25, 2026
2ebce5c
Merge branch 'autowarefoundation:main' into main
KSeangTan Mar 27, 2026
b27adaa
Merge branch 'main' into feat/add_undistortion_to_bevfusion_camera
KSeangTan Mar 27, 2026
6055c69
Remove flip_image_channels
KSeangTan Mar 27, 2026
43c7028
Remove flip_image_channels
KSeangTan Mar 27, 2026
c8abebf
Remove lib/camera_matrices.cpp
KSeangTan Mar 27, 2026
302eef7
Add sanity check to check input image shape and ImagePreProcessingPar…
KSeangTan Mar 27, 2026
9337210
Add sanity check to check input image shape and ImagePreProcessingPar…
KSeangTan Mar 27, 2026
669ad9b
Update error message
KSeangTan Mar 27, 2026
33c3331
Add CHECK_CUDA_ERROR for cuda function
KSeangTan Mar 27, 2026
3507a58
Add checkImageCameraMatricesReady and check sensor_fusion before proc…
KSeangTan Mar 27, 2026
bcbb6dc
Add checkImageCameraMatricesReady and check sensor_fusion before proc…
KSeangTan Mar 27, 2026
ded3664
Remove cv_bridge and opencv hpp
KSeangTan Mar 27, 2026
a904e4c
Merge branch 'main' into feat/add_undistortion_to_bevfusion_camera
KSeangTan Mar 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions perception/autoware_bevfusion/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ if(TRT_AVAIL AND CUDA_AVAIL AND SPCONV_AVAIL)
lib/postprocess/circle_nms_kernel.cu
lib/postprocess/postprocess_kernel.cu
lib/preprocess/preprocess_kernel.cu
lib/camera/camera_preprocess_kernel.cu
)

target_link_libraries(${PROJECT_NAME}_cuda_lib
Expand All @@ -120,6 +121,8 @@ if(TRT_AVAIL AND CUDA_AVAIL AND SPCONV_AVAIL)
lib/preprocess/precomputed_features.cpp
lib/ros_utils.cpp
lib/bevfusion_trt.cpp
lib/camera/camera_matrices.cpp
lib/camera/camera_data.cpp
)

target_compile_definitions(${PROJECT_NAME}_lib PRIVATE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# pre-process params
densification_num_past_frames: 1
densification_world_frame_id: map
run_image_undistortion: true

# post-process params
circle_nms_dist_threshold: 0.5
iou_nms_search_distance_2d: 10.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# pre-process params
densification_num_past_frames: 1
densification_world_frame_id: map
run_image_undistortion: false

# post-process params
circle_nms_dist_threshold: 0.5
iou_nms_search_distance_2d: 10.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
features_width: 72
num_depth_features: 95
image_feature_channel: 256
flip_image_channels: true
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
features_width: 0
num_depth_features: 0
image_feature_channel: 0
flip_image_channels: false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as previous comment, but let's keep this comment with memo:

This comment can be only resolved if maintainer provide link to awf/autoware PR with updated artifacts.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check the comment above, I have removed the parameter here:

6055c69
43c7028

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define AUTOWARE__BEVFUSION__BEVFUSION_NODE_HPP_

#include "autoware/bevfusion/bevfusion_trt.hpp"
#include "autoware/bevfusion/camera/camera_data.hpp"
#include "autoware/bevfusion/detection_class_remapper.hpp"
#include "autoware/bevfusion/postprocess/non_maximum_suppression.hpp"
#include "autoware/bevfusion/preprocess/pointcloud_densification.hpp"
Expand Down Expand Up @@ -67,7 +68,8 @@ class BEVFUSION_PUBLIC BEVFusionNode : public rclcpp::Node
void diagnoseProcessingTime(diagnostic_updater::DiagnosticStatusWrapper & stat);

// Helper methods for constructor
void initializeSensorFusionSubscribers(std::int64_t num_cameras);
void initializeSensorFusionSubscribers(
std::int64_t num_cameras, const ImagePreProcessingParams & image_pre_processing_params);
void validateParameters(
const std::vector<float> & point_cloud_range, const std::vector<float> & voxel_size);

Expand Down Expand Up @@ -100,6 +102,11 @@ class BEVFUSION_PUBLIC BEVFusionNode : public rclcpp::Node
std::vector<rclcpp::Subscription<sensor_msgs::msg::CameraInfo>::ConstSharedPtr> camera_info_subs_;
rclcpp::Publisher<autoware_perception_msgs::msg::DetectedObjects>::SharedPtr objects_pub_{
nullptr};
// unique_ptr to avoid copying the actual camera data in memory since there's gpu buffer in the
// camera data
std::vector<std::unique_ptr<CameraData>> camera_data_ptrs_;
// One CameraMatrices object can be shared by several CameraData
std::vector<std::shared_ptr<CameraMatrices>> camera_matrices_ptrs_;

tf2_ros::Buffer tf_buffer_;
tf2_ros::TransformListener tf_listener_{tf_buffer_};
Expand All @@ -109,9 +116,7 @@ class BEVFUSION_PUBLIC BEVFusionNode : public rclcpp::Node
std::optional<std::string> lidar_frame_;
float max_camera_lidar_delay_;

std::vector<sensor_msgs::msg::Image::ConstSharedPtr> image_msgs_;
std::vector<float> camera_masks_;
std::vector<std::optional<sensor_msgs::msg::CameraInfo>> camera_info_msgs_;
std::vector<std::optional<Matrix4f>> lidar2camera_extrinsics_;

bool sensor_fusion_{false};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef AUTOWARE__BEVFUSION__BEVFUSION_TRT_HPP_
#define AUTOWARE__BEVFUSION__BEVFUSION_TRT_HPP_

#include "autoware/bevfusion/camera/camera_data.hpp"
#include "autoware/bevfusion/postprocess/postprocess_kernel.hpp"
#include "autoware/bevfusion/preprocess/pointcloud_densification.hpp"
#include "autoware/bevfusion/preprocess/preprocess_kernel.hpp"
Expand Down Expand Up @@ -87,7 +88,7 @@ class BEVFUSION_PUBLIC BEVFusionTRT

bool detect(
const std::shared_ptr<const cuda_blackboard::CudaPointCloud2> & input_pointcloud_msg_ptr,
const std::vector<sensor_msgs::msg::Image::ConstSharedPtr> & image_msgs,
const std::vector<std::unique_ptr<CameraData>> & camera_data_ptrs,
const std::vector<float> & camera_masks, const tf2_ros::Buffer & tf_buffer,
std::vector<Box3D> & det_boxes3d, std::unordered_map<std::string, double> & proc_timing,
bool & is_num_voxels_within_range);
Expand All @@ -102,7 +103,7 @@ class BEVFUSION_PUBLIC BEVFusionTRT

bool preProcess(
const std::shared_ptr<const cuda_blackboard::CudaPointCloud2> & pc_msg_ptr,
const std::vector<sensor_msgs::msg::Image::ConstSharedPtr> & image_msgs,
const std::vector<std::unique_ptr<CameraData>> & camera_data_ptrs,
const std::vector<float> & camera_masks, const tf2_ros::Buffer & tf_buffer,
bool & is_num_voxels_within_range);

Expand All @@ -112,7 +113,7 @@ class BEVFUSION_PUBLIC BEVFusionTRT
void clearDeviceMemory();

void processImages(
const std::vector<sensor_msgs::msg::Image::ConstSharedPtr> & image_msgs,
const std::vector<std::unique_ptr<CameraData>> & camera_data_ptrs,
const std::vector<float> & camera_masks);

std::int64_t processPointCloudVoxelization(
Expand Down Expand Up @@ -140,7 +141,6 @@ class BEVFUSION_PUBLIC BEVFusionTRT
std::unique_ptr<PreprocessCuda> pre_ptr_{nullptr};
std::unique_ptr<PostprocessCuda> post_ptr_{nullptr};
cudaStream_t stream_{nullptr};
std::vector<cudaStream_t> camera_streams_{};

BEVFusionConfig config_;
std::vector<int> roi_start_y_vector_;
Expand Down Expand Up @@ -171,7 +171,6 @@ class BEVFUSION_PUBLIC BEVFusionTRT

// image buffers
CudaUniquePtr<std::uint8_t[]> roi_tensor_d_{nullptr};
std::vector<CudaUniquePtr<std::uint8_t[]>> image_buffers_d_{};
CudaUniquePtr<float[]> camera_masks_d_{nullptr};

// image feature buffers for fusion model
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2026 TIER IV
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef AUTOWARE__BEVFUSION__CAMERA__CAMERA_DATA_HPP_
#define AUTOWARE__BEVFUSION__CAMERA__CAMERA_DATA_HPP_

#include "autoware/bevfusion/camera/camera_matrices.hpp"
#include "autoware/bevfusion/camera/camera_preprocess.hpp"

#include <autoware/cuda_utils/cuda_check_error.hpp>
#include <autoware/cuda_utils/cuda_unique_ptr.hpp>
#include <rclcpp/rclcpp.hpp>

#include <sensor_msgs/msg/camera_info.hpp>
#include <sensor_msgs/msg/compressed_image.hpp>
#include <sensor_msgs/msg/image.hpp>

#include <memory>
#include <string>

namespace autoware::bevfusion
{
using autoware::cuda_utils::CudaUniquePtr;

struct ImagePreProcessingParams
{
std::int64_t original_image_height;
std::int64_t original_image_width;
std::int64_t roi_height;
std::int64_t roi_width;
float image_aug_scale_y;
float image_aug_scale_x;
bool run_image_undistortion;
bool flip_image_channels;
std::int64_t crop_height;
std::int64_t crop_width;
std::int64_t resized_height;
std::int64_t resized_width;
std::int64_t roi_start_y;
std::int64_t roi_start_x;

ImagePreProcessingParams(
const std::int64_t original_image_height, const std::int64_t original_image_width,
const std::int64_t roi_height, const std::int64_t roi_width, const float image_aug_scale_y,
const float image_aug_scale_x, const bool run_image_undistortion,
const bool flip_image_channels);
};

class CameraData
{
public:
CameraData(
rclcpp::Node * node, const int camera_id,
const ImagePreProcessingParams & image_pre_processing_params,
const std::shared_ptr<CameraMatrices> & camera_matrices_ptr);
~CameraData();

void update_image_msg(const sensor_msgs::msg::Image::ConstSharedPtr & input_camera_image_msg);
void update_camera_info(const sensor_msgs::msg::CameraInfo & input_camera_info_msg);
std::optional<sensor_msgs::msg::CameraInfo> camera_info() const;
sensor_msgs::msg::CameraInfo camera_info_value() const;

sensor_msgs::msg::Image::ConstSharedPtr image_msg() const;
bool is_image_msg_available() const;
bool is_camera_info_available() const;
std::size_t output_img_offset() const;

void preprocess_image(std::uint8_t * output_img);
bool is_camera_matrices_ready() const;
cudaError_t sync_cuda_stream();

private:
// Camera info buffer
std::optional<sensor_msgs::msg::CameraInfo> camera_info_;

// Image buffer
// TODO(KokSeang): Remove this once we move preprocessing to subscribers
sensor_msgs::msg::Image::ConstSharedPtr image_msg_;

// GPU Memory for preprocessed image
// image buffers
CudaUniquePtr<std::uint8_t[]> image_buffer_d_{nullptr};
CudaUniquePtr<std::uint8_t[]> undistorted_image_buffer_d_{nullptr};

rclcpp::Logger logger_;
int camera_id_;
ImagePreProcessingParams image_pre_processing_params_;
std::size_t output_img_offset_;

cudaStream_t stream_{nullptr};
std::unique_ptr<CameraPreprocess> camera_preprocess_ptr_{nullptr};
std::shared_ptr<CameraMatrices> camera_matrices_ptr_{nullptr};
};
} // namespace autoware::bevfusion
#endif // AUTOWARE__BEVFUSION__CAMERA__CAMERA_DATA_HPP_
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2026 TIER IV
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef AUTOWARE__BEVFUSION__CAMERA__CAMERA_MATRICES_HPP_
#define AUTOWARE__BEVFUSION__CAMERA__CAMERA_MATRICES_HPP_

#include <autoware/cuda_utils/cuda_unique_ptr.hpp>

#include <sensor_msgs/msg/camera_info.hpp>

#if __has_include(<cv_bridge/cv_bridge.hpp>)
#include <cv_bridge/cv_bridge.hpp>
#else
#include <cv_bridge/cv_bridge.h>
#endif
#include <opencv2/opencv.hpp>

namespace autoware::bevfusion
{
using autoware::cuda_utils::CudaUniquePtr;

// Helper struct for camera matrices
struct CameraMatrices
{
cv::Mat K;
cv::Mat D;
cv::Mat P;
int map_width;
int map_height;
bool matrices_ready{false};

// GPU Memory for undistortion maps and they only need to be computed once for each camera
CudaUniquePtr<float[]> undistorted_map_x_d_{nullptr};
CudaUniquePtr<float[]> undistorted_map_y_d_{nullptr};

CameraMatrices();
void update_camera_matrices(const sensor_msgs::msg::CameraInfo & camera_info);
void compute_undistorted_map_x_y();
};
} // namespace autoware::bevfusion
#endif // AUTOWARE__BEVFUSION__CAMERA__CAMERA_MATRICES_HPP_
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2026 TIER IV
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef AUTOWARE__BEVFUSION__CAMERA__CAMERA_PREPROCESS_HPP_
#define AUTOWARE__BEVFUSION__CAMERA__CAMERA_PREPROCESS_HPP_

#include "autoware/bevfusion/utils.hpp"

#include <autoware/cuda_utils/cuda_check_error.hpp>

#include <cstdint>

namespace autoware::bevfusion
{

class CameraPreprocess
{
public:
CameraPreprocess(cudaStream_t stream, const int camera_id);
~CameraPreprocess();

cudaError_t resizeAndExtractRoi_launch(
const std::uint8_t * input_img, std::uint8_t * output_img, int H,
int W, // Original image dimensions
int H2, int W2, // Resized image dimensions
int H3, int W3, // ROI dimensions
int y_start, int x_start, // ROI top-left coordinates in resized image
bool flip_image_channels // Set to True if the image channels are to be flipped, for example,
// BGR to RGB
);
cudaError_t remap_launch(
const std::uint8_t * input_img, std::uint8_t * output_img, int output_height,
int output_width, // Output (destination) image dimensions
int input_height, int input_width, // Input (source) image dimensions
const float * map_x, const float * map_y);

private:
cudaStream_t stream_;
int camera_id_;
};
} // namespace autoware::bevfusion
#endif // AUTOWARE__BEVFUSION__CAMERA__CAMERA_PREPROCESS_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ class PreprocessCuda
const float * points, unsigned int points_size, float * voxel_features,
std::int32_t * voxel_coords, std::int32_t * num_points_per_voxel);

cudaError_t resizeAndExtractRoi_launch(
const std::uint8_t * input_img, std::uint8_t * output_img, int H, int W, int H2, int W2, int H3,
int W3, int y_start, int x_start, cudaStream_t stream);

private:
BEVFusionConfig config_;
cudaStream_t stream_;
Expand Down
24 changes: 12 additions & 12 deletions perception/autoware_bevfusion/launch/bevfusion.launch.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,18 @@
<param from="$(var class_remapper_param_path)"/>
<param from="$(var common_param_path)"/>

<remap from="~/input/camera_info0" to="$(var camera_info0)"/>
<remap from="~/input/camera_info1" to="$(var camera_info1)"/>
<remap from="~/input/camera_info2" to="$(var camera_info2)"/>
<remap from="~/input/camera_info3" to="$(var camera_info3)"/>
<remap from="~/input/camera_info4" to="$(var camera_info4)"/>
<remap from="~/input/camera_info5" to="$(var camera_info5)"/>
<remap from="~/input/image0" to="$(var image0)"/>
<remap from="~/input/image1" to="$(var image1)"/>
<remap from="~/input/image2" to="$(var image2)"/>
<remap from="~/input/image3" to="$(var image3)"/>
<remap from="~/input/image4" to="$(var image4)"/>
<remap from="~/input/image5" to="$(var image5)"/>
<remap from="~/input/camera_info0" to="$(var bevfusion_camera_info0)"/>
<remap from="~/input/camera_info1" to="$(var bevfusion_camera_info1)"/>
<remap from="~/input/camera_info2" to="$(var bevfusion_camera_info2)"/>
<remap from="~/input/camera_info3" to="$(var bevfusion_camera_info3)"/>
<remap from="~/input/camera_info4" to="$(var bevfusion_camera_info4)"/>
<remap from="~/input/camera_info5" to="$(var bevfusion_camera_info5)"/>
<remap from="~/input/image0" to="$(var bevfusion_image0)"/>
<remap from="~/input/image1" to="$(var bevfusion_image1)"/>
<remap from="~/input/image2" to="$(var bevfusion_image2)"/>
<remap from="~/input/image3" to="$(var bevfusion_image3)"/>
<remap from="~/input/image4" to="$(var bevfusion_image4)"/>
<remap from="~/input/image5" to="$(var bevfusion_image5)"/>
<param name="use_compressed_images" value="$(var use_compressed_images)"/>
<!-- This parameter shall NOT be included in param file. See also: https://github.com/autowarefoundation/autoware.universe/pull/6167 -->
<param name="build_only" value="$(var build_only)"/>
Expand Down
Loading
Loading