Skip to content

feat: migrate code from ros1 to ros2#1

Open
sujit-168 wants to merge 1 commit intomainfrom
ros2
Open

feat: migrate code from ros1 to ros2#1
sujit-168 wants to merge 1 commit intomainfrom
ros2

Conversation

@sujit-168
Copy link
Copy Markdown

feat: migrate FAST-Calib from ROS1 to ROS2 (Jazzy/Humble)

This PR migrates the FAST-Calib project from ROS1 to ROS2, following the architectural patterns and technology stack used in FAST-LIVO2. The migration ensures compatibility with modern ROS2 distributions (tested on ROS2 Jazzy).

Key Changes

1. Build System

  • package.xml: Updated to format 3 and replaced ROS1 dependencies with ROS2 equivalents (rclcpp, tf2_ros, sensor_msgs, livox_ros_driver2, rosbag2_cpp, etc.).
  • CMakeLists.txt: Converted to ament_cmake build system and updated library linking for ROS2.

2. Core Code Migration

  • Node Structure: Refactored main.cpp and all headers to use the ROS2 node structure and shared pointers.
  • Parameters: Migrated parameter handling to the modern ROS2 declare/get pattern.
  • Logging: Replaced ROS_INFO/WARN/ERROR macros with RCLCPP logging macros.

3. Library & Header Fixes

  • PCL & cv_bridge: Updated headers for ROS2 Jazzy/Humble compatibility.
  • OpenCV: Replaced deprecated cv::aruco::drawAxis with cv::drawFrameAxes for OpenCV 4.x compatibility.

4. Data Processing

  • Rosbag2 Support: Updated data_preprocess.hpp to support reading point cloud data from ROS2 bag files using rosbag2_cpp.

5. Launch & Configuration

  • Launch: Added calib.launch.py (ROS2 Python launch file).
  • Params: Updated qr_params.yaml to the required ROS2 hierarchical format.

Verification

  • Built successfully using colcon build --packages-select fast_calib in a ROS2 Jazzy environment.
  • Verified that all dependencies (including livox_ros_driver2) are correctly linked and available.

@sujit-168 sujit-168 self-assigned this Dec 28, 2025
Copilot AI review requested due to automatic review settings December 28, 2025 15:28
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates the FAST-Calib calibration system from ROS1 to ROS2 (Jazzy/Humble), updating the build system, core APIs, and all dependencies to their ROS2 equivalents.

  • Converted build system from catkin to ament_cmake with updated package format
  • Migrated core node structure to use rclcpp with shared pointers and modern parameter handling
  • Updated rosbag reading to use rosbag2_cpp API with support for both Livox CustomMsg and standard PointCloud2 formats

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
package.xml Upgraded to format 3 with ROS2 dependencies (rclcpp, tf2_ros, livox_ros_driver2, rosbag2_cpp)
CMakeLists.txt Converted to ament_cmake build system with ROS2 find_package and installation patterns
src/main.cpp Updated to use rclcpp node initialization, shared pointers, ROS2 publishers, and spin patterns
src/qr_detect.hpp Migrated to rclcpp publishers, updated OpenCV aruco API, added ROS2-compatible cv_bridge include guards
src/lidar_detect.hpp Updated to use rclcpp publishers and ROS2 message types for point cloud publishing
src/data_preprocess.hpp Implemented rosbag2_cpp reader with deserialization for Livox CustomMsg and PointCloud2 formats
include/common_lib.h Migrated parameter loading to ROS2 declare/get pattern, updated PCL and tf2 includes
include/CustomMsg.h Removed ROS1-generated message headers (now using livox_ros_driver2 package)
include/CustomPoint.h Removed ROS1-generated message headers (now using livox_ros_driver2 package)
launch/calib.launch.py Added ROS2 Python launch file with node and RViz2 configuration
config/qr_params.yaml Updated to ROS2 hierarchical parameter format with node namespace

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/data_preprocess.hpp Outdated
Comment on lines +60 to +62
// Determine if the message is a Livox custom message or PointCloud2
// Note: In ROS2, message types are often checked via the metadata in the bag,
// but here we try to deserialize.
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

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

The comment on lines 61-62 is outdated and potentially confusing. In ROS2, the message type metadata is available through the bag API, specifically via bag_message->topic_name and the serialization format. The current try-catch approach works but the comment suggests uncertainty about the implementation. Consider clarifying that this is a deliberate fallback strategy for handling both Livox CustomMsg and standard PointCloud2 formats.

Suggested change
// Determine if the message is a Livox custom message or PointCloud2
// Note: In ROS2, message types are often checked via the metadata in the bag,
// but here we try to deserialize.
// Determine if the message is a Livox CustomMsg or a standard PointCloud2.
// In ROS2, message type metadata is available via the bag API (e.g. topic_name and
// serialization format), but here we intentionally use a deserialization-based
// fallback: first try Livox CustomMsg, then fall back to PointCloud2.

Copilot uses AI. Check for mistakes.
Comment thread src/data_preprocess.hpp Outdated
Comment on lines 38 to 52
img_input_ = cv::imread(params.image_path, cv::IMREAD_UNCHANGED);
if (img_input_.empty())
{
std::string msg = "Loading the image " + image_path + " failed";
ROS_ERROR_STREAM(msg.c_str());
RCLCPP_ERROR(rclcpp::get_logger("data_preprocess"), "Loading the image %s failed", image_path.c_str());
return;
}

