Skip to main content

SwitchFloor

Service type: map_manager/srv/SwitchFloor

Service name: ${MM}/switch_floor

Description

Switch to another floor and load its localization map.

Request

FieldTypeDescription
floor_idstringUnique floor identifier.
initial_posegeometry_msgs/Pose2DInitial pose on the destination floor.
use_transitionboolWhether to use a floor transition.
transition_idstringIdentifier of the floor transition.

Response

FieldTypeDescription
successboolWhether the operation succeeded.
messagestringResult details or an error message.
current_floormap_manager/msg/FloorCurrent floor information.

Examples

Example 1

Bash
# Switch floors directly
ros2 service call ${MM}/switch_floor map_manager/srv/SwitchFloor \
"{floor_id: '2F', initial_pose: {x: 0.0, y: 0.0, theta: 0.0}, use_transition: false}"

# Switch floors through an elevator transition
ros2 service call ${MM}/switch_floor map_manager/srv/SwitchFloor \
"{floor_id: '2F', use_transition: true, transition_id: 'elevator_1'}"

Example 2

Python
from map_manager.srv import SwitchFloor
from geometry_msgs.msg import Pose2D
import rclpy
from rclpy.node import Node

class FloorSwitcher(Node):
def __init__(self):
super().__init__('floor_switcher')
self.client = self.create_client(SwitchFloor, '/switch_floor')
self.client.wait_for_service()

def switch_direct(self, floor_id: str, x: float = 0.0, y: float = 0.0, theta: float = 0.0):
"""Switch floors directly"""
request = SwitchFloor.Request()
request.floor_id = floor_id
request.initial_pose = Pose2D(x=x, y=y, theta=theta)
request.use_transition = False

future = self.client.call_async(request)
rclpy.spin_until_future_complete(self, future)
result = future.result()

if result.success:
print(f"Floor switch succeeded: {result.current_floor.name}")
else:
print(f"Floor switch failed: {result.message}")
return result

def switch_via_transition(self, floor_id: str, transition_id: str):
"""Switch floors through a transition"""
request = SwitchFloor.Request()
request.floor_id = floor_id
request.use_transition = True
request.transition_id = transition_id

future = self.client.call_async(request)
rclpy.spin_until_future_complete(self, future)
return future.result()

rclpy.init()
switcher = FloorSwitcher()

# Switch directly to floor 2F
switcher.switch_direct('2F', x=5.0, y=3.0, theta=1.57)

# Switch via elevator
switcher.switch_via_transition('3F', 'elevator_main')

rclpy.shutdown()

Example 3

C++
#include <rclcpp/rclcpp.hpp>
#include <map_manager/srv/switch_floor.hpp>
#include <geometry_msgs/msg/pose2_d.hpp>

class FloorSwitcher : public rclcpp::Node {
public:
FloorSwitcher() : Node("floor_switcher") {
client_ = create_client<map_manager::srv::SwitchFloor>(
"/switch_floor");
client_->wait_for_service();
}

bool switch_direct(const std::string& floor_id,
double x = 0.0, double y = 0.0, double theta = 0.0) {
auto request = std::make_shared<map_manager::srv::SwitchFloor::Request>();
request->floor_id = floor_id;
request->initial_pose.x = x;
request->initial_pose.y = y;
request->initial_pose.theta = theta;
request->use_transition = false;

auto future = client_->async_send_request(request);
if (rclcpp::spin_until_future_complete(shared_from_this(), future) ==
rclcpp::FutureReturnCode::SUCCESS) {
auto result = future.get();
RCLCPP_INFO(get_logger(), "Floor switch %s: %s",
result->success ? "succeeded" : "failed", result->message.c_str());
return result->success;
}
return false;
}

private:
rclcpp::Client<map_manager::srv::SwitchFloor>::SharedPtr client_;
};

Floor-Switching Sequence

  1. Verify that the target floor exists.
  2. When a transition is requested, verify that the transition is valid and available.
  3. Notify the mapping and localization module to load the target floor's localization map.
  4. Update the current-floor state.
  5. Publish the floor-switch event.

Notes

  • Ensure the target floor has been loaded before switching.
  • When using a floor transition, place the robot near the transition point.
  • After a successful switch, relocalize the robot or use the target pose supplied by the transition.