6.6.2 minimal_rt_monitoring_sample.cpp

이 예제(2_minimal_rt_monitoring_sample.cpp)는 DRFLEx API를 사용한 최소한의 실시간 모니터링 구성을 보여 줍니다.

  • connect_rt_control()로 실시간(RT) 모니터링 채널을 열고,

  • set_rt_control_output()으로 RT 세션을 설정하고,

  • RT 모니터링 콜백(set_on_rt_monitoring_data)을 등록한 다음,

  • 간단한 콘솔 입력으로 RT 모니터링을 시작하고 정지합니다.

2_minimal_rt_monitoring_sample

주의

실시간 모니터링과 제어는 실제 로봇 시스템에서만 지원합니다. 샘플은 IP_ADDRESS를 127.0.0.1로 설정하므로, 실행하기 전에 실제 컨트롤러의 IP 주소(예: 192.168.137.100)로 바꾸세요.

이 예제의 경로는 다음과 같습니다.
API-DRFL/example/Linux_64/2_minimal_rt_monitoring_sample.cpp

예제는 Doosan Robotics API-DRFL GitHub에서 확인하세요.

개요 및 전역 설정

샘플은 먼저 DRCF 프로토콜 버전을 선택하고 전역 DRFLEx 인스턴스를 생성합니다.

샘플은 컴파일러가 DRCF_VERSION을 정의하지 않으면 2로 설정합니다. DRCF v3 컨트롤러에서는 컴파일러에 -DDRCF_VERSION=3을 전달하세요.

#ifndef DRCF_VERSION
#define DRCF_VERSION 2 // DRCF 버전에 따라 2 또는 3으로 설정하거나, -DDRCF_VERSION=3을 전달합니다.
#endif

#include "../../include/DRFLEx.h"

#include <cstring>
#include <iostream>
#include <thread>

using namespace DRAFramework;
// ...
const std::string IP_ADDRESS = "127.0.0.1";
CDRFLEx robot; // API 호출용 인스턴스

bool get_control_access = false; // 제어권 확인용 변수
bool is_standby = false; // 로봇 상태가 대기 상태인지 확인하는 변수입니다.

#define GREEN  "\033[1;32m"
#define CYAN   "\033[1;36m"
  • DRCF_VERSION: 컨트롤러 펌웨어와 일치해야 합니다(예: 2 또는 3).

  • IP_ADDRESS: 샘플에서는 127.0.0.1로 설정되어 있습니다. 실제 컨트롤러의 IP 주소로 바꾸세요.

  • 색상 매크로(GREEN, CYAN)는 터미널에 색이 있는 출력을 표시할 때 사용합니다.

실시간 연결 설정

main 함수는 먼저 실시간 모니터링 연결을 엽니다.

int main(){
    // DRCF 컨트롤러에 연결합니다.
    bool ret = robot.connect_rt_control(IP_ADDRESS);
    std::cout << "open connection return value " << ret << std::endl;
    if (true != ret) {
        std::cout << "Cannot open connection to robot @ " << IP_ADDRESS
                        << std::endl;
        return 1;
    }
    // RT 모니터링에는 "제어권 획득"이 필요하지 않습니다.
    // 하지만 servoj_rt 같은 RT 쓰기에는 여전히 "제어권"과 "대기 상태"가 필요합니다.
  • connect_rt_control(IP_ADDRESS)는 컨트롤러와의 UDP 실시간 채널을 엽니다.

  • 연결에 실패하면(예: 잘못된 IP, 실제 컨트롤러 없음) 프로그램이 오류를 출력하고 종료합니다.

  • RT 모니터링만(읽기 전용) 할 때는 제어권(Control Authority)이 필요하지 않습니다.

  • RT 쓰기(예: servoj_rt, 토크 명령)에도 제어권은 필요하지 않습니다. 다만 로봇이 STATE_STANDBY 또는 STATE_MOVING 상태여야 합니다. 샘플의 주석에는 RT 쓰기에 제어권이 필요하다고 적혀 있지만, 이는 오래된 내용입니다.

RT 모니터링 콜백

이 예제는 실시간 상태 데이터를 받기 위해 람다 콜백을 등록합니다.

robot.set_on_rt_monitoring_data([](LPRT_OUTPUT_DATA_LIST data)->void{
    if (!data) return;
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    printf(GREEN "[%.3f] === Robot State ===\n", ms / 1000.0);
    printf(CYAN "Joint Position: ");
    for (int i = 0; i < 6; ++i) {
        printf("%.3f%s", data->actual_joint_position[i], (i < 5) ? ", " : "\n");
    }
    printf(CYAN "Joint Velocity: ");
    for (int i = 0; i < 6; ++i) {
        printf("%.3f%s", data->actual_joint_velocity[i], (i < 5) ? ", " : "\n");
    }
    printf(CYAN "Joint Torque: ");
    for (int i = 0; i < 6; ++i) {
        printf("%.3f%s", data->actual_joint_torque[i], (i < 5) ? ", " : "\n");
    }
    printf(CYAN "Gravity Torque: ");
    for (int i = 0; i < 6; ++i) {
        printf("%.3f%s", data->gravity_torque[i], (i < 5) ? ", " : "\n");
    }
    // 행렬 보기 좋게 출력
    auto print_matrix = [](const char* name, float mat[6][6]) {
        printf(CYAN "%s:\n", name);
        for (int i = 0; i < 6; ++i) {
            printf(CYAN "  [");
            for (int j = 0; j < 6; ++j) {
                printf(CYAN "%7.3f%s", mat[i][j], (j < 5) ? ", " : "");
            }
            printf(CYAN "]\n");
        }
    };
    print_matrix(CYAN "Jacobian Matrix", data->jacobian_matrix);
    print_matrix(CYAN "Mass Matrix", data->mass_matrix);
    print_matrix(CYAN "Coriolis Matrix", data->coriolis_matrix);

});

콜백은 data가 null이면 바로 반환합니다. 그렇지 않으면 로컬 시스템 시계 기준 타임스탬프, 조인트 위치, 조인트 속도, 조인트 토크, 중력 토크, 동역학 행렬(자코비안, 질량, 코리올리)을 출력합니다.

2_minimal_rt_monitoring_sample_result

  • RT 세션 설정 및 시작

콜백을 등록한 뒤 샘플은 set_rt_control_output()으로 RT 세션을 설정하고, Enter를 기다렸다가 start_rt_control()을 호출하고, 다시 Enter를 기다렸다가 disconnect_rt_control()을 호출합니다.

string version = "v1.0";
// 출력 설정이 모니터링 데이터 전송을 결정합니다. 주기의 단위는 초입니다.
float period = 0.01f; // 100 Hz
int losscount = 4;
std::cout << "RT Result " << robot.set_rt_control_output(version, period, losscount) << std::endl;

std::cout << "Press Enter to continue..." ;
std::cin.get();  // 사용자가 Enter를 누를 때까지 대기
robot.start_rt_control();

std::cout << "Press Enter to terminate..." ;
std::cin.get();  // 사용자가 Enter를 누를 때까지 대기
robot.disconnect_rt_control();
return 0;

RT 출력

RT 세션을 시작하기 전에 프로그램은 컨트롤러가 RT 데이터를 보내는 주기를 설정하는 set_rt_control_output()을 호출합니다.

string version = "v1.0";
// 출력 설정이 모니터링 데이터 전송을 결정합니다. 주기의 단위는 초입니다.
float period = 0.01f; // 100 Hz
int losscount = 4;
std::cout << "RT Result " << robot.set_rt_control_output(version, period, losscount) << std::endl;
  • version = "v1.0": RT 프로토콜 버전을 선택합니다.

  • period = 0.01f: 통신 주기(초)인 fPeriod 인수로 전달됩니다(100 Hz).

  • losscount = 4: 허용하는 연속 손실 횟수인 nLossCnt 인수로 전달됩니다.

매개변수는 set_rt_control_output을 참고하세요. 반환값은 콘솔에 출력됩니다. 반환값은 설정을 보냈다는 것만 알려 줄 뿐, 컨트롤러가 설정을 수락했다는 뜻은 아닙니다.

RT 모니터링 시작 및 정지

이 예제는 간단한 Enter 키 입력으로 RT 모니터링을 시작하고 정지합니다.

std::cout << "Press Enter to continue..." ;
std::cin.get();  // 사용자가 Enter를 누를 때까지 대기
robot.start_rt_control();

std::cout << "Press Enter to terminate..." ;
std::cin.get();  // 사용자가 Enter를 누를 때까지 대기
robot.disconnect_rt_control();
return 0;
  • 첫 번째 Enter 뒤에 샘플은 start_rt_control()을 호출합니다.

  • 두 번째 Enter 뒤에는 disconnect_rt_control()이 실시간 모니터링 채널을 닫고 프로그램이 종료됩니다.