제어명령을 로봇으로 전달 - dingdongdengdong/astra_ws GitHub Wiki
index.js
의 코드 흐름을 webserver.py
와 teleoprator.py
파일을 참고하여 자세히 설명하겠습니다. index.js
는 WebRTC를 활용하여 로봇의 비디오 스트림을 수신하고, 사용자의 입력(키보드, 페달, 카메라)을 처리해 로봇을 제어하며, 로봇의 상태를 UI에 반영하는 클라이언트 측 스크립트입니다. 아래에서 주요 기능을 단계별로 분석하고, 두 파이썬 파일과의 상호작용을 설명하겠습니다.
1. 웹 페이지 로드 및 초기 설정
-
동작 개요:
- 페이지가 로드되면 초기 설정이 이루어집니다.
window.addEventListener('load', function () { ... })
에서 실행되며, 즉시 스트림을 시작하지 않고 사용자에게 "Click the start stream button, or presst
to start stream." 메시지를 표시합니다.- 키보드 이벤트 리스너가 설정되어 사용자가 키를 누르면 제어 명령이 생성됩니다.
controlCommTarget
에 'fromServer' 이벤트 리스너가 등록되어 서버로부터의 응답을 처리하고 UI를 업데이트합니다.
-
세부 사항:
- 사용자가 스트림을 시작하기 전까지 비디오 스트림이나 데이터 채널은 활성화되지 않습니다.
- 키보드 입력은 이후 로봇 제어 명령으로 변환됩니다.
start
함수)
2. 스트림 시작 (-
동작 개요:
async function start() { ... }
는 사용자가 'start' 버튼을 클릭하거나 't' 키를 누르면 호출됩니다.- WebRTC 피어 연결(
RTCPeerConnection
)을 생성하고, 비디오 스트림 수신을 위한 설정을 진행합니다.
-
세부 사항:
- 세 개의 비디오 트랙(머리, 왼쪽 손목, 오른쪽 손목)을 수신하기 위해 트랜시버를 추가합니다.
- 데이터 채널(
hand
,pedal
,control
)을 생성하고, 각 채널에 이벤트 리스너를 설정합니다. - ICE 후보 수집이 완료되면
/offer
엔드포인트로 POST 요청을 보내 SDP offer를 전송하고, 서버로부터 SDP answer를 받아 설정합니다.
-
webserver.py와의 상호작용:
webserver.py
의offer
함수가/offer
엔드포인트를 처리합니다.- 클라이언트가 보낸 SDP offer를 받아
RTCPeerConnection
을 설정하고,FeedableVideoStreamTrack
을 통해 비디오 스트림을 준비한 후 SDP answer를 반환합니다.
3. 비디오 스트림 수신 및 표시
-
동작 개요:
pc.addEventListener('track', function (evt) { ... })
에서 WebRTC 연결로부터 'track' 이벤트가 발생하면 수신된 비디오 트랙을 처리합니다.- MID(미디어 ID)를 기반으로 머리, 왼쪽 손목, 오른쪽 손목 비디오를 구분하여 HTML 비디오 요소에 연결합니다.
-
webserver.py와의 상호작용:
webserver.py
의feed_webserver
또는feed_webserver_av
함수가 카메라로부터 이미지를 캡처합니다.- 캡처된 이미지는
FeedableVideoStreamTrack
에 공급되고, WebRTC를 통해 클라이언트로 전송되어 비디오 요소에 표시됩니다.
4. 데이터 채널을 통한 통신
index.js
는 세 개의 데이터 채널을 통해 서버와 통신합니다.
(1) hand 채널
- 동작:
capture
함수에서 사용자의 카메라로 ArUco 마커를 감지하고, 결과를 JSON으로 직렬화하여handChannel
을 통해 서버로 전송합니다.
- webserver.py와의 상호작용:
webserver.py
의on_datachannel
에서 "hand" 채널 메시지를 수신하고,hand_cb
로 전달합니다.
- teleoprator.py와의 상호작용:
teleoprator.py
의hand_cb
에서 ArUco 마커 정보를 처리해 로봇의 목표 자세를 계산하고, 로봇의 움직임을 제어합니다.
(2) pedal 채널
- 동작:
connectPedal
함수에서 시리얼 포트를 통해 페달의 상태를 읽고, 보정된 값을 JSON으로 직렬화하여pedalChannel
을 통해 전송합니다.
- webserver.py와의 상호작용:
webserver.py
의on_datachannel
에서 "pedal" 채널 메시지를 수신하고,pedal_cb
로 전달합니다.
- teleoprator.py와의 상호작용:
teleoprator.py
의pedal_cb
에서 페달 값을 처리해 로봇의 그리퍼나 리프트 동작을 제어합니다.
(3) control 채널
- 동작:
- 키보드 이벤트에서 생성된 제어 명령을
controlChannel
을 통해 서버로 전송하고, 서버의 응답을 받아 UI를 업데이트합니다.
- 키보드 이벤트에서 생성된 제어 명령을
- webserver.py와의 상호작용:
webserver.py
의on_datachannel
에서 "control" 채널 메시지를 수신하고,control_cb
로 전달합니다.
- teleoprator.py와의 상호작용:
teleoprator.py
의control_cb
에서 명령을 처리해 로봇의 모드를 변경하거나 리셋, 완료 등의 동작을 수행합니다.
capture
함수)
5. 카메라 캡처 및 ArUco 마커 감지 (-
동작 개요:
async function capture() { ... }
는 사용자의 카메라를 열고, OpenCV.js를 사용해 ArUco 마커를 감지합니다.- 감지된 마커의 코너와 ID를 JSON으로 직렬화하여
handChannel
로 전송하고, 디버깅용 캔버스에 결과를 그립니다.
-
teleoprator.py와의 상호작용:
teleoprator.py
의hand_cb
에서 수신된 데이터를 기반으로 로봇의 목표 자세를 계산합니다.
connectPedal
함수)
6. 페달 연결 및 데이터 전송 (-
동작 개요:
async function connectPedal() { ... }
는 시리얼 포트를 통해 페달 장치와 연결하고, 페달 상태를 주기적으로 읽습니다.- 값을 보정하고 JSON으로 직렬화하여
pedalChannel
로 전송합니다.
-
teleoprator.py와의 상호작용:
teleoprator.py
의pedal_cb
에서 페달 데이터를 받아 로봇의 동작(예: 그리퍼, 리프트)을 제어합니다.
7. 키보드 제어 명령 처리
-
동작 개요:
document.addEventListener("keydown", ... )
에서 사용자가 특정 키를 누르면 해당 키에 매핑된 제어 명령을 생성합니다.- 명령은
controlCommTarget.dispatchEvent
를 통해 'toServer' 이벤트로 전달되고,controlChannel
을 통해 서버로 전송됩니다.
-
teleoprator.py와의 상호작용:
teleoprator.py
의control_cb
에서 명령을 처리해 로봇의 모드 변경, 리셋, 완료 등을 수행합니다.
8. 서버 응답 처리 및 UI 업데이트
-
동작 개요:
controlCommTarget.addEventListener('fromServer', ... )
에서 서버로부터 수신된 메시지를 파싱하여 UI를 업데이트합니다.- 예: 텔레오퍼레이션 모드나 그리퍼 잠금 상태를 표시합니다.
-
teleoprator.py와의 상호작용:
teleoprator.py
에서 로봇 상태나 이벤트를webserver.control_datachannel_log
를 통해 클라이언트로 전송하면,index.js
가 이를 UI에 반영합니다.
전체 흐름 요약
- 페이지 로드: 초기 설정 및 이벤트 리스너 등록.
- 스트림 시작: 'start' 버튼 클릭 또는 't' 키 입력으로 WebRTC 연결 설정 및 비디오 스트림 수신.
- 비디오 표시: 수신된 비디오 트랙을 HTML 요소에 연결.
- 데이터 채널 통신:
hand
: ArUco 마커 감지 결과 전송.pedal
: 페달 상태 전송.control
: 제어 명령 전송 및 응답 수신.
- 카메라 캡처: ArUco 마커 감지 및 결과 전송.
- 페달 연결: 페달 데이터 읽기 및 전송.
- 키보드 제어: 키 입력을 명령으로 변환해 전송.
- UI 업데이트: 서버 응답을 받아 UI 반영.
index.js
는 WebRTC를 통해 webserver.py
로부터 비디오 스트림을 수신하고, 사용자의 입력을 teleoprator.py
로 전달해 로봇을 제어하며, 상태를 실시간으로 UI에 반영합니다. webserver.py
는 비디오 스트림 제공과 데이터 중계를, teleoprator.py
는 로봇 제어 로직을 담당합니다.