1317.12 ROS2 서비스 기반 노드 간 상호작용

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.