제어명령을 로봇으로 전달 - dingdongdengdong/astra_ws GitHub Wiki

index.js의 코드 흐름을 webserver.pyteleoprator.py 파일을 참고하여 자세히 설명하겠습니다. index.js는 WebRTC를 활용하여 로봇의 비디오 스트림을 수신하고, 사용자의 입력(키보드, 페달, 카메라)을 처리해 로봇을 제어하며, 로봇의 상태를 UI에 반영하는 클라이언트 측 스크립트입니다. 아래에서 주요 기능을 단계별로 분석하고, 두 파이썬 파일과의 상호작용을 설명하겠습니다.


1. 웹 페이지 로드 및 초기 설정

  • 동작 개요:

    • 페이지가 로드되면 초기 설정이 이루어집니다.
    • window.addEventListener('load', function () { ... })에서 실행되며, 즉시 스트림을 시작하지 않고 사용자에게 "Click the start stream button, or press t to start stream." 메시지를 표시합니다.
    • 키보드 이벤트 리스너가 설정되어 사용자가 키를 누르면 제어 명령이 생성됩니다.
    • controlCommTarget에 'fromServer' 이벤트 리스너가 등록되어 서버로부터의 응답을 처리하고 UI를 업데이트합니다.
  • 세부 사항:

    • 사용자가 스트림을 시작하기 전까지 비디오 스트림이나 데이터 채널은 활성화되지 않습니다.
    • 키보드 입력은 이후 로봇 제어 명령으로 변환됩니다.

2. 스트림 시작 (start 함수)

  • 동작 개요:

    • async function start() { ... }는 사용자가 'start' 버튼을 클릭하거나 't' 키를 누르면 호출됩니다.
    • WebRTC 피어 연결(RTCPeerConnection)을 생성하고, 비디오 스트림 수신을 위한 설정을 진행합니다.
  • 세부 사항:

    • 세 개의 비디오 트랙(머리, 왼쪽 손목, 오른쪽 손목)을 수신하기 위해 트랜시버를 추가합니다.
    • 데이터 채널(hand, pedal, control)을 생성하고, 각 채널에 이벤트 리스너를 설정합니다.
    • ICE 후보 수집이 완료되면 /offer 엔드포인트로 POST 요청을 보내 SDP offer를 전송하고, 서버로부터 SDP answer를 받아 설정합니다.
  • webserver.py와의 상호작용:

    • webserver.pyoffer 함수가 /offer 엔드포인트를 처리합니다.
    • 클라이언트가 보낸 SDP offer를 받아 RTCPeerConnection을 설정하고, FeedableVideoStreamTrack을 통해 비디오 스트림을 준비한 후 SDP answer를 반환합니다.

3. 비디오 스트림 수신 및 표시

  • 동작 개요:

    • pc.addEventListener('track', function (evt) { ... })에서 WebRTC 연결로부터 'track' 이벤트가 발생하면 수신된 비디오 트랙을 처리합니다.
    • MID(미디어 ID)를 기반으로 머리, 왼쪽 손목, 오른쪽 손목 비디오를 구분하여 HTML 비디오 요소에 연결합니다.
  • webserver.py와의 상호작용:

    • webserver.pyfeed_webserver 또는 feed_webserver_av 함수가 카메라로부터 이미지를 캡처합니다.
    • 캡처된 이미지는 FeedableVideoStreamTrack에 공급되고, WebRTC를 통해 클라이언트로 전송되어 비디오 요소에 표시됩니다.

4. 데이터 채널을 통한 통신

index.js는 세 개의 데이터 채널을 통해 서버와 통신합니다.

(1) hand 채널

  • 동작:
    • capture 함수에서 사용자의 카메라로 ArUco 마커를 감지하고, 결과를 JSON으로 직렬화하여 handChannel을 통해 서버로 전송합니다.
  • webserver.py와의 상호작용:
    • webserver.pyon_datachannel에서 "hand" 채널 메시지를 수신하고, hand_cb로 전달합니다.
  • teleoprator.py와의 상호작용:
    • teleoprator.pyhand_cb에서 ArUco 마커 정보를 처리해 로봇의 목표 자세를 계산하고, 로봇의 움직임을 제어합니다.

