비동기 작업의 개념

ROS2에서 비동기 작업은 액션 서버와 클라이언트 사이에서 발생하는 통신의 중요한 부분이다. 비동기 작업은 시스템의 성능을 극대화하고, 동시에 여러 작업을 처리할 수 있게 하여 ROS2 액션이 매우 유연하게 동작하도록 한다.

비동기 작업의 기본 흐름

비동기 작업에서는 클라이언트가 요청을 보낸 후, 서버로부터 바로 응답을 기다리지 않고 다른 작업을 수행할 수 있다. 이는 특히 실시간 로봇 시스템에서 중요한데, 작업의 지연을 최소화하면서 다양한 센서와 모터, 계산 작업을 동시에 처리할 수 있기 때문이다.

비동기 작업의 기본 흐름을 다음과 같이 요약할 수 있다: 1. 클라이언트가 서버에 요청을 보냄 2. 서버는 요청을 받고 작업을 처리하며, 중간 상태 및 결과를 클라이언트에 전달 3. 클라이언트는 서버로부터의 응답을 기다리지 않고 다른 작업을 처리 4. 서버는 작업이 완료되면 최종 결과를 클라이언트로 전송

이 과정은 다음과 같은 도식으로 표현할 수 있다:

sequenceDiagram participant Client participant Server Client->>Server: 요청 전송 Server-->>Client: 처리 중 상태 (Feedback) Client->>Client: 다른 작업 처리 Server-->>Client: 최종 결과 전송

비동기 작업의 장점

1. 시스템 성능 향상

비동기 작업의 가장 큰 장점 중 하나는 시스템 성능을 극대화할 수 있다는 점이다. 로봇 시스템에서는 여러 작업이 동시에 이루어져야 하며, 특히 실시간 처리가 중요한 경우에 비동기 작업이 필수적이다. 예를 들어, 센서 데이터를 실시간으로 수집하면서 동시에 로봇의 동작을 제어할 수 있어야 하는 경우, 클라이언트가 서버로부터 응답을 기다리며 시간을 낭비하지 않고 다른 작업을 처리할 수 있다.

2. 자원의 효율적 활용

동기 작업에서는 클라이언트가 서버의 응답을 기다리는 동안 CPU 자원이 사용되지 않지만, 비동기 작업을 사용하면 클라이언트는 서버 응답을 기다리는 동안 다른 작업을 계속 처리할 수 있다. 이렇게 자원을 효율적으로 활용함으로써 더 많은 작업을 짧은 시간 내에 처리할 수 있다.

3. 높은 유연성

비동기 작업은 시스템의 유연성을 높여준다. 클라이언트가 여러 서버와 동시에 통신할 수 있으며, 각각의 작업이 독립적으로 처리되므로 시스템의 각 구성 요소가 서로의 상태에 구애받지 않고 동작할 수 있다. 이는 특히 복잡한 로봇 시스템에서 큰 장점이 된다.

비동기 작업의 활용 예시

로봇 팔 제어

로봇 팔을 제어하는 시스템에서, 비동기 작업은 로봇의 움직임을 최적화하는 데 사용될 수 있다. 예를 들어, 로봇이 물체를 잡고 이동하는 동안에도 다른 센서 데이터 처리나 상태 모니터링을 동시에 수행할 수 있다. 클라이언트는 물체 잡기 작업을 서버에 요청하고, 그 응답을 기다리는 동안 다른 센서 데이터를 분석하거나 다음 명령을 준비할 수 있다.

// ROS2 액션 서버 비동기 호출 예시
auto future_result = action_client->async_send_goal(goal);
if (rclcpp::spin_until_future_complete(node, future_result) ==
  rclcpp::executor::FutureReturnCode::SUCCESS) {
  // 작업 성공
} else {
  // 작업 실패
}

이 코드는 비동기 방식으로 액션을 요청하는 클라이언트의 예시이다. 클라이언트는 서버에 목표를 전송한 후 바로 결과를 기다리지 않고 다른 작업을 수행할 수 있다. 결과가 도착하면, 클라이언트는 결과에 대한 처리를 계속할 수 있다.

4. 확장성 있는 시스템 구축

비동기 작업을 통해 구축된 시스템은 확장성이 높다. 여러 클라이언트가 하나의 서버에 요청을 보낼 수 있으며, 각각의 요청은 독립적으로 처리된다. 예를 들어, 다중 로봇 시스템에서는 각 로봇이 개별적으로 작업을 요청하고 처리할 수 있어야 하는데, 비동기 작업을 활용하면 이를 손쉽게 구현할 수 있다.

다중 로봇 환경에서의 활용

다중 로봇 환경에서 각 로봇은 다양한 작업을 수행해야 한다. 이때 각 로봇은 하나의 중앙 서버에 작업을 요청할 수 있으며, 서버는 비동기적으로 각각의 요청을 처리한다. 클라이언트(로봇)는 서버로부터 응답을 기다리는 동안 다른 작업을 병렬로 수행할 수 있다. 예를 들어, 로봇 A는 경로 탐색을 요청하고, 로봇 B는 목표 도달 여부를 요청하는 상황에서 서버는 두 요청을 동시에 처리할 수 있다.

auto future_result_robotA = action_clientA->async_send_goal(goalA);
auto future_result_robotB = action_clientB->async_send_goal(goalB);

rclcpp::spin_until_future_complete(node, future_result_robotA);
rclcpp::spin_until_future_complete(node, future_result_robotB);

위 코드는 두 개의 클라이언트(로봇 A와 B)가 각각 비동기적으로 서버에 목표를 요청하는 예시이다. 각 클라이언트는 독립적으로 작업을 요청하고 처리할 수 있으며, 서버는 두 요청을 병렬로 처리하게 된다.

5. 낮은 지연 시간(Latency) 처리

비동기 작업은 지연 시간(Latency)을 줄이는 데에도 유용하다. 동기 작업의 경우, 서버로부터의 응답을 기다리면서 발생하는 지연이 있을 수 있다. 하지만 비동기 작업에서는 클라이언트가 응답을 기다리지 않고 다른 작업을 수행할 수 있기 때문에 전체 시스템의 처리 속도를 향상시킬 수 있다.

실시간 데이터 처리

로봇 시스템에서는 다양한 센서로부터 실시간 데이터를 수집하고 처리해야 하는데, 이 과정에서 동기 작업을 사용할 경우 지연이 발생할 수 있다. 예를 들어, 카메라 센서에서 이미지 데이터를 수집하고 이를 분석하는 작업을 서버에 요청한 후, 그 결과를 기다리면 다른 작업에 지장이 있을 수 있다. 비동기 작업을 활용하면 이미지 분석 요청을 서버에 보낸 후 다른 센서 데이터도 동시에 처리할 수 있다.

auto future_image_analysis = action_client->async_send_goal(image_goal);
auto future_lidar_processing = action_client->async_send_goal(lidar_goal);

if (rclcpp::spin_until_future_complete(node, future_image_analysis) == 
    rclcpp::executor::FutureReturnCode::SUCCESS) {
    // 이미지 분석 완료
}
if (rclcpp::spin_until_future_complete(node, future_lidar_processing) == 
    rclcpp::executor::FutureReturnCode::SUCCESS) {
    // 라이다 처리 완료
}

위 코드에서는 이미지 분석과 라이다 처리 두 작업을 비동기적으로 요청하고 처리하는 예시이다. 이렇게 비동기 작업을 사용함으로써 여러 작업을 동시에 효율적으로 처리할 수 있다.

6. 피드백 처리의 유용성

비동기 작업은 피드백(Feedback) 처리를 보다 유연하게 할 수 있게 해준다. 작업이 완료되기 전에 중간 결과를 서버로부터 받아볼 수 있으며, 이를 통해 클라이언트는 작업의 진행 상태를 모니터링하고 필요에 따라 동적으로 대응할 수 있다.

피드백을 활용한 상태 모니터링

로봇이 목표 지점까지 이동하는 작업에서, 로봇의 현재 위치나 경로 상태에 대한 피드백을 받아 클라이언트가 실시간으로 로봇의 상태를 모니터링할 수 있다. 만약 경로 상에서 문제가 발생하거나 장애물을 감지했을 경우, 즉시 대응할 수 있다.

void feedback_callback(const std::shared_ptr<const ActionFeedback> feedback) {
    RCLCPP_INFO(node->get_logger(), "현재 진행 상태: %f%%", feedback->progress);
}
auto future_result = action_client->async_send_goal(goal, feedback_callback);

이 예시에서는 액션의 피드백 콜백 함수를 통해 작업의 진행 상태를 실시간으로 받아 처리하는 방식이다. 피드백을 활용하면, 작업이 완료되기 전에 진행 상태를 미리 파악하고 상황에 맞게 조치를 취할 수 있다.