Skip to content

Commit 75517d5

Browse files
feat [ROS]: Allow to set parameters from a yaml file (#467)
1 parent 6719993 commit 75517d5

File tree

6 files changed

+135
-71
lines changed

6 files changed

+135
-71
lines changed

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 KISS-ICP algorithm itself are written in a yaml configuration file. They are meant to be set before launching the node. An **example** yaml file is given in config/config.yaml. The file parsed by default is located in the share directory of the kiss_icp package (in your workspace that would be `install/kiss_icp/share/kiss_icp/config/config.yaml`), but any file path can be provided with the `config_file` launch argument, e.g.: `ros2 launch kiss_icp odometry.launch.py config_file:=/path/to/my/config_file.yaml`.
41+
42+
The ROS-related parameters can 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 the ROS-related parameters 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: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
#### /!\ If you set these ROS-related parameters in the file, they will overwrite the corresponding launch arguments ####
8+
9+
# base_frame: ""
10+
# lidar_odom_frame: "odom_lidar"
11+
# publish_odom_tf: True
12+
# invert_odom_tf: True
13+
# position_covariance: 0.1
14+
# orientation_covariance: 0.1
15+
16+
#### Core KISS-ICP parameters ####
17+
18+
data:
19+
deskew: True
20+
max_range: 100.0
21+
min_range: 0.0
22+
23+
mapping:
24+
# voxel_size: 1.0 # <- optional, default = max_range / 100.0
25+
max_points_per_voxel: 20
26+
27+
adaptive_threshold:
28+
initial_threshold: 2.0
29+
min_motion_th: 0.1
30+
31+
registration:
32+
max_num_iterations: 500 # <- optional
33+
convergence_criterion: 0.0001 # <- optional
34+
max_num_threads: 0 # <- optional, 0 means automatic

ros/launch/odometry.launch.py

Lines changed: 17 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,11 @@
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+
default_config_file = os.path.join(
40+
get_package_share_directory(PACKAGE_NAME), "config", "config.yaml"
41+
)
6042

6143

6244
def generate_launch_description():
@@ -75,9 +57,14 @@ def generate_launch_description():
7557
publish_odom_tf = LaunchConfiguration("publish_odom_tf", default=True)
7658
invert_odom_tf = LaunchConfiguration("invert_odom_tf", default=True)
7759

60+
position_covariance = LaunchConfiguration("position_covariance", default=0.1)
61+
orientation_covariance = LaunchConfiguration("orientation_covariance", default=0.1)
62+
63+
config_file = LaunchConfiguration("config_file", default=default_config_file)
64+
7865
# KISS-ICP node
7966
kiss_icp_node = Node(
80-
package="kiss_icp",
67+
package=PACKAGE_NAME,
8168
executable="kiss_icp_node",
8269
name="kiss_icp_node",
8370
output="screen",
@@ -91,26 +78,13 @@ def generate_launch_description():
9178
"lidar_odom_frame": lidar_odom_frame,
9279
"publish_odom_tf": publish_odom_tf,
9380
"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,
11081
# ROS CLI arguments
11182
"publish_debug_clouds": visualize,
11283
"use_sim_time": use_sim_time,
84+
"position_covariance": position_covariance,
85+
"orientation_covariance": orientation_covariance,
11386
},
87+
config_file,
11488
],
11589
)
11690
rviz_node = Node(
@@ -119,7 +93,7 @@ def generate_launch_description():
11993
output="screen",
12094
arguments=[
12195
"-d",
122-
PathJoinSubstitution([FindPackageShare("kiss_icp"), "rviz", "kiss_icp.rviz"]),
96+
PathJoinSubstitution([FindPackageShare(PACKAGE_NAME), "rviz", "kiss_icp.rviz"]),
12397
],
12498
condition=IfCondition(visualize),
12599
)

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)