std::fstream file_;
file_.open(bag_path, ios::in);
if (!file_)
{
std::string msg = "Loading the rosbag " + bag_path + " failed";
ROS_ERROR_STREAM(msg.c_str());
return;
}
ROS_INFO("Loading the rosbag %s", bag_path.c_str());
RCLCPP_INFO(rclcpp::get_logger("data_preprocess"), "Loading the rosbag %s", bag_path.c_str());

rosbag::Bag bag;
rosbag2_cpp::Reader reader;
try {
bag.open(bag_path, rosbag::bagmode::Read);
} catch (rosbag::BagException &e) {
ROS_ERROR_STREAM("LOADING BAG FAILED: " << e.what());
reader.open(bag_path);
} catch (const std::exception &e) {
RCLCPP_ERROR(rclcpp::get_logger("data_preprocess"), "LOADING BAG FAILED: %s", e.what());
return;
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

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

The constructor returns early on errors (lines 42 and 52) but leaves the object in a partially constructed state with img_input_ potentially empty or cloud_input_ potentially empty. This violates object construction best practices. The calling code in main.cpp doesn't check if the DataPreprocess object is in a valid state before using img_input_ and cloud_input_. Consider either throwing exceptions from the constructor to signal failure, or adding a validation method that main.cpp can call after construction.

Copilot uses AI. Check for mistakes.
Comment thread package.xml
Comment on lines +32 to +33
<build_depend>rosbag2_cpp</build_depend>
<build_depend>rosbag2_storage</build_depend>
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

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

The rosbag2_storage dependency is declared in both package.xml and CMakeLists.txt, but it's not directly used in the code. The rosbag2_cpp::Reader class handles storage internally. While this dependency might be transitively required, explicitly listing unused dependencies adds unnecessary complexity. Consider removing it unless it's specifically required by your ROS2 distribution.

Copilot uses AI. Check for mistakes.
Comment thread src/qr_detect.hpp
#include <message_filters/time_synchronizer.h>
#include <ros/ros.h>
#endif
#include <image_geometry/pinhole_camera_model.hpp>
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

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

The header image_geometry/pinhole_camera_model.hpp is included but never used in the code. No image_geometry classes or functions are referenced. This unused include should be removed to reduce compilation dependencies and improve build times.

Suggested change
#include <image_geometry/pinhole_camera_model.hpp>

Copilot uses AI. Check for mistakes.
Comment thread src/qr_detect.hpp
#include <ros/ros.h>
#endif
#include <image_geometry/pinhole_camera_model.hpp>
#include <message_filters/subscriber.hpp>
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

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

The include for message_filters/subscriber.hpp is not used anywhere in the code. The QRDetect class doesn't use message_filters for subscribers, and message_filters is not listed as a dependency in CMakeLists.txt or package.xml. This unused include should be removed to avoid potential compilation issues.

Suggested change
#include <message_filters/subscriber.hpp>

Copilot uses AI. Check for mistakes.
Comment thread config/qr_params.yaml Outdated
Comment on lines +42 to +43
bag_path: "calib_data/mid360/11.bag" # Note: in ROS2, we might pass absolute path
image_path: "calib_data/mid360/11.png"
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

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

The paths for bag_path and image_path are specified as relative paths without using ROS2 package resolution. In ROS2, package-relative paths should be resolved programmatically (e.g., using ament_index_python in Python or similar in C++). These relative paths may not work correctly depending on where the node is launched from. Consider either using absolute paths, environment variables, or updating the code to resolve package-relative paths at runtime.

Copilot uses AI. Check for mistakes.
Comment thread CMakeLists.txt
Comment on lines +73 to +74
install(
DIRECTORY config launch rviz_cfg
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

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

The installation command on line 74 attempts to install the rviz_cfg directory, but this directory may not exist in the repository (the launch file references fast_livo2.rviz which appears to be from a different project). If the rviz_cfg directory doesn't exist, the build will fail or issue warnings. Verify that this directory exists, or remove it from the install list if it's not part of this package.

Copilot uses AI. Check for mistakes.
Comment thread src/qr_detect.hpp
Comment on lines +324 to +327
// Note: logging might need a node pointer if used outside constructor,
// but for now I'll assume we can use a global or pass it.
// Actually, I'll need to pass the node pointer or use a static logger.
// For simplicity, I'll use rclcpp::get_logger("qr_detect")
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

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

The developer comments on lines 324-327 are remnants from the migration process and should be removed from production code. These temporary notes about logging implementation don't add value to the final codebase and make the code less professional.

Suggested change
// Note: logging might need a node pointer if used outside constructor,
// but for now I'll assume we can use a global or pass it.
// Actually, I'll need to pass the node pointer or use a static logger.
// For simplicity, I'll use rclcpp::get_logger("qr_detect")

Copilot uses AI. Check for mistakes.
Comment thread launch/calib.launch.py
executable='rviz2',
name='rviz2',
arguments=['-d', rviz_config],
condition=None # Handle rviz argument if needed
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

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

The condition=None parameter is ineffective and the use_rviz variable on line 16 is declared but never used. To properly control whether RViz launches, you should import IfCondition from launch.conditions and use it like: condition=IfCondition(use_rviz). This would allow users to control RViz startup via the launch argument.

Copilot uses AI. Check for mistakes.
Comment thread launch/calib.launch.py
rviz_config = os.path.join(pkg_fast_calib, 'rviz_cfg', 'fast_livo2.rviz')

# Launch arguments
use_rviz = LaunchConfiguration('rviz', default='true')
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

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

Variable use_rviz is not used.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants