Skip to content

Commit 3cef65a

Browse files
leroycorentinCorentin LEROY
authored andcommitted
feat [ROS]: Allow to set parameters from a yaml file
1 parent 3ac517b commit 3cef65a

6 files changed

Lines changed: 127 additions & 71 deletions

File tree

ros/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,6 @@ ament_target_dependencies(
6767
rclcpp_components_register_node(odometry_component PLUGIN "kiss_icp_ros::OdometryServer" EXECUTABLE kiss_icp_node)
6868

6969
install(TARGETS odometry_component LIBRARY DESTINATION lib RUNTIME DESTINATION lib/${PROJECT_NAME})
70-
install(DIRECTORY launch rviz DESTINATION share/${PROJECT_NAME}/)
70+
install(DIRECTORY launch rviz config DESTINATION share/${PROJECT_NAME}/)
7171

7272
ament_package()

ros/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,33 @@ and then,
3030
ros2 bag play <path>*.bag
3131
```
3232

33+
A preconfigured Rviz2 window is launched by default. To disable it, you can set the `visualize` launch argument to `false`:
34+
```sh
35+
ros2 launch kiss_icp odometry.launch.py topic:=<topic_name> visualize:=false
36+
```
37+
38+
### Configuration
39+
40+
The parameters for the ROS node and the KISS-ICP algorithm itself are written in a yaml configuration file, located in the share directory of the node (in your workspace that would be `install/kiss_icp/share/kiss_icp/config/config.yaml`). They are meant to be set before launching the node. An **example** yaml file is given in config/config.yaml.
41+
42+
Some parameters can also be set via command-line when launching the node:
43+
* `base_frame`
44+
* `lidar_odom_frame`
45+
* `publish_odom_tf`
46+
* `invert_odom_tf`
47+
* `position_covariance`
48+
* `orientation_covariance`
49+
50+
You can set them like so:
51+
```sh
52+
ros2 launch kiss_icp odometry.launch.py topic:=<topic_name> <parameter_name>:=<parameter_value>
53+
```
54+
For example:
55+
```sh
56+
ros2 launch kiss_icp odometry.launch.py topic:=/lidar/points base_frame:=lidar_cloud
57+
```
58+
Note that if you set their value in the yaml configuration file and via command-line, the values in the yaml file will be selected in the end.
59+
3360
## Out of source builds
3461

3562
Good news! If you don't have git or you don't need to change the core KISS-ICP library, you can just

ros/config/config.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# NOTE: Please note that this is just an example of the advanced configuration for the KISS-ICP
2+
# pipeline and it's not really meant to use for any particular dataset, is just to expose other
3+
# options that are disabled by default
4+
5+
kiss_icp_node:
6+
ros__parameters:
7+
base_frame: ""
8+
lidar_odom_frame: "odom_lidar"
9+
publish_odom_tf: True
10+
invert_odom_tf: True
11+
position_covariance: 0.1
12+
orientation_covariance: 0.1
13+
14+
data:
15+
deskew: True
16+
max_range: 100.0
17+
min_range: 0.0
18+
19+
mapping:
20+
voxel_size: 1.0 # <- optional
21+
max_points_per_voxel: 20
22+
23+
adaptive_threshold:
24+
initial_threshold: 2.0
25+
min_motion_th: 0.1
26+
27+
registration:
28+
max_num_iterations: 500 # <- optional
29+
convergence_criterion: 0.0001 # <- optional
30+
max_num_threads: 0 # <- optional, 0 means automatic

ros/launch/odometry.launch.py

Lines changed: 13 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2121
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2222
# SOFTWARE.
23+
import os
24+
25+
from ament_index_python.packages import get_package_share_directory
2326
from launch import LaunchDescription
2427
from launch.actions import ExecuteProcess
2528
from launch.conditions import IfCondition
@@ -31,32 +34,9 @@
3134
from launch_ros.actions import Node
3235
from launch_ros.substitutions import FindPackageShare
3336

37+
PACKAGE_NAME = "kiss_icp"
3438

35-
# This configuration parameters are not exposed thorught the launch system, meaning you can't modify
36-
# those throw the ros launch CLI. If you need to change these values, you could write your own
37-
# launch file and modify the 'parameters=' block from the Node class.
38-
class config:
39-
# Preprocessing
40-
max_range: float = 100.0
41-
min_range: float = 0.0
42-
deskew: bool = True
43-
44-
# Mapping parameters
45-
voxel_size: float = max_range / 100.0
46-
max_points_per_voxel: int = 20
47-
48-
# Adaptive threshold
49-
initial_threshold: float = 2.0
50-
min_motion_th: float = 0.1
51-
52-
# Registration
53-
max_num_iterations: int = 500 #
54-
convergence_criterion: float = 0.0001
55-
max_num_threads: int = 0
56-
57-
# Covariance diagonal values
58-
position_covariance: float = 0.1
59-
orientation_covariance: float = 0.1
39+
yaml_config = os.path.join(get_package_share_directory(PACKAGE_NAME), "config", "config.yaml")
6040

6141

6242
def generate_launch_description():
@@ -75,9 +55,12 @@ def generate_launch_description():
7555
publish_odom_tf = LaunchConfiguration("publish_odom_tf", default=True)
7656
invert_odom_tf = LaunchConfiguration("invert_odom_tf", default=True)
7757

58+
position_covariance = LaunchConfiguration("position_covariance", default=0.1)
59+
orientation_covariance = LaunchConfiguration("orientation_covariance", default=0.1)
60+
7861
# KISS-ICP node
7962
kiss_icp_node = Node(
80-
package="kiss_icp",
63+
package=PACKAGE_NAME,
8164
executable="kiss_icp_node",
8265
name="kiss_icp_node",
8366
output="screen",
@@ -91,26 +74,13 @@ def generate_launch_description():
9174
"lidar_odom_frame": lidar_odom_frame,
9275
"publish_odom_tf": publish_odom_tf,
9376
"invert_odom_tf": invert_odom_tf,
94-
# KISS-ICP configuration
95-
"max_range": config.max_range,
96-
"min_range": config.min_range,
97-
"deskew": config.deskew,
98-
"max_points_per_voxel": config.max_points_per_voxel,
99-
"voxel_size": config.voxel_size,
100-
# Adaptive threshold
101-
"initial_threshold": config.initial_threshold,
102-
"min_motion_th": config.min_motion_th,
103-
# Registration
104-
"max_num_iterations": config.max_num_iterations,
105-
"convergence_criterion": config.convergence_criterion,
106-
"max_num_threads": config.max_num_threads,
107-
# Fixed covariances
108-
"position_covariance": config.position_covariance,
109-
"orientation_covariance": config.orientation_covariance,
11077
# ROS CLI arguments
11178
"publish_debug_clouds": visualize,
11279
"use_sim_time": use_sim_time,
80+
"position_covariance": position_covariance,
81+
"orientation_covariance": orientation_covariance,
11382
},
83+
yaml_config,
11484
],
11585
)
11686
rviz_node = Node(
@@ -119,7 +89,7 @@ def generate_launch_description():
11989
output="screen",
12090
arguments=[
12191
"-d",
122-
PathJoinSubstitution([FindPackageShare("kiss_icp"), "rviz", "kiss_icp.rviz"]),
92+
PathJoinSubstitution([FindPackageShare(PACKAGE_NAME), "rviz", "kiss_icp.rviz"]),
12393
],
12494
condition=IfCondition(visualize),
12595
)

ros/src/OdometryServer.cpp

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -73,34 +73,8 @@ using utils::PointCloud2ToEigen;
7373

7474
OdometryServer::OdometryServer(const rclcpp::NodeOptions &options)
7575
: rclcpp::Node("kiss_icp_node", options) {
76-
base_frame_ = declare_parameter<std::string>("base_frame", base_frame_);
77-
lidar_odom_frame_ = declare_parameter<std::string>("lidar_odom_frame", lidar_odom_frame_);
78-
publish_odom_tf_ = declare_parameter<bool>("publish_odom_tf", publish_odom_tf_);
79-
invert_odom_tf_ = declare_parameter<bool>("invert_odom_tf", invert_odom_tf_);
80-
publish_debug_clouds_ = declare_parameter<bool>("publish_debug_clouds", publish_debug_clouds_);
81-
position_covariance_ = declare_parameter<double>("position_covariance", 0.1);
82-
orientation_covariance_ = declare_parameter<double>("orientation_covariance", 0.1);
83-
8476
kiss_icp::pipeline::KISSConfig config;
85-
config.max_range = declare_parameter<double>("max_range", config.max_range);
86-
config.min_range = declare_parameter<double>("min_range", config.min_range);
87-
config.deskew = declare_parameter<bool>("deskew", config.deskew);
88-
config.voxel_size = declare_parameter<double>("voxel_size", config.max_range / 100.0);
89-
config.max_points_per_voxel =
90-
declare_parameter<int>("max_points_per_voxel", config.max_points_per_voxel);
91-
config.initial_threshold =
92-
declare_parameter<double>("initial_threshold", config.initial_threshold);
93-
config.min_motion_th = declare_parameter<double>("min_motion_th", config.min_motion_th);
94-
config.max_num_iterations =
95-
declare_parameter<int>("max_num_iterations", config.max_num_iterations);
96-
config.convergence_criterion =
97-
declare_parameter<double>("convergence_criterion", config.convergence_criterion);
98-
config.max_num_threads = declare_parameter<int>("max_num_threads", config.max_num_threads);
99-
if (config.max_range < config.min_range) {
100-
RCLCPP_WARN(get_logger(),
101-
"[WARNING] max_range is smaller than min_range, settng min_range to 0.0");
102-
config.min_range = 0.0;
103-
}
77+
initializeParameters(config);
10478

10579
// Construct the main KISS-ICP odometry node
10680
kiss_icp_ = std::make_unique<kiss_icp::pipeline::KissICP>(config);
@@ -128,6 +102,57 @@ OdometryServer::OdometryServer(const rclcpp::NodeOptions &options)
128102
RCLCPP_INFO(this->get_logger(), "KISS-ICP ROS 2 odometry node initialized");
129103
}
130104

105+
void OdometryServer::initializeParameters(kiss_icp::pipeline::KISSConfig &config) {
106+
RCLCPP_INFO(this->get_logger(), "Initializing parameters");
107+
108+
base_frame_ = declare_parameter<std::string>("base_frame", base_frame_);
109+
RCLCPP_INFO(this->get_logger(), "\tBase frame: %s", base_frame_.c_str());
110+
lidar_odom_frame_ = declare_parameter<std::string>("lidar_odom_frame", lidar_odom_frame_);
111+
RCLCPP_INFO(this->get_logger(), "\tLiDAR odometry frame: %s", lidar_odom_frame_.c_str());
112+
publish_odom_tf_ = declare_parameter<bool>("publish_odom_tf", publish_odom_tf_);
113+
RCLCPP_INFO(this->get_logger(), "\tPublish odometry transform: %d", publish_odom_tf_);
114+
invert_odom_tf_ = declare_parameter<bool>("invert_odom_tf", invert_odom_tf_);
115+
RCLCPP_INFO(this->get_logger(), "\tInvert odometry transform: %d", invert_odom_tf_);
116+
publish_debug_clouds_ = declare_parameter<bool>("publish_debug_clouds", publish_debug_clouds_);
117+
RCLCPP_INFO(this->get_logger(), "\tPublish debug clouds: %d", publish_debug_clouds_);
118+
position_covariance_ = declare_parameter<double>("position_covariance", 0.1);
119+
RCLCPP_INFO(this->get_logger(), "\tPosition covariance: %.2f", position_covariance_);
120+
orientation_covariance_ = declare_parameter<double>("orientation_covariance", 0.1);
121+
RCLCPP_INFO(this->get_logger(), "\tOrientation covariance: %.2f", orientation_covariance_);
122+
123+
config.max_range = declare_parameter<double>("data.max_range", config.max_range);
124+
RCLCPP_INFO(this->get_logger(), "\tMax range: %.2f", config.max_range);
125+
config.min_range = declare_parameter<double>("data.min_range", config.min_range);
126+
RCLCPP_INFO(this->get_logger(), "\tMin range: %.2f", config.min_range);
127+
config.deskew = declare_parameter<bool>("data.deskew", config.deskew);
128+
RCLCPP_INFO(this->get_logger(), "\tDeskew: %d", config.deskew);
129+
config.voxel_size = declare_parameter<double>("mapping.voxel_size", config.max_range / 100.0);
130+
RCLCPP_INFO(this->get_logger(), "\tVoxel size: %.2f", config.voxel_size);
131+
config.max_points_per_voxel =
132+
declare_parameter<int>("mapping.max_points_per_voxel", config.max_points_per_voxel);
133+
RCLCPP_INFO(this->get_logger(), "\tMax points per voxel: %d", config.max_points_per_voxel);
134+
config.initial_threshold =
135+
declare_parameter<double>("adaptive_threshold.initial_threshold", config.initial_threshold);
136+
RCLCPP_INFO(this->get_logger(), "\tInitial threshold: %.2f", config.initial_threshold);
137+
config.min_motion_th =
138+
declare_parameter<double>("adaptive_threshold.min_motion_th", config.min_motion_th);
139+
RCLCPP_INFO(this->get_logger(), "\tMin motion threshold: %.2f", config.min_motion_th);
140+
config.max_num_iterations =
141+
declare_parameter<int>("registration.max_num_iterations", config.max_num_iterations);
142+
RCLCPP_INFO(this->get_logger(), "\tMax number of iterations: %d", config.max_num_iterations);
143+
config.convergence_criterion = declare_parameter<double>("registration.convergence_criterion",
144+
config.convergence_criterion);
145+
RCLCPP_INFO(this->get_logger(), "\tConvergence criterion: %.2f", config.convergence_criterion);
146+
config.max_num_threads =
147+
declare_parameter<int>("registration.max_num_threads", config.max_num_threads);
148+
RCLCPP_INFO(this->get_logger(), "\tMax number of threads: %d", config.max_num_threads);
149+
if (config.max_range < config.min_range) {
150+
RCLCPP_WARN(get_logger(),
151+
"[WARNING] max_range is smaller than min_range, settng min_range to 0.0");
152+
config.min_range = 0.0;
153+
}
154+
}
155+
131156
void OdometryServer::RegisterFrame(const sensor_msgs::msg::PointCloud2::ConstSharedPtr &msg) {
132157
const auto cloud_frame_id = msg->header.frame_id;
133158
const auto points = PointCloud2ToEigen(msg);

ros/src/OdometryServer.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ class OdometryServer : public rclcpp::Node {
4545
explicit OdometryServer(const rclcpp::NodeOptions &options);
4646

4747
private:
48+
/// Declare ROS parameters and set the associated variables (in this class and in the provided
49+
/// config object)
50+
void initializeParameters(kiss_icp::pipeline::KISSConfig &config);
51+
4852
/// Register new frame
4953
void RegisterFrame(const sensor_msgs::msg::PointCloud2::ConstSharedPtr &msg);
5054

0 commit comments

Comments
 (0)