1317.12 ROS2 서비스 기반 노드 간 상호작용
1. ROS2 서비스의 개요
ROS2 서비스(Service)는 동기적 요청-응답(request-response) 패턴의 통신 메커니즘이다. 클라이언트가 요청 메시지를 전송하면 서버가 처리 후 응답 메시지를 반환한다. PlanSys2에서 서비스는 도메인 정보 조회, 세계 상태 관리, 계획 생성 등 즉각적 응답이 필요한 상호 작용에 사용된다.
2. PlanSys2의 서비스 사용 패턴
2.1 도메인 정보 조회
Domain Expert 노드가 서비스 서버로, 다른 노드와 외부 클라이언트가 서비스 클라이언트로 동작한다:
// 서비스 서버 (Domain Expert 내부)
auto get_types_srv = create_service<plansys2_msgs::srv::GetDomainTypes>(
"get_domain_types",
std::bind(&DomainExpertNode::getTypesCallback, this, _1, _2));
// 서비스 콜백
void getTypesCallback(
const std::shared_ptr<plansys2_msgs::srv::GetDomainTypes::Request> request,
std::shared_ptr<plansys2_msgs::srv::GetDomainTypes::Response> response)
{
response->types = domain_expert_->getTypes();
response->success = true;
}
// 서비스 클라이언트 (DomainExpertClient)
auto client = create_client<plansys2_msgs::srv::GetDomainTypes>("get_domain_types");
auto request = std::make_shared<plansys2_msgs::srv::GetDomainTypes::Request>();
auto future = client->async_send_request(request);
if (rclcpp::spin_until_future_complete(node, future) == rclcpp::FutureReturnCode::SUCCESS) {
auto response = future.get();
return response->types;
}
2.2 세계 상태 관리
Problem Expert 노드가 서비스 서버로, 외부 노드(센서 처리, 상태 모니터링)와 Executor가 서비스 클라이언트로 동작한다:
// 술어 추가 서비스
auto add_pred_srv = create_service<plansys2_msgs::srv::AddPredicate>(
"add_predicate",
std::bind(&ProblemExpertNode::addPredicateCallback, this, _1, _2));
void addPredicateCallback(
const std::shared_ptr<plansys2_msgs::srv::AddPredicate::Request> request,
std::shared_ptr<plansys2_msgs::srv::AddPredicate::Response> response)
{
response->success = problem_expert_->addPredicate(
plansys2::Predicate(request->predicate));
}
2.3 계획 생성
Planner 노드가 서비스 서버로, 계획 요청 노드가 클라이언트로 동작한다:
// 계획 생성 서비스 호출
auto planner_client = create_client<plansys2_msgs::srv::GetPlan>("get_plan");
auto request = std::make_shared<plansys2_msgs::srv::GetPlan::Request>();
request->domain = domain_text;
request->problem = problem_text;
auto future = planner_client->async_send_request(request);
3. 클라이언트 라이브러리의 서비스 추상화
PlanSys2의 클라이언트 라이브러리는 ROS2 서비스 호출을 고수준 메서드로 추상화한다:
// 직접 서비스 호출 (저수준)
auto client = create_client<plansys2_msgs::srv::AddPredicate>("add_predicate");
auto request = std::make_shared<plansys2_msgs::srv::AddPredicate::Request>();
request->predicate = "(robot_at robot1 wp1)";
auto future = client->async_send_request(request);
// ... future 대기 및 결과 처리
// 클라이언트 라이브러리 사용 (고수준)
auto problem_client = std::make_shared<plansys2::ProblemExpertClient>();
bool success = problem_client->addPredicate(plansys2::Predicate("(robot_at robot1 wp1)"));
4. 서비스 통신의 동기적 특성과 비동기 처리
ROS2 서비스는 본질적으로 동기적이지만, async_send_request를 사용하여 비동기적으로 호출할 수 있다. PlanSys2의 클라이언트 라이브러리는 내부적으로 비동기 호출과 타임아웃 처리를 수행하여, 서비스 서버의 일시적 비가용 상태에 대응한다.
5. 서비스 가용성 확인
PlanSys2의 클라이언트 라이브러리는 서비스 서버의 가용성을 자동으로 확인한다:
// 서비스 대기 (타임아웃 포함)
if (!client->wait_for_service(std::chrono::seconds(5))) {
RCLCPP_ERROR(get_logger(), "Service not available");
return false;
}
6. 참고 문헌
- Gonzalez, F., Martin, F., Matellán, V., & Rodriguez, F. J. (2021). “PlanSys2: A Planning System Framework for ROS2.” IEEE ICARSC.
- Macenski, S., Foote, T., Gerkey, B., Lalancette, C., & Woodall, W. (2022). “Robot Operating System 2: Design, Architecture, and Uses in the Wild.” Science Robotics, 7(66), eabm6074.