ros는 여러개의 노드가 비동기 환경에서 작동하는 운영체제이다.
그래서 콜백함수를 호출하는 것에도 여러 규칙이 적용되는데,
사용자는 spin과 spinOnce를 사용해서 콜백 함수를 다루게 된다.
spin과 spinOnce는 둘 다 큐를 사용해서 먼저 요쳥된 콜백함수부터 처리한다는 공통점이 있지만 큰 차이점이 있다.
spin과 spinOnce의 공통점과 차이점
ros::spin | ros::spinOnce | |
공통점 | 큐에 요청된 콜백함수를 처리함 | |
차이점 | 프로그램이 종료될 때 까지 반복 | 호출 시점까지 요청된 콜백함수를 처리 |
spinOnce는 현재까지 요청된 콜백 함수를 모두 호출하고 코드의 다음부분으로 넘어가지만,
spin은 노드가 shutdown되거나 Ctrl+C로 정지되기 이전까지 무한루프처럼 동작하며 콜백함수를 끊임없이 처리한다.
즉, 코드 상에 ros::spin이 있다면, 특별한 방법 없이는 해당 spin 아래 있는 모든 함수는 실행되지 않는 것이다.
ros::spin의 구현
while (ros::ok())
{
ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1));
}
spin은 위와같이 연결이 끊기기 전까지 지속되며 콜백함수를 호출하는 함수가 무한루프 안에 존재한다.
ros::spinOnce의 구현
ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0));
spinOnce는 spin에서 while이 빠져있는 형태이며, 호출되는 순간 콜백요청 큐에 쌓여있는 모든 요청을 처리하고 종료된다. 그러므로 spinOnce는 while 내부에 ros::Rate의 sleep메소드를 활용하는 경우가 일반적이다.
일반적인 spinOnce의 사용
ros::Rate r(10); // 10헤르츠
while (ros::ok())
{
~~~~~~~~ // 사용자의 작업
ros::spinOnce(); // 콜백함수 호출
r.sleep(); // 일시정지
}
spinOnce는 일반적으로 위와 같이 사용된다.
콜백함수를 어느정도 빠르기로 처리할지 헤르츠를 설정하고, while의 조건문에서 ros::ok로 노드의 종료 여부를 판단한 후 사용자가 하고싶은 작업을 실행한다.
그래고 spinOnce를 통해서 사용자의 작업이 진행되는 동안 쌓인 콜백함수 요청을 처리하고, sleep을 통해서 원하는 만큼 기다린 후 다시 while문을 통해서 이전까지의 작업을 반복하는 것이다.