I am working on Part II of the ROS2 Basics in 5 Days (C++) course, Create a ROS service that looks for the wall. I am looking for some general advice on how to go about it.
I know that I will need at least two callbacks, 1 for actually running the service once it is called, and a 2nd for getting laser scan data from the /scan topic.
Both of these callbacks will need to be run at the same time, as the laser scan data will need to be updated as the wall find server executes its steps (find shortest distance, point at wall, drive to wall, rotate until the side of the robot is pointed at the wall).
In unit 4, we learned about executors and callbacks. Since I want 2 callbacks executing in the same node, we will need to use callback groups. I have some code prepared where I use two callback groups in a MutuallyExclusiveCallbackGroup. However, I think that since my service callback group has blocking loops in it, it is still stopping the laser scan data from updating. Am I understanding callback groups correctly, and is it possible that my blocking wallfind_callback is blocking the scan_callback from running? What are other ways to solve this problem? Thanks!
Here is the first part of my wallfind_callback that runs when the service is called. As you can see here (at the bottom), there is a for loop that runs until the front of the robot is facing the wall. Even though this callback is in a MutuallyExclusiveCallbackGroup, I think this blocking part of the code stops the laser scan callback from updating the scan values.
void wallfind_callback(const std::shared_ptr<FindWall::Request> request,
std::shared_ptr<FindWall::Response> response) {
auto message = geometry_msgs::msg::Twist();
while (scan_data_.ranges.empty()) {
RCLCPP_INFO(this->get_logger(), "Waiting");
}
float min_distance = 99;
size_t min_distance_index = 0;
RCLCPP_INFO(this->get_logger(), "Finding shortest distance");
for (size_t i = 1; i < scan_data_.ranges.size();
++i) { // find the minimum distance
if (scan_data_.ranges[i] < min_distance) {
min_distance = scan_data_.ranges[i];
min_distance_index = i;
}
}
RCLCPP_INFO(this->get_logger(), "Shortest distance: %f at range %f",
min_distance, min_distance_index);
RCLCPP_INFO(this->get_logger(), "Rotating until front points at wall");
// rotate until ray[0] is pointing at the wall
while (scan_data_.ranges[0] > (min_distance - buffer)) {
message.linear.x = 0.0;
message.angular.z = 0.25;
publisher_->publish(message);
RCLCPP_INFO(this->get_logger(), "Shortest distance: %f", min_distance);
}
... rest of code continues
Here is the laser scan callback:
void scan_callback(const sensor_msgs::msg::LaserScan::SharedPtr msg) {
scan_data_ = *msg;
RCLCPP_INFO(this->get_logger(),
"Hello from laser callback. Front distance: %f",
scan_data_.ranges[0]);
}