(2) pedal 채널

  • 동작:
    • connectPedal 함수에서 시리얼 포트를 통해 페달의 상태를 읽고, 보정된 값을 JSON으로 직렬화하여 pedalChannel을 통해 전송합니다.
  • webserver.py와의 상호작용:
    • webserver.pyon_datachannel에서 "pedal" 채널 메시지를 수신하고, pedal_cb로 전달합니다.
  • teleoprator.py와의 상호작용:
    • teleoprator.pypedal_cb에서 페달 값을 처리해 로봇의 그리퍼나 리프트 동작을 제어합니다.

(3) control 채널

  • 동작:
    • 키보드 이벤트에서 생성된 제어 명령을 controlChannel을 통해 서버로 전송하고, 서버의 응답을 받아 UI를 업데이트합니다.
  • webserver.py와의 상호작용:
    • webserver.pyon_datachannel에서 "control" 채널 메시지를 수신하고, control_cb로 전달합니다.
  • teleoprator.py와의 상호작용:
    • teleoprator.pycontrol_cb에서 명령을 처리해 로봇의 모드를 변경하거나 리셋, 완료 등의 동작을 수행합니다.

5. 카메라 캡처 및 ArUco 마커 감지 (capture 함수)

  • 동작 개요:

    • async function capture() { ... }는 사용자의 카메라를 열고, OpenCV.js를 사용해 ArUco 마커를 감지합니다.
    • 감지된 마커의 코너와 ID를 JSON으로 직렬화하여 handChannel로 전송하고, 디버깅용 캔버스에 결과를 그립니다.
  • teleoprator.py와의 상호작용:

    • teleoprator.pyhand_cb에서 수신된 데이터를 기반으로 로봇의 목표 자세를 계산합니다.

6. 페달 연결 및 데이터 전송 (connectPedal 함수)

  • 동작 개요:

    • async function connectPedal() { ... }는 시리얼 포트를 통해 페달 장치와 연결하고, 페달 상태를 주기적으로 읽습니다.
    • 값을 보정하고 JSON으로 직렬화하여 pedalChannel로 전송합니다.
  • teleoprator.py와의 상호작용:

    • teleoprator.pypedal_cb에서 페달 데이터를 받아 로봇의 동작(예: 그리퍼, 리프트)을 제어합니다.

7. 키보드 제어 명령 처리

  • 동작 개요:

    • document.addEventListener("keydown", ... )에서 사용자가 특정 키를 누르면 해당 키에 매핑된 제어 명령을 생성합니다.
    • 명령은 controlCommTarget.dispatchEvent를 통해 'toServer' 이벤트로 전달되고, controlChannel을 통해 서버로 전송됩니다.
  • teleoprator.py와의 상호작용:

    • teleoprator.pycontrol_cb에서 명령을 처리해 로봇의 모드 변경, 리셋, 완료 등을 수행합니다.

8. 서버 응답 처리 및 UI 업데이트

  • 동작 개요:

    • controlCommTarget.addEventListener('fromServer', ... )에서 서버로부터 수신된 메시지를 파싱하여 UI를 업데이트합니다.
    • 예: 텔레오퍼레이션 모드나 그리퍼 잠금 상태를 표시합니다.
  • teleoprator.py와의 상호작용:

    • teleoprator.py에서 로봇 상태나 이벤트를 webserver.control_datachannel_log를 통해 클라이언트로 전송하면, index.js가 이를 UI에 반영합니다.

전체 흐름 요약

  1. 페이지 로드: 초기 설정 및 이벤트 리스너 등록.
  2. 스트림 시작: 'start' 버튼 클릭 또는 't' 키 입력으로 WebRTC 연결 설정 및 비디오 스트림 수신.
  3. 비디오 표시: 수신된 비디오 트랙을 HTML 요소에 연결.
  4. 데이터 채널 통신:
    • hand: ArUco 마커 감지 결과 전송.
    • pedal: 페달 상태 전송.
    • control: 제어 명령 전송 및 응답 수신.
  5. 카메라 캡처: ArUco 마커 감지 및 결과 전송.
  6. 페달 연결: 페달 데이터 읽기 및 전송.
  7. 키보드 제어: 키 입력을 명령으로 변환해 전송.
  8. UI 업데이트: 서버 응답을 받아 UI 반영.

index.js는 WebRTC를 통해 webserver.py로부터 비디오 스트림을 수신하고, 사용자의 입력을 teleoprator.py로 전달해 로봇을 제어하며, 상태를 실시간으로 UI에 반영합니다. webserver.py는 비디오 스트림 제공과 데이터 중계를, teleoprator.py는 로봇 제어 로직을 담당합니다.