diff --git a/.github/workflows/ros.yml b/.github/workflows/ros.yml
index dc54d50c..4ae5cf29 100644
--- a/.github/workflows/ros.yml
+++ b/.github/workflows/ros.yml
@@ -7,31 +7,11 @@ on:
branches: ["main"]
jobs:
- ros1_node:
- runs-on: ubuntu-latest
- strategy:
- matrix:
- release: [noetic]
- container: osrf/ros:${{ matrix.release }}-desktop-full
- steps:
- - name: Setup cmake
- uses: jwlawson/actions-setup-cmake@v1.13
- with:
- cmake-version: "3.25.x"
- - name: Prepare catkin_ws
- run: mkdir -p catkin_ws/src
- - uses: actions/checkout@v3
- with:
- path: catkin_ws/src
- - name: Run catkin_make
- run: source /opt/ros/${{ matrix.release }}/setup.bash && cd catkin_ws && catkin_make
- shell: bash
-
ros2_node:
runs-on: ubuntu-latest
strategy:
matrix:
- release: [humble, iron]
+ release: [humble, iron, rolling]
container: osrf/ros:${{ matrix.release }}-desktop
steps:
- name: Setup cmake
diff --git a/README.md b/README.md
index 16af3cd1..86443f80 100644
--- a/README.md
+++ b/README.md
@@ -11,12 +11,7 @@
•
Install
•
- ROS 1
- •
ROS 2
- •
- ROS Demo
•
Paper
•
@@ -49,9 +44,10 @@ kiss_icp_pipeline --help
This should print the following help message:
![out](https://user-images.githubusercontent.com/21349875/193282970-25a400aa-ebcd-487a-b839-faa04eeca5b9.png)
+
-For advanced instructions on the Python pacakge plase see [this README](python/README.md)
+For advanced instructions on the Python package please see [this README](python/README.md)
## ROS support
@@ -61,17 +57,18 @@ For advanced instructions on the Python pacakge plase see [this README](python/R
```sh
cd ~/ros2_ws/src/ && git clone https://github.com/PRBonn/kiss-icp && cd ~/ros2_ws/ && colcon build --packages-select kiss_icp
```
+For more detailed instructions on the ROS wrapper, please visit this [README](ros/README.md)
+
ROS 1
-```sh
-cd ~/catkin_ws/ && git clone https://github.com/PRBonn/kiss-icp && catkin build
-```
-
+⚠️ ⚠️ **ROS 1 is deprecated in KISS-ICP and is not officially supported anymore. Upgrade now to ROS 2!** ⚠️ ⚠️
-For more detailed instructions on the ROS wrappers, please visit this [README](ros/README.md)
+The last release that supports ROS 1 is [v0.3.0](https://github.com/PRBonn/kiss-icp/tree/v0.3.0), if you still need ROS 1 support please check that version.
+
+
## Citation
diff --git a/cpp/kiss_icp/CMakeLists.txt b/cpp/kiss_icp/CMakeLists.txt
index ba62c9e2..abbb01a7 100644
--- a/cpp/kiss_icp/CMakeLists.txt
+++ b/cpp/kiss_icp/CMakeLists.txt
@@ -21,7 +21,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.16...3.26)
-project(kiss_icp_cpp VERSION 0.3.0 LANGUAGES CXX)
+project(kiss_icp_cpp VERSION 0.4.0 LANGUAGES CXX)
# Setup build options
option(USE_CCACHE "Build using Ccache if found on the path" ON)
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 5caf44e7..eaa2f9bd 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -21,7 +21,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.16...3.26)
-project(kiss_icp_pybind VERSION 0.3.0 LANGUAGES CXX)
+project(kiss_icp_pybind VERSION 0.4.0 LANGUAGES CXX)
# Set build type
set(CMAKE_BUILD_TYPE Release)
diff --git a/python/README.md b/python/README.md
index 90de0415..09725043 100644
--- a/python/README.md
+++ b/python/README.md
@@ -11,8 +11,6 @@
•
Install
•
- ROS 1
- •
ROS 2
•
*.bag
```
-## ROS 1
-
-### How to build
-
-You should not need any extra dependency, just clone and build:
-
-```sh
-cd ~/catkin_ws/
-git clone https://github.com/PRBonn/kiss-icp
-catkin build
-source devel/setup.bash
-```
-
-### How to run
-
-The only required argument to provide is the **topic name** so KISS-ICP knows which PointCloud2 to proces:
-
-```sh
-roslaunch kiss_icp odometry.launch bagfile:= topic:=
-```
-
-You can optionally launch the node with any bagfile, and play the bagfiles on a different shell:
-
-```sh
-roslaunch kiss_icp odometry.launch topic:=
-```
-
-and then,
-
-```sh
-rosbag play *.bag
-```
-
## Out of source builds
Good news! If you don't have git or you don't need to change the core KISS-ICP library, you can just
-copy paste this folder into your ROS1/ROS2 workspace and build as usual. The build system will fetch
+copy paste this folder into your ROS2 workspace and build as usual. The build system will fetch
the latest stable release for you.
## Looking how to run KITTI on ROS along with KISS-ICP?
diff --git a/ros/launch/odometry.launch b/ros/launch/odometry.launch
deleted file mode 100644
index 4dc9a26b..00000000
--- a/ros/launch/odometry.launch
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ros/launch/odometry.launch.py b/ros/launch/odometry.launch.py
index 470f2e07..f6f7dc61 100644
--- a/ros/launch/odometry.launch.py
+++ b/ros/launch/odometry.launch.py
@@ -76,7 +76,7 @@ def generate_launch_description():
package="rviz2",
executable="rviz2",
output={"both": "log"},
- arguments=["-d", PathJoinSubstitution([current_pkg, "rviz", "kiss_icp_ros2.rviz"])],
+ arguments=["-d", PathJoinSubstitution([current_pkg, "rviz", "kiss_icp.rviz"])],
condition=IfCondition(LaunchConfiguration("visualize")),
),
ExecuteProcess(
diff --git a/ros/package.xml b/ros/package.xml
index ac7c00c4..eff04c96 100644
--- a/ros/package.xml
+++ b/ros/package.xml
@@ -25,26 +25,16 @@
-->
kiss_icp
- 0.3.0
- KISS-ICP ROS Wrappers
+ 0.4.0
+ KISS-ICP ROS 2 Wrapper
ivizzo
MIT
-
- ros_environment
+ ament_cmake
-
- catkin
- roscpp
-
-
- ament_cmake
- rcutils
- rclcpp
- rclcpp_components
- ros2launch
-
-
+ rcutils
+ rclcpp
+ rclcpp_components
geometry_msgs
nav_msgs
std_msgs
@@ -52,8 +42,9 @@
tf2
tf2_ros
+ ros2launch
+
- catkin
- ament_cmake
+ ament_cmake
diff --git a/ros/ros1/OdometryServer.cpp b/ros/ros1/OdometryServer.cpp
deleted file mode 100644
index 3cf3c480..00000000
--- a/ros/ros1/OdometryServer.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-// MIT License
-//
-// Copyright (c) 2022 Ignacio Vizzo, Tiziano Guadagnino, Benedikt Mersch, Cyrill
-// Stachniss.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-#include
-#include
-#include
-#include
-
-// KISS-ICP-ROS
-#include "OdometryServer.hpp"
-#include "Utils.hpp"
-
-// KISS-ICP
-#include "kiss_icp/pipeline/KissICP.hpp"
-
-// ROS 1 headers
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace kiss_icp_ros {
-
-using utils::EigenToPointCloud2;
-using utils::GetTimestamps;
-using utils::PointCloud2ToEigen;
-
-OdometryServer::OdometryServer(const ros::NodeHandle &nh, const ros::NodeHandle &pnh)
- : nh_(nh), pnh_(pnh), tf2_listener_(tf2_ros::TransformListener(tf2_buffer_)) {
- pnh_.param("base_frame", base_frame_, base_frame_);
- pnh_.param("odom_frame", odom_frame_, odom_frame_);
- pnh_.param("publish_odom_tf", publish_odom_tf_, false);
- pnh_.param("visualize", publish_debug_clouds_, publish_debug_clouds_);
- pnh_.param("max_range", config_.max_range, config_.max_range);
- pnh_.param("min_range", config_.min_range, config_.min_range);
- pnh_.param("deskew", config_.deskew, config_.deskew);
- pnh_.param("voxel_size", config_.voxel_size, config_.max_range / 100.0);
- pnh_.param("max_points_per_voxel", config_.max_points_per_voxel, config_.max_points_per_voxel);
- pnh_.param("initial_threshold", config_.initial_threshold, config_.initial_threshold);
- pnh_.param("min_motion_th", config_.min_motion_th, config_.min_motion_th);
- if (config_.max_range < config_.min_range) {
- ROS_WARN("[WARNING] max_range is smaller than min_range, setting min_range to 0.0");
- config_.min_range = 0.0;
- }
-
- // Construct the main KISS-ICP odometry node
- odometry_ = kiss_icp::pipeline::KissICP(config_);
-
- // Initialize subscribers
- pointcloud_sub_ = nh_.subscribe("pointcloud_topic", queue_size_,
- &OdometryServer::RegisterFrame, this);
-
- // Initialize publishers
- odom_publisher_ = pnh_.advertise("/kiss/odometry", queue_size_);
- traj_publisher_ = pnh_.advertise("/kiss/trajectory", queue_size_);
- if (publish_debug_clouds_) {
- frame_publisher_ = pnh_.advertise("/kiss/frame", queue_size_);
- kpoints_publisher_ =
- pnh_.advertise("/kiss/keypoints", queue_size_);
- map_publisher_ = pnh_.advertise("/kiss/local_map", queue_size_);
- }
- // Initialize the transform buffer
- tf2_buffer_.setUsingDedicatedThread(true);
- path_msg_.header.frame_id = odom_frame_;
-
- // publish odometry msg
- ROS_INFO("KISS-ICP ROS 1 Odometry Node Initialized");
-}
-
-Sophus::SE3d OdometryServer::LookupTransform(const std::string &target_frame,
- const std::string &source_frame) const {
- std::string err_msg;
- if (tf2_buffer_._frameExists(source_frame) && //
- tf2_buffer_._frameExists(target_frame) && //
- tf2_buffer_.canTransform(target_frame, source_frame, ros::Time(0), &err_msg)) {
- try {
- auto tf = tf2_buffer_.lookupTransform(target_frame, source_frame, ros::Time(0));
- return tf2::transformToSophus(tf);
- } catch (tf2::TransformException &ex) {
- ROS_WARN("%s", ex.what());
- }
- }
- ROS_WARN("Failed to find tf between %s and %s. Reason=%s", target_frame.c_str(),
- source_frame.c_str(), err_msg.c_str());
- return {};
-}
-
-void OdometryServer::RegisterFrame(const sensor_msgs::PointCloud2::ConstPtr &msg) {
- const auto cloud_frame_id = msg->header.frame_id;
- const auto points = PointCloud2ToEigen(msg);
- const auto timestamps = [&]() -> std::vector {
- if (!config_.deskew) return {};
- return GetTimestamps(msg);
- }();
- const auto egocentric_estimation = (base_frame_.empty() || base_frame_ == cloud_frame_id);
-
- // Register frame, main entry point to KISS-ICP pipeline
- const auto &[frame, keypoints] = odometry_.RegisterFrame(points, timestamps);
-
- // Compute the pose using KISS, ego-centric to the LiDAR
- const Sophus::SE3d kiss_pose = odometry_.poses().back();
-
- // If necessary, transform the ego-centric pose to the specified base_link/base_footprint frame
- const auto pose = [&]() -> Sophus::SE3d {
- if (egocentric_estimation) return kiss_pose;
- const Sophus::SE3d cloud2base = LookupTransform(base_frame_, cloud_frame_id);
- return cloud2base * kiss_pose * cloud2base.inverse();
- }();
-
- // Spit the current estimated pose to ROS msgs
- PublishOdometry(pose, msg->header.stamp, cloud_frame_id);
-
- // Publishing this clouds is a bit costly, so do it only if we are debugging
- if (publish_debug_clouds_) {
- PublishClouds(frame, keypoints, msg->header.stamp, cloud_frame_id);
- }
-}
-
-void OdometryServer::PublishOdometry(const Sophus::SE3d &pose,
- const ros::Time &stamp,
- const std::string &cloud_frame_id) {
- // Header for point clouds and stuff seen from desired odom_frame
-
- // Broadcast the tf
- if (publish_odom_tf_) {
- geometry_msgs::TransformStamped transform_msg;
- transform_msg.header.stamp = stamp;
- transform_msg.header.frame_id = odom_frame_;
- transform_msg.child_frame_id = base_frame_.empty() ? cloud_frame_id : base_frame_;
- transform_msg.transform = tf2::sophusToTransform(pose);
- tf_broadcaster_.sendTransform(transform_msg);
- }
-
- // publish trajectory msg
- geometry_msgs::PoseStamped pose_msg;
- pose_msg.header.stamp = stamp;
- pose_msg.header.frame_id = odom_frame_;
- pose_msg.pose = tf2::sophusToPose(pose);
- path_msg_.poses.push_back(pose_msg);
- traj_publisher_.publish(path_msg_);
-
- // publish odometry msg
- nav_msgs::Odometry odom_msg;
- odom_msg.header.stamp = stamp;
- odom_msg.header.frame_id = odom_frame_;
- odom_msg.pose.pose = tf2::sophusToPose(pose);
- odom_publisher_.publish(odom_msg);
-}
-
-void OdometryServer::PublishClouds(const std::vector frame,
- const std::vector keypoints,
- const ros::Time &stamp,
- const std::string &cloud_frame_id) {
- std_msgs::Header odom_header;
- odom_header.stamp = stamp;
- odom_header.frame_id = odom_frame_;
-
- // Publish map
- const auto kiss_map = odometry_.LocalMap();
-
- if (!publish_odom_tf_) {
- // debugging happens in an egocentric world
- std_msgs::Header cloud_header;
- cloud_header.stamp = stamp;
- cloud_header.frame_id = cloud_frame_id;
-
- frame_publisher_.publish(*EigenToPointCloud2(frame, cloud_header));
- kpoints_publisher_.publish(*EigenToPointCloud2(keypoints, cloud_header));
- map_publisher_.publish(*EigenToPointCloud2(kiss_map, odom_header));
-
- return;
- }
-
- // If transmitting to tf tree we know where the clouds are exactly
- const auto cloud2odom = LookupTransform(odom_frame_, cloud_frame_id);
- frame_publisher_.publish(*EigenToPointCloud2(frame, cloud2odom, odom_header));
- kpoints_publisher_.publish(*EigenToPointCloud2(keypoints, cloud2odom, odom_header));
-
- if (!base_frame_.empty()) {
- const Sophus::SE3d cloud2base = LookupTransform(base_frame_, cloud_frame_id);
- map_publisher_.publish(*EigenToPointCloud2(kiss_map, cloud2base, odom_header));
- } else {
- map_publisher_.publish(*EigenToPointCloud2(kiss_map, odom_header));
- }
-}
-
-} // namespace kiss_icp_ros
-
-int main(int argc, char **argv) {
- ros::init(argc, argv, "kiss_icp");
- ros::NodeHandle nh;
- ros::NodeHandle nh_private("~");
-
- kiss_icp_ros::OdometryServer node(nh, nh_private);
-
- ros::spin();
-
- return 0;
-}
diff --git a/ros/ros1/OdometryServer.hpp b/ros/ros1/OdometryServer.hpp
deleted file mode 100644
index 3786844f..00000000
--- a/ros/ros1/OdometryServer.hpp
+++ /dev/null
@@ -1,96 +0,0 @@
-// MIT License
-//
-// Copyright (c) 2022 Ignacio Vizzo, Tiziano Guadagnino, Benedikt Mersch, Cyrill
-// Stachniss.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-#pragma once
-
-// KISS-ICP
-#include "kiss_icp/pipeline/KissICP.hpp"
-
-// ROS
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-namespace kiss_icp_ros {
-
-class OdometryServer {
-public:
- /// OdometryServer constructor
- OdometryServer(const ros::NodeHandle &nh, const ros::NodeHandle &pnh);
-
-private:
- /// Register new frame
- void RegisterFrame(const sensor_msgs::PointCloud2::ConstPtr &msg);
-
- /// Stream the estimated pose to ROS
- void PublishOdometry(const Sophus::SE3d &pose,
- const ros::Time &stamp,
- const std::string &cloud_frame_id);
-
- /// Stream the debugging point clouds for visualization (if required)
- void PublishClouds(const std::vector frame,
- const std::vector keypoints,
- const ros::Time &stamp,
- const std::string &cloud_frame_id);
-
- /// Utility function to compute transformation using tf tree
- Sophus::SE3d LookupTransform(const std::string &target_frame,
- const std::string &source_frame) const;
-
- /// Ros node stuff
- ros::NodeHandle nh_;
- ros::NodeHandle pnh_;
- int queue_size_{1};
-
- /// Tools for broadcasting TFs.
- tf2_ros::TransformBroadcaster tf_broadcaster_;
- tf2_ros::Buffer tf2_buffer_;
- tf2_ros::TransformListener tf2_listener_;
- bool publish_odom_tf_;
- bool publish_debug_clouds_;
-
- /// Data subscribers.
- ros::Subscriber pointcloud_sub_;
-
- /// Data publishers.
- ros::Publisher odom_publisher_;
- ros::Publisher frame_publisher_;
- ros::Publisher kpoints_publisher_;
- ros::Publisher map_publisher_;
- ros::Publisher traj_publisher_;
- nav_msgs::Path path_msg_;
-
- /// KISS-ICP
- kiss_icp::pipeline::KissICP odometry_;
- kiss_icp::pipeline::KISSConfig config_;
-
- /// Global/map coordinate frame.
- std::string odom_frame_{"odom"};
- std::string base_frame_{};
-};
-
-} // namespace kiss_icp_ros
diff --git a/ros/ros1/Utils.hpp b/ros/ros1/Utils.hpp
deleted file mode 100644
index ed4d833f..00000000
--- a/ros/ros1/Utils.hpp
+++ /dev/null
@@ -1,236 +0,0 @@
-// MIT License
-//
-// Copyright (c) 2022 Ignacio Vizzo, Tiziano Guadagnino, Benedikt Mersch, Cyrill
-// Stachniss.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-// ROS 1 headers
-#include
-#include
-#include
-#include
-#include
-
-namespace tf2 {
-
-inline geometry_msgs::Transform sophusToTransform(const Sophus::SE3d &T) {
- geometry_msgs::Transform t;
- t.translation.x = T.translation().x();
- t.translation.y = T.translation().y();
- t.translation.z = T.translation().z();
-
- Eigen::Quaterniond q(T.so3().unit_quaternion());
- t.rotation.x = q.x();
- t.rotation.y = q.y();
- t.rotation.z = q.z();
- t.rotation.w = q.w();
-
- return t;
-}
-
-inline geometry_msgs::Pose sophusToPose(const Sophus::SE3d &T) {
- geometry_msgs::Pose t;
- t.position.x = T.translation().x();
- t.position.y = T.translation().y();
- t.position.z = T.translation().z();
-
- Eigen::Quaterniond q(T.so3().unit_quaternion());
- t.orientation.x = q.x();
- t.orientation.y = q.y();
- t.orientation.z = q.z();
- t.orientation.w = q.w();
-
- return t;
-}
-
-inline Sophus::SE3d transformToSophus(const geometry_msgs::TransformStamped &transform) {
- const auto &t = transform.transform;
- return Sophus::SE3d(
- Sophus::SE3d::QuaternionType(t.rotation.w, t.rotation.x, t.rotation.y, t.rotation.z),
- Sophus::SE3d::Point(t.translation.x, t.translation.y, t.translation.z));
-}
-} // namespace tf2
-
-namespace kiss_icp_ros::utils {
-using PointCloud2 = sensor_msgs::PointCloud2;
-using PointField = sensor_msgs::PointField;
-using Header = std_msgs::Header;
-
-inline std::string FixFrameId(const std::string &frame_id) {
- return std::regex_replace(frame_id, std::regex("^/"), "");
-}
-
-inline auto GetTimestampField(const PointCloud2::ConstPtr msg) {
- PointField timestamp_field;
- for (const auto &field : msg->fields) {
- if ((field.name == "t" || field.name == "timestamp" || field.name == "time")) {
- timestamp_field = field;
- }
- }
- if (!timestamp_field.count) {
- throw std::runtime_error("Field 't', 'timestamp', or 'time' does not exist");
- }
- return timestamp_field;
-}
-
-// Normalize timestamps from 0.0 to 1.0
-inline auto NormalizeTimestamps(const std::vector ×tamps) {
- const auto [min_it, max_it] = std::minmax_element(timestamps.cbegin(), timestamps.cend());
- const double min_timestamp = *min_it;
- const double max_timestamp = *max_it;
-
- std::vector timestamps_normalized(timestamps.size());
- std::transform(timestamps.cbegin(), timestamps.cend(), timestamps_normalized.begin(),
- [&](const auto ×tamp) {
- return (timestamp - min_timestamp) / (max_timestamp - min_timestamp);
- });
- return timestamps_normalized;
-}
-
-inline auto ExtractTimestampsFromMsg(const PointCloud2::ConstPtr msg, const PointField &field) {
- auto extract_timestamps =
- [&msg](sensor_msgs::PointCloud2ConstIterator &&it) -> std::vector {
- const size_t n_points = msg->height * msg->width;
- std::vector timestamps;
- timestamps.reserve(n_points);
- for (size_t i = 0; i < n_points; ++i, ++it) {
- timestamps.emplace_back(static_cast(*it));
- }
- return NormalizeTimestamps(timestamps);
- };
-
- // Get timestamp field that must be one of the following : {t, timestamp, time}
- auto timestamp_field = GetTimestampField(msg);
-
- // According to the type of the timestamp == type, return a PointCloud2ConstIterator
- using sensor_msgs::PointCloud2ConstIterator;
- if (timestamp_field.datatype == PointField::UINT32) {
- return extract_timestamps(PointCloud2ConstIterator(*msg, timestamp_field.name));
- } else if (timestamp_field.datatype == PointField::FLOAT32) {
- return extract_timestamps(PointCloud2ConstIterator(*msg, timestamp_field.name));
- } else if (timestamp_field.datatype == PointField::FLOAT64) {
- return extract_timestamps(PointCloud2ConstIterator(*msg, timestamp_field.name));
- }
-
- // timestamp type not supported, please open an issue :)
- throw std::runtime_error("timestamp field type not supported");
-}
-
-inline std::unique_ptr CreatePointCloud2Msg(const size_t n_points,
- const Header &header,
- bool timestamp = false) {
- auto cloud_msg = std::make_unique();
- sensor_msgs::PointCloud2Modifier modifier(*cloud_msg);
- cloud_msg->header = header;
- cloud_msg->header.frame_id = FixFrameId(cloud_msg->header.frame_id);
- cloud_msg->fields.clear();
- int offset = 0;
- offset = addPointField(*cloud_msg, "x", 1, PointField::FLOAT32, offset);
- offset = addPointField(*cloud_msg, "y", 1, PointField::FLOAT32, offset);
- offset = addPointField(*cloud_msg, "z", 1, PointField::FLOAT32, offset);
- offset += sizeOfPointField(PointField::FLOAT32);
- if (timestamp) {
- // assuming timestamp on a velodyne fashion for now (between 0.0 and 1.0)
- offset = addPointField(*cloud_msg, "time", 1, PointField::FLOAT64, offset);
- offset += sizeOfPointField(PointField::FLOAT64);
- }
-
- // Resize the point cloud accordingly
- cloud_msg->point_step = offset;
- cloud_msg->row_step = cloud_msg->width * cloud_msg->point_step;
- cloud_msg->data.resize(cloud_msg->height * cloud_msg->row_step);
- modifier.resize(n_points);
- return cloud_msg;
-}
-
-inline void FillPointCloud2XYZ(const std::vector &points, PointCloud2 &msg) {
- sensor_msgs::PointCloud2Iterator msg_x(msg, "x");
- sensor_msgs::PointCloud2Iterator msg_y(msg, "y");
- sensor_msgs::PointCloud2Iterator msg_z(msg, "z");
- for (size_t i = 0; i < points.size(); i++, ++msg_x, ++msg_y, ++msg_z) {
- const Eigen::Vector3d &point = points[i];
- *msg_x = point.x();
- *msg_y = point.y();
- *msg_z = point.z();
- }
-}
-
-inline void FillPointCloud2Timestamp(const std::vector ×tamps, PointCloud2 &msg) {
- sensor_msgs::PointCloud2Iterator msg_t(msg, "time");
- for (size_t i = 0; i < timestamps.size(); i++, ++msg_t) *msg_t = timestamps[i];
-}
-
-inline std::vector GetTimestamps(const PointCloud2::ConstPtr msg) {
- auto timestamp_field = GetTimestampField(msg);
-
- // Extract timestamps from cloud_msg
- std::vector timestamps = ExtractTimestampsFromMsg(msg, timestamp_field);
-
- return timestamps;
-}
-
-inline std::vector PointCloud2ToEigen(const PointCloud2::ConstPtr msg) {
- std::vector points;
- points.reserve(msg->height * msg->width);
- sensor_msgs::PointCloud2ConstIterator msg_x(*msg, "x");
- sensor_msgs::PointCloud2ConstIterator msg_y(*msg, "y");
- sensor_msgs::PointCloud2ConstIterator msg_z(*msg, "z");
- for (size_t i = 0; i < msg->height * msg->width; ++i, ++msg_x, ++msg_y, ++msg_z) {
- points.emplace_back(*msg_x, *msg_y, *msg_z);
- }
- return points;
-}
-
-inline std::unique_ptr EigenToPointCloud2(const std::vector &points,
- const Header &header) {
- auto msg = CreatePointCloud2Msg(points.size(), header);
- FillPointCloud2XYZ(points, *msg);
- return msg;
-}
-
-inline std::unique_ptr EigenToPointCloud2(const std::vector &points,
- const Sophus::SE3d &T,
- const Header &header) {
- std::vector points_t;
- points_t.resize(points.size());
- std::transform(points.cbegin(), points.cend(), points_t.begin(),
- [&](const auto &point) { return T * point; });
- return EigenToPointCloud2(points_t, header);
-}
-
-inline std::unique_ptr EigenToPointCloud2(const std::vector &points,
- const std::vector ×tamps,
- const Header &header) {
- auto msg = CreatePointCloud2Msg(points.size(), header, true);
- FillPointCloud2XYZ(points, *msg);
- FillPointCloud2Timestamp(timestamps, *msg);
- return msg;
-}
-} // namespace kiss_icp_ros::utils
diff --git a/ros/rviz/kiss_icp_ros2.rviz b/ros/rviz/kiss_icp.rviz
similarity index 100%
rename from ros/rviz/kiss_icp_ros2.rviz
rename to ros/rviz/kiss_icp.rviz
diff --git a/ros/rviz/kiss_icp_ros1.rviz b/ros/rviz/kiss_icp_ros1.rviz
deleted file mode 100644
index d313da5f..00000000
--- a/ros/rviz/kiss_icp_ros1.rviz
+++ /dev/null
@@ -1,226 +0,0 @@
-Panels:
- - Class: rviz/Displays
- Help Height: 78
- Name: Displays
- Property Tree Widget:
- Expanded:
- - /local_map1/Autocompute Value Bounds1
- Splitter Ratio: 0.5
- Tree Height: 752
- - Class: rviz/Selection
- Name: Selection
- - Class: rviz/Tool Properties
- Expanded:
- - /2D Pose Estimate1
- - /2D Nav Goal1
- - /Publish Point1
- Name: Tool Properties
- Splitter Ratio: 0.5886790156364441
- - Class: rviz/Views
- Expanded:
- - /Current View1
- Name: Views
- Splitter Ratio: 0.5
- - Class: rviz/Time
- Name: Time
- SyncMode: 0
- SyncSource: local_map
-Preferences:
- PromptSaveOnExit: true
-Toolbars:
- toolButtonStyle: 2
-Visualization Manager:
- Class: ""
- Displays:
- - Alpha: 0.699999988079071
- Autocompute Intensity Bounds: true
- Autocompute Value Bounds:
- Max Value: 10
- Min Value: -10
- Value: true
- Axis: Z
- Channel Name: intensity
- Class: rviz/PointCloud2
- Color: 243; 243; 0
- Color Transformer: FlatColor
- Decay Time: 0
- Enabled: true
- Invert Rainbow: false
- Max Color: 255; 255; 255
- Min Color: 0; 0; 0
- Name: frame_deskewed
- Position Transformer: XYZ
- Queue Size: 10
- Selectable: true
- Size (Pixels): 1
- Size (m): 0.009999999776482582
- Style: Points
- Topic: /kiss/frame
- Unreliable: false
- Use Fixed Frame: true
- Use rainbow: false
- Value: true
- - Alpha: 0.5
- Autocompute Intensity Bounds: true
- Autocompute Value Bounds:
- Max Value: 29.128881454467773
- Min Value: -13.79653549194336
- Value: true
- Axis: Z
- Channel Name: intensity
- Class: rviz/PointCloud2
- Color: 255; 255; 255
- Color Transformer: AxisColor
- Decay Time: 0
- Enabled: true
- Invert Rainbow: false
- Max Color: 255; 255; 255
- Min Color: 0; 0; 0
- Name: local_map
- Position Transformer: XYZ
- Queue Size: 10
- Selectable: true
- Size (Pixels): 1
- Size (m): 0.009999999776482582
- Style: Points
- Topic: /kiss/local_map
- Unreliable: true
- Use Fixed Frame: true
- Use rainbow: true
- Value: true
- - Alpha: 1
- Autocompute Intensity Bounds: true
- Autocompute Value Bounds:
- Max Value: 18.019136428833008
- Min Value: -5.5211381912231445
- Value: true
- Axis: Z
- Channel Name: intensity
- Class: rviz/PointCloud2
- Color: 255; 255; 255
- Color Transformer: FlatColor
- Decay Time: 0
- Enabled: false
- Invert Rainbow: false
- Max Color: 255; 255; 255
- Min Color: 0; 0; 0
- Name: keypoints
- Position Transformer: XYZ
- Queue Size: 10
- Selectable: true
- Size (Pixels): 3
- Size (m): 0.009999999776482582
- Style: Points
- Topic: /odometry_node/keypoints
- Unreliable: false
- Use Fixed Frame: true
- Use rainbow: true
- Value: false
- - Alpha: 1
- Class: rviz/Axes
- Enabled: true
- Length: 3
- Name: odometry_frame
- Radius: 0.10000000149011612
- Reference Frame: odom
- Show Trail: false
- Value: true
- - Alpha: 1
- Class: rviz/Axes
- Enabled: true
- Length: 3
- Name: child_frame
- Radius: 0.10000000149011612
- Reference Frame: base
- Show Trail: false
- Value: true
- - Alpha: 1
- Buffer Length: 1
- Class: rviz/Path
- Color: 30; 85; 157
- Enabled: true
- Head Diameter: 0.30000001192092896
- Head Length: 0.20000000298023224
- Length: 1
- Line Style: Billboards
- Line Width: 0.20000000298023224
- Name: trajectory
- Offset:
- X: 0
- Y: 0
- Z: 0
- Pose Color: 134; 44; 134
- Pose Style: None
- Queue Size: 10
- Radius: 0.20000000298023224
- Shaft Diameter: 0.10000000149011612
- Shaft Length: 0.10000000149011612
- Topic: /kiss/trajectory
- Unreliable: false
- Value: true
- Enabled: true
- Global Options:
- Background Color: 0; 0; 0
- Default Light: true
- Fixed Frame: odom
- Frame Rate: 30
- Name: root
- Tools:
- - Class: rviz/Interact
- Hide Inactive Objects: true
- - Class: rviz/MoveCamera
- - Class: rviz/Select
- - Class: rviz/FocusCamera
- - Class: rviz/Measure
- - Class: rviz/SetInitialPose
- Theta std deviation: 0.2617993950843811
- Topic: /initialpose
- X std deviation: 0.5
- Y std deviation: 0.5
- - Class: rviz/SetGoal
- Topic: /move_base_simple/goal
- - Class: rviz/PublishPoint
- Single click: true
- Topic: /clicked_point
- Value: true
- Views:
- Current:
- Class: rviz/Orbit
- Distance: 73.19767761230469
- Enable Stereo Rendering:
- Stereo Eye Separation: 0.05999999865889549
- Stereo Focal Distance: 1
- Swap Stereo Eyes: false
- Value: false
- Field of View: 0.7853981852531433
- Focal Point:
- X: -0.9206065535545349
- Y: -1.2210272550582886
- Z: 4.959392547607422
- Focal Shape Fixed Size: true
- Focal Shape Size: 0.05000000074505806
- Invert Z Axis: false
- Name: Current View
- Near Clip Distance: 0.009999999776482582
- Pitch: 0.6503981947898865
- Target Frame:
- Yaw: 4.798571586608887
- Saved: ~
-Window Geometry:
- Displays:
- collapsed: true
- Height: 1043
- Hide Left Dock: true
- Hide Right Dock: false
- QMainWindow State: 000000ff00000000fd00000004000000000000027200000379fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073000000003b00000379000000c700fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000359fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003b00000359000000a000fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007800000003efc0100000002fb0000000800540069006d00650100000000000007800000030700fffffffb0000000800540069006d00650100000000000004500000000000000000000007800000037900000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
- Selection:
- collapsed: false
- Time:
- collapsed: false
- Tool Properties:
- collapsed: false
- Views:
- collapsed: false
- Width: 1920
- X: 3840
- Y: 0
diff --git a/ros/ros2/OdometryServer.cpp b/ros/src/OdometryServer.cpp
similarity index 100%
rename from ros/ros2/OdometryServer.cpp
rename to ros/src/OdometryServer.cpp
diff --git a/ros/ros2/OdometryServer.hpp b/ros/src/OdometryServer.hpp
similarity index 100%
rename from ros/ros2/OdometryServer.hpp
rename to ros/src/OdometryServer.hpp
diff --git a/ros/ros2/Utils.hpp b/ros/src/Utils.hpp
similarity index 100%
rename from ros/ros2/Utils.hpp
rename to ros/src/Utils.hpp