토픽·서비스·액션 선택
55분 안팎
학습 목표
센서 스트림·설정 조회·목표 이동에 맞는 통신 계약과 이유를 제출합니다.
개념
통신 이름보다 완료의 의미를 먼저 정합니다
자율 이동 로봇의 센서 화면에 값이 보이기 시작했습니다. 이제 관제 담당자가 제한 속도를 확인하고 목표점 이동을 요청하려 합니다. 세 기능을 모두 같은 센서 토픽에 넣으면 어떤 요청에 답한 것인지, 이동을 접수한 것인지 끝낸 것인지 구분하기 어렵습니다. 이번 목표는 센서 스트림·설정 조회·목표 이동을 나누고 각 계약을 선택한 이유를 문서로 설명하는 것입니다.
선택 전에 네 가지를 묻습니다. 데이터가 계속 생기는지, 특정 요청에 대한 응답이 필요한지, 완료까지 작업 상태를 보관해야 하는지, 진행 확인과 취소가 필요한지입니다. 메시지가 크거나 작다는 사실만으로 결정하지 않습니다. 같은 좌표도 현재 위치 관측이면 스트림이고, 도착해야 할 목적지이면 작업 목표입니다. 필드 모양이 같더라도 수명과 책임은 달라집니다.
센서 스트림은 관측을 전달합니다
앞 모듈의 /robot/range_status는 측정 거리와 결함 상태를 이어서 알리는 토픽입니다. 발행자는 화면의 설정 조회 요청을 기다리지 않고 관측을 발행합니다. 상태 표시가 잠시 늦어져도 다음 관측을 받아 갱신할 수 있도록 최신 항목을 남기는 큐 정책을 썼습니다. 측정 seq·stamp_s와 발행 pub_seq·pub_s는 의미가 달랐으며 이번 모듈에서도 그 구분을 유지합니다.
토픽 하나를 받아 화면이 갱신됐다는 사실은 특정 이동 명령이 성공했다는 증거가 아닙니다. 센서의 거리와 목표까지의 거리는 기준도 다릅니다. 센서 거리 range_m를 목표 이동의 성공 조건에 직접 대입하면 장애물까지 가까워졌다는 사실을 도착으로 오해할 수 있습니다. 관측 경로는 유지하고 이동 목표의 수명은 별도 관리합니다.
설정 조회는 짧은 질문과 답으로 묶습니다
관제는 max_speed_mps 값을 알고 싶습니다. 요청에 id와 key를 넣고 응답에 같은 id, ok, code, value를 넣으면 어느 질문에 대한 답인지 확인할 수 있습니다. 서버가 한 번 읽어 바로 반환할 수 있고 중간 진행을 보고할 필요가 없으므로 서비스 형태의 계약을 택합니다. 여기서 서비스는 요청·응답의 역할을 말하며 Python 함수의 반환값이 실제 네트워크 서비스를 구현하지는 않습니다.
응답을 못 받았다는 사실과 UNKNOWN_KEY 응답을 받았다는 사실은 다릅니다. 전자는 대기 기한, 서버 생존, 전송 상태를 점검해야 합니다. 후자는 서버까지 요청이 도달했고 키가 계약에 없다는 업무 결과입니다. 클라이언트가 비동기로 호출해도 질문과 답의 의미는 서비스로 남습니다. 비동기 호출이라는 구현 방법만으로 액션이 되는 것은 아닙니다.
목표 이동은 진행과 종료를 구분합니다
목표점은 즉시 도착할 수 없는 작업입니다. 관제는 접수 결과를 먼저 확인하고, 실행 중 남은 거리 피드백을 받으며, 나중에 최종 결과를 조회해야 합니다. 중간 취소도 요구하므로 액션 형태가 적합합니다. 접수 응답은 목표를 관리하기 시작했다는 뜻이고 성공 결과는 지정 도착 조건을 만족한 뒤 작업을 종료했다는 뜻입니다. 두 응답을 같은 성공 플래그로 합치지 않습니다.
피드백이 1.0m에서 0.5m로 줄어도 최종 성공이 확정되지는 않습니다. 다음 관측에서 장애물이나 구동 결함이 생길 수 있습니다. 반대로 진행 메시지 몇 개가 늦었다는 이유만으로 결과를 실패로 덮어쓰지도 않습니다. 작업 id로 관측을 연결하고 종료 결과를 별도로 보존합니다. 피드백 빈도와 취소 지연은 구현 및 운전 요구에 맞춰 정할 항목입니다.
계약표에 경계와 단위를 담습니다
표의 열은 기능, 생산자, 소비자, 입력, 응답 또는 피드백, 종료 기준, 실패 처리로 잡습니다. 센서는 sensor_node에서 status_node로 거리 m와 측정 시각 s를 전달합니다. 설정 조회는 관제에서 설정 역할로 key를 보내 값을 받습니다. 이동은 관제에서 이동 역할로 id·map 좌표 m·속도 상한 m/s를 보내고 같은 id의 거리와 결과를 받습니다.
이 트랙의 실행 도구는 Python 3, gcc, bash입니다. 브라우저 실습은 표준 입력을 읽어 표준 출력으로만 답하고 디버깅 로그를 채점 출력에 섞지 않습니다. 로컬 실습은 starter.zip을 별도 폴더에 풀어 bash check.sh로 확인합니다. 테스트의 기대값을 바꾸는 대신 TODO를 고칩니다. solution.zip은 비교용이며 기존 프로젝트의 회귀 코드가 유지됐는지도 확인합니다.
현장의 추가 요구를 판단합니다
이동 시작과 종료만 있는 첫 시제품에서는 서비스 호출 뒤 완료를 기다리자는 제안이 나올 수 있습니다. 그 제안이 어떤 진행 정보와 취소 경로를 생략하는지 요구사항과 비교합니다. 이번 시나리오는 진행 표시와 취소가 있으므로 액션을 고릅니다. 반대로 단순 설정 조회에 목표 이력과 취소 상태를 붙이면 불필요한 수명 관리가 늘어납니다. 선택은 기능의 요구에서 설명합니다.
토픽으로 명령을 전달하는 시스템도 만들 수 있지만 그 자체로 목표 접수·중복 판정·결과 조회 계약이 생기지는 않습니다. 직접 만든 프로토콜이라면 누락한 책임을 따로 구현해야 합니다. 이번 교육에서는 세 역할을 명확히 나누어 리뷰 부담을 줄입니다. 통신 수단 하나가 신뢰성, 안전성, 정확히 한 번 실행을 모두 보장한다고 주장하지 않습니다.
PC 모델과 ROS 2 대응을 분리합니다
로컬 코드의 문자열 id는 목표를 구별하는 교육용 값입니다. 실제 ROS 2 액션에서는 목표 식별자와 상태 전달, 결과 요청 등 통신 요소가 함께 작동합니다. PC의 딕셔너리와 함수 호출 테스트는 DDS 발견이나 콜백 스케줄을 시험하지 않습니다. 제출물에 PC에서 확인한 계약과 실제 rclpy 서버·클라이언트로 확인할 항목을 각각 적습니다.
ROS 2의 상세 통신 구조와 서비스 API는 더 읽기로 이어갑니다. 공식 액션 설계 문서는 목표 접수, 실행, 취소 처리와 종료 상태를 나눕니다. 이 모듈은 그 구분을 자율 이동 프로젝트에 적용합니다. 실제 API 명령을 실행한 것으로 꾸미지 않고, 실행 로그가 있는 PC 예제만 따라하기 출력에 기록합니다.
설계 검토를 마칩니다
계약표를 읽는 동료에게 “센서 한 건을 놓치면 어떻게 되는가”, “조회 키가 없으면 어떤 답인가”, “이동 접수 뒤 언제 종료되는가”를 물어봅니다. 이 질문에 같은 문장으로 답한다면 세 경계가 충분히 나뉘지 않은 것입니다. 각 행에 실패 상황 하나와 관찰 근거 하나를 추가하면 선택의 이유가 더 명확해집니다.
마지막으로 취소 요청을 받았다는 응답만으로 물리적 정지를 증명하지 않는다고 적습니다. 뒤 레슨에서는 C HAL 출력 확인을 결과 기록에 연결하지만 그것도 PC 출력 증거입니다. 실제 모터 감속과 브레이크 동작은 별도 시험입니다. 이번 제출물은 구현자가 어떤 책임을 다음 단계에서 채워야 하는지 알 수 있는 인터페이스 결정 기록입니다.
사실 확인 참고: ROS 2 공식 액션 설계의 목표 수명과 상태 구분을 확인합니다.
따라하기
요구를 계약으로 분류합니다
세 기능의 요구를 사전에 연결해 분류표를 출력합니다.
contracts={"sensor_stream":"TOPIC","config_lookup":"SERVICE","move_goal":"ACTION"}
for task,kind in contracts.items():
print(task+" -> "+kind)실행 결과
sensor_stream -> TOPIC config_lookup -> SERVICE move_goal -> ACTION
접수와 종료를 분리합니다
관제 기록에 같은 id의 서로 다른 시점을 넣습니다.
events=[("g1","ACCEPTED"),("g1","EXECUTING"),("g1","SUCCEEDED")]
for gid,state in events:
print(gid,state,"terminal="+str(state in {"SUCCEEDED","ABORTED","CANCELED"}))실행 결과
g1 ACCEPTED terminal=False g1 EXECUTING terminal=False g1 SUCCEEDED terminal=True
단위를 계약표에 붙입니다
입력 필드의 단위를 확인합니다. 이 출력은 통신 테스트가 아니라 계약표 생성입니다.
fields={"x_m":"m in map","y_m":"m in map","max_speed_mps":"m/s","distance_m":"m to goal"}
for key,unit in fields.items():
print(key+": "+unit)실행 결과
x_m: m in map y_m: m in map max_speed_mps: m/s distance_m: m to goal
선택 기록을 제출합니다
센서 스트림·설정 조회·목표 이동 각 행에 생산자·소비자·요청·응답·진행·종료·오류를 적습니다. 이동에서 취소 접수와 출력 확인 뒤 종료를 따로 표시하고 실제 ROS 2 후속 항목 두 개를 작성합니다.
확인 문제
실습
통신 계약표 3행과 선택 이유를 제출합니다. 각 행에 생산자·소비자·단위·응답 필요 여부·진행·취소·종료·오류 사례를 넣습니다. 목표 접수와 도착을 구별하고, PC 검증과 실제 ROS 2 후속 확인 두 가지를 나눕니다. “비동기라 액션” 또는 “토픽 수신이라 이동 성공”으로 설명하지 않는지 검토합니다.
더 읽기
면접 질문
- ROS 2 토픽과 서비스, 액션의 선택 기준을 설명해 주시면 됩니다.