C++ IndyDCP3 클라이언트
C++에서 IndyDCP3 클라이언트를 사용하려면 아래 단계를 따르십시오. 이 가이드는 C++17 이상이 설정된 적절한 개발 환경을 갖추고 있다고 가정합니다.
설치 요구 사항
- 프로젝트 구성 및 빌드를 위한 CMake가 필요합니다.
- C++17 이상을 지원하는 C++ 컴파일러가 필요합니다.
- IndyDCP3 라이브러리 파일 및 헤더가 필요합니다.
설치 방법
Linux
1. gRPC 설치
다음 gRPC 설치 가이드는 gRPC 공식 웹사이트에 기재된 내용을 요약한 것입니다. 자세한 내용은 grpc.io를 참조하세요.
로컬로 설치된 패키지를 보관할 디렉토리를 선택하십시오. 이 페이지는 환경 변수 MY_INSTALL_DIR이 이 디렉토리 경로를 보유하고 있다고 가정합니다. 아래 터미널 명령을 통해 디렉터리가 있는지 확인하십시오.
로컬 bin 폴더를 경로 변수에 추가하십시오.
예를 들어:
CMake 설치 버전 3.13 이상의 CMake가 필요합니다. 다음 지침에 따라 설치하십시오:
CMake 버전을 확인하십시오:리눅스에서 시스템 전체 CMake 버전이 오래된 경우가 있습니다. 로컬 설치 디렉토리에 최신 버전을 설치하려면 다음 명령을 사용하십시오.
wget -q -O cmake-linux.sh https://github.com/Kitware/CMake/releases/download/v3.19.6/cmake-3.19.6-Linux-x86_64.sh
sh cmake-linux.sh -- --skip-license --prefix=$MY_INSTALL_DIR
rm cmake-linux.sh
기타 필요한 도구 설치 gRPC를 빌드하는 데 필요한 기본 도구를 설치하십시오:
grpc 저장소 및 하위 모듈 클론:
$ git clone --recurse-submodules -b v1.59.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc
gRPC 및 프로토콜 버퍼 빌드 및 설치
gRPC 애플리케이션은 종종 서비스 정의 및 데이터 직렬화를 위해 예제 코드에서와 같이 프로토콜 버퍼를 사용합니다. gRPC 및 프로토콜 버퍼를 빌드하고 로컬로 설치하려면 다음 명령을 실행하십시오:
cd grpc
mkdir -p cmake/build
pushd cmake/build
cmake -DgRPC_INSTALL=ON \
-DgRPC_BUILD_TESTS=OFF \
-DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR \
../..
make -j 4
make install
popd
Note
전역 설치 후 gRPC를 제거하는 간단한 방법이 없기 때문에 CMAKE_INSTALL_PREFIX를 적절히 설정하여 gRPC를 로컬에 설치하는 것이 강력히 권장됩니다.
2. 예제 다운로드 및 빌드
예제 저장소 클론
C++ 폴더로 이동
빌드 디렉토리 생성 및 이동
CMake 구성 실행 및 예제 빌드
Windows
이 설정에는 Visual Studio Code를 사용하는 것을 권장합니다.
1. 환경 설정
Visual Studio Code 설치 - 다음 확장 프로그램 설치: C/C++, C/C++ 확장 팩 및 CMake 도구.
vs_BuildTools 설치 - BuildTools 옵션에서 C++를 사용한 데스크톱 개발 및 Visual Studio 확장 개발을 선택하십시오.
2. gRPC 설치
모든 준비가 완료되면 개발자 명령 프롬프트를 열고 다음 명령을 실행하십시오:
빌드 폴더 생성
CMake를 사용하여 구성 및 빌드
cmake -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17 -DBUILD_SHARED_LIBS=OFF -DABSL_PROPAGATE_CXX_STD=ON -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX=..\..\..\install ../..
gRPC 빌드 및 설치
3. 예제 다운로드 및 빌드
예제 저장소 클론
Visual Studio Code 열고 neuromeka-package/cpp/ 폴더 열기 .vscode 폴더의 settings.json으로 빌드를 구성하십시오.
그런 다음 CMakeList.txt를 수정하십시오. 다음 줄을 변경하여 grpc 설치 디렉토리를 가리키도록 하십시오.
set(absl_DIR "E:/Example/install/lib/cmake/absl")
set(utf8_range_DIR "E:/Example/install/lib/cmake/utf8_range")
set(protobuf_DIR "E:/Example/install/cmake")
set(gRPC_DIR "E:/Example/install/lib/cmake/grpc")
Visual Studio Code에서 Ctrl+Shift+P를 누르거나 보기 -> 명령 팔레트로 이동하여 명령 팔레트를 열고 다음 명령을 선택하십시오: - CMake: Scan for kits: 컴퓨터에서 컴파일러를 검색합니다. - CMake: Select a kit: 특정 컴파일러(예: Visual Studio Build Tools 2022 Release - amd64)를 선택합니다.
작업이 완료되면 왼쪽 하단의 빌드 버튼을 누르십시오.
IndyDCP3 사용
클라이언트 개체를 생성하려면 IndyDCP3 라이브러리에서 IndyDCP3 클래스 헤더를 포함하고 로봇의 IP 주소로 초기화하십시오.
#include "indydcp3.h"
int main() {
IndyDCP3 indy("192.168.xxx.xxx");
// indy 객체를 사용하여 로봇과 상호작용...
return 0;
}
192.168.xxx.xxx: 로봇 컨트롤러의 IP 주소.
메서드 및 함수
IndyDCP3 객체를 사용하여 호출할 수 있는 프로토콜 함수 목록은 아래에 나와 있습니다. 각 함수의 사용 방법 및 입출력 예제를 참조하세요.
실시간 데이터 수집 함수
로봇의 현재 모션 상태, 제어 데이터, 상태, 서보 모터 상태, 오류 정보 및 프로그램 상태를 검색할 수 있습니다.
| 메서드 | 설명 |
|---|---|
get_robot_data() |
로봇 상태 데이터 |
get_control_state() |
제어 상태 |
get_motion_data() |
모션 데이터 |
get_servo_data() |
서보 데이터 |
get_violation_data() |
오류 데이터 |
get_program_data() |
로봇 프로그램 데이터 |
get_robot_data() 예제
Nrmk::IndyFramework::ControlData control_data;
bool is_success = indy.get_robot_data(control_data);
if (is_success) {
// control_data 처리
}
{
'running_mins': 6,
'running_secs': 11,
'op_state': 5,
'sim_mode': true,
'ref_frame': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
'tool_frame': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
'running_hours': 0
}
running_hours: 로봇 작동 시간running_mins: 로봇 작동 분running_secs: 로봇 작동 초op_state:OpState클래스에 정의된 로봇 상태OpState:SYSTEM_OFF(0),SYSTEM_ON(1),VIOLATE(2),RECOVER_HARD(3),RECOVER_SOFT(4),IDLE(5),MOVING(6),TEACHING(7),COLLISION(8),STOP_AND_OFF(9),COMPLIANCE(10),BRAKE_CONTROL(11),SYSTEM_RESET(12),SYSTEM_SWITCH(13),VIOLATE_HARD(15),MANUAL_RECOVER(16),TELE_OP(17)
get_control_state() 예제
Nrmk::IndyFramework::ControlData control_data;
bool is_success = indy.get_control_state(control_data);
if (is_success) {
// 관절 위치에 접근
for (int i = 0; i < control_data.q_size(); i++) {
float joint_position = control_data.q(i);
}
}
{
'q': [...],
'qdot': [...],
'qddot': [...],
'qdes': [...],
'qdotdes': [...],
'qddotdes': [...],
'p': [...],
'pdot': [...],
'pddot': [...],
'pdes': [...],
'pdotdes': [...],
'pddotdes': [...],
'tau': [...],
'tau_act': [...],
'tau_ext': [...],
'tau_jts': [...],
'tau_jts_raw1': [...],
'tau_jts_raw2': [...]
}
q,qdot,qddot: 각 관절의 현재 위치(도), 속도(도/초) 및 가속도(도/초²)qdes,qdotdes,qddotdes: 각 관절의 목표 위치(도), 속도(도/초) 및 가속도(도/초²)p,pdot,pddot: 현재 작업 공간 자세 위치(mm), 속도(mm/초) 및 가속도(mm/초²)pdes,pdotdes,pddotdes: 목표 작업 공간 자세 위치(mm), 속도(mm/초) 및 가속도(mm/초²)tau,tau_act,tau_ext: 각 관절의 현재 입력 토크, 실제 토크 및 외부 토크(Nm)tau_jts,tau_jts_raw1,tau_jts_raw2: 각 관절의 관절토크 센서 값
get_servo_data() 예제
Nrmk::IndyFramework::ServoData servo_data;
bool is_success = indy.get_servo_data(servo_data);
if (is_success) {
std::cout << "servo data:" << std::endl;
for (int i = 0; i < servo_data.temperatures_size(); i++){
std::cout << "temperature" << i << ": " << servo_data.temperatures(i) << std::endl;
}
}
else{
std::cout << "Failed to get_servo_data" << std::endl;
}
{
'status_codes': ['0x1237', '0x1237', '0x1237', '0x1237', '0x1237', '0x1237'],
'temperatures': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
'voltages': [48.0, 48.0, 48.0, 48.0, 48.0, 48.0],
'currents': [3.4812942e-18,
26.195215,
26.963966,
0.12320003,
0.55777645,
4.536144e-05],
'servo_actives': [true, true, true, true, true, true],
'brake_actives': [false, false, false, false, false, false]
}
status_codes: 각 관절 서보의 상태 코드(CiA402)temperatures: 각 관절 서보의 온도voltages: 각 관절 서보의 전압currents: 각 관절 서보의 전류servo_actives: 각 관절 서보의 활성화 상태(true/false)brake_actives: 각 관절 서보의 브레이크 활성화 상태(true/false)
get_violation_data() 예제
Nrmk::IndyFramework::ViolationData violation_data;
bool is_success = indy.get_violation_data(violation_data);
if (is_success) {
int j_index = violation_data.j_index();
}
{
'j_index': 3,
'i_args': [2],
'f_args': [0.03445887],
'violation_str': 'Collision Detected: joint (4/6), Error threshold , val 0.0345',
'violation_code': '0'
}
j_index: 위반이 발생한 관절의 인덱스i_args: 위반에 대한 정수 정보f_args: 위반에 대한 부동 소수점 정보violation_str: 오류 메시지
get_program_data() 예제
Nrmk::IndyFramework::ProgramData program_data;
bool is_success = indy.get_program_data(program_data);
if (is_success) {
std::string program_name = program_data.program_name();
}
{
'program_name': 'ProgramScripts/',
'program_state': 0,
'cmd_id': 0,
'sub_cmd_id': 0,
'running_hours': 0,
'running_mins': 0,
'running_secs': 0,
'program_alarm': '',
'program_annotation': ''
}
program_name: 현재 실행 중인 프로그램 파일의 이름program_state: 프로그램 실행 상태ProgramState:IDLE(0),RUNNING(1),PAUSING(2),STOPPING(3)
I/O 장치 관련 기능
I/O 장치 기능은 디지털 및 아날로그 I/O, 엔드 툴 I/O 및 센서와 같은 다양한 로봇 하드웨어 구성 요소와 상호 작용하는 데 사용됩니다.
| 메서드 | 설명 |
|---|---|
get_di(DigitalList &data) |
IO 보드 DI 데이터 확인 |
get_do(DigitalList &data) |
IO 보드 DO 데이터 확인 |
set_do(const DigitalList &data) |
IO 보드 DO 데이터 확인 |
get_ai(AnalogList &data) |
IO 보드 AI 데이터 확인 |
get_ao(AnalogList &data) |
IO 보드 AO 데이터 확인 |
set_ao(const AnalogList &data) |
IO 보드 AO 데이터 설정 |
get_endtool_di(EndtoolSignalList &data) |
엔드 툴 DI 데이터 확인 |
get_endtool_do(EndtoolSignalList &data) |
엔드 툴 DO 데이터 확인 |
set_endtool_do(const EndtoolSignalList &data) |
엔드 툴 DO 데이터 설정 |
get_endtool_ai(AnalogList &data) |
엔드 툴 AI 데이터 확인 |
get_endtool_ao(AnalogList &data) |
엔드 툴 AO 데이터 확인 |
set_endtool_ao(const AnalogList &data) |
엔드툴 AO 데이터 확인 (List) |
get_device_info(DeviceInfo &data) |
장치 정보 확인 |
get_ft_sensor_data(FTSensorData &data) |
엔드 툴 F/T 센서 데이터 확인 |
get_gripper_data(GripperData& gripper_data) |
그리퍼 상태 및 위치 가져오기 |
set_gripper_command(GripperCommand& gripper_command) |
그리퍼 구동 프로파일 전송 |
set_endtool_rs485_rx(EndtoolRS485Rx& request) |
엔드툴 RS485 RX 버퍼 워드 쓰기 |
get_endtool_rs485_rx(EndtoolRS485Rx& rx_data) |
엔드툴 RS485 RX 버퍼 읽기 |
get_endtool_rs485_tx(EndtoolRS485Tx& tx_data) |
엔드툴 RS485 TX 버퍼 읽기 |
set_sander_command(SanderType& sander_type, string& ip, const float speed, const bool state) |
샌더 설정/시작/정지 |
get_sander_command(SanderCommand& sander_command) |
마지막 샌더 명령 상태 확인 |
add_photoneo_calib_point(string& vision_name, double px, double py, double pz) |
Photoneo 비전 calibration point 등록 |
get_photoneo_detection(VisionServer& vision_server, string& object, VisionFrameType frame_type, VisionResult& result) |
Photoneo 비전의 detection 위치 획득 |
get_photoneo_retrieval(VisionServer& vision_server, const string& object, VisionFrameType frame_type, VisionResult& result) |
Photoneo retrieval 위치 획득 |
get_di() 예제
Nrmk::IndyFramework::DigitalList di_data;
bool is_success = indy.get_di(di_data);
if (is_success) {
for (int i = 0; i < di_data.signals_size(); ++i) {
std::cout << "DI " << i << " 주소: " << di_data.signals(i).address()
<< ", 상태: " << di_data.signals(i).state() << std::endl;
}
}
get_do(), set_do() 예제
Nrmk::IndyFramework::DigitalList do_signal_list;
auto *do_signal = do_signal_list.add_signals();
do_signal->set_address(1);
do_signal->set_state(Nrmk::IndyFramework::DigitalState::ON_STATE);
bool is_success = indy.set_do(do_signal_list);
if (is_success) {
std::cout << "Set DO successfully." << std::endl;
} else {
std::cerr << "Failed to set DO." << std::endl;
}
Nrmk::IndyFramework::DigitalList do_data;
is_success = indy.get_do(do_data);
if (is_success) {
std::cout << "GetDO RPC succeeded." << std::endl;
for (int i = 0; i < do_data.signals_size(); i++) {
const auto& signal = do_data.signals(i);
std::cout << "Address: " << signal.address() << ", State: " << signal.state() << std::endl;
}
}
else {
std::cerr << "GetDO RPC failed." << std::endl;
}
get_ai() 예제
Nrmk::IndyFramework::AnalogList ai_data;
bool is_success = indy.get_ai(ai_data);
if (is_success) {
for (int i = 0; i < ai_data.signals_size(); ++i) {
std::cout << "AI " << i << " 주소: " << ai_data.signals(i).address()
<< ", 전압: " << ai_data.signals(i).voltage() << std::endl;
}
}
get_ao(), set_ao() 예제
Nrmk::IndyFramework::AnalogList ao_signal_list;
auto* ao_signal1 = ao_signal_list.add_signals();
ao_signal1->set_address(1);
ao_signal1->set_voltage(1000); //mV
auto* ao_signal2 = ao_signal_list.add_signals();
ao_signal2->set_address(2);
ao_signal2->set_voltage(2000); //mV
is_success = indy.set_ao(ao_signal_list);
if (is_success) {
std::cout << "SetAO RPC succeeded." << std::endl;
} else {
std::cerr << "SetAO RPC failed." << std::endl;
}
Nrmk::IndyFramework::AnalogList ao_data;
is_success = indy.get_ao(ao_data);
if (is_success) {
std::cout << "GetAO RPC succeeded." << std::endl;
for (int i = 0; i < ao_data.signals_size(); ++i) {
const auto &signal = ao_data.signals(i);
std::cout << "Address: " << signal.address() << ", Voltage: " << signal.voltage() << std::endl;
}
} else {
std::cerr << "GetAO RPC failed." << std::endl;
}
get_endtool_di() 예제
Nrmk::IndyFramework::EndtoolSignalList endtool_di_data;
is_success = indy.get_endtool_di(endtool_di_data);
if (is_success) {
std::cout << "GetEndDI RPC succeeded." << std::endl;
for (int i = 0; i < endtool_di_data.signals_size(); i++) {
const auto& signal = endtool_di_data.signals(i);
std::cout << "Port: " << signal.port() << std::endl;
for (const auto& state : signal.states()) {
std::cout << "State: " << state << std::endl;
}
}
} else {
std::cerr << "GetEndDI RPC failed." << std::endl;
}
get_endtool_do(), set_endtool_do() 예제
Nrmk::IndyFramework::EndtoolSignalList end_do_signal_list;
auto* end_signal1 = end_do_signal_list.add_signals();
end_signal1->set_port("C");
end_signal1->add_states(EndtoolState::UNUSED);
is_success = indy.set_endtool_do(end_do_signal_list);
if (is_success) {
std::cout << "SetEndDO RPC succeeded." << std::endl;
} else {
std::cerr << "SetEndDO RPC failed." << std::endl;
}
Nrmk::IndyFramework::EndtoolSignalList endtool_do_data;
is_success = indy.get_endtool_do(endtool_do_data);
if (is_success) {
std::cout << "GetEndDO RPC succeeded." << std::endl;
for (int i = 0; i < endtool_do_data.signals_size(); i++) {
const auto& signal = endtool_do_data.signals(i);
std::cout << "Port: " << signal.port() << std::endl;
for (const auto& state : signal.states()) {
std::cout << "State: " << state << std::endl;
}
}
} else {
std::cerr << "GetEndDO RPC failed." << std::endl;
}
get_endtool_ai() 예제
아날로그 입출력 기능은 RevE 엔드툴에서 사용이 가능하며, 엔드툴 AO 주소는 0과 1 두 가지 채널을 사용할 수 있습니다.
Nrmk::IndyFramework::AnalogList endtool_ai_data;
is_success = indy.get_endtool_ai(endtool_ai_data);
if (is_success) {
std::cout << "GetEndAI RPC succeeded." << std::endl;
for (int i = 0; i < endtool_ai_data.signals_size(); i++) {
const auto& signal = endtool_ai_data.signals(i);
std::cout << "Address: " << signal.address() << ", Voltage: " << signal.voltage() << std::endl; //mV
}
} else {
std::cerr << "GetEndAI RPC failed." << std::endl;
}
get_endtool_ao(), set_endtool_ao() 예제
아날로그 입출력 기능은 RevE 엔드툴에서 사용이 가능하며, 엔드툴 AO 주소는 0과 1 두 가지 채널을 사용할 수 있습니다.
Nrmk::IndyFramework::AnalogList end_ao_signal_list;
auto* end_ao_signal1 = end_ao_signal_list.add_signals();
end_ao_signal1->set_address(1);
end_ao_signal1->set_voltage(1000); //mV
is_success = indy.set_endtool_ao(end_ao_signal_list);
if (is_success) {
std::cout << "SetEndAO RPC succeeded." << std::endl;
} else {
std::cerr << "SetEndAO RPC failed." << std::endl;
}
Nrmk::IndyFramework::AnalogList endtool_ao_data;
is_success = indy.get_endtool_ao(endtool_ao_data);
if (is_success) {
std::cout << "GetEndAO RPC succeeded." << std::endl;
for (int i = 0; i < endtool_ao_data.signals_size(); i++) {
const auto& signal = endtool_ao_data.signals(i);
std::cout << "Address: " << signal.address() << ", Voltage: " << signal.voltage() << std::endl; //mV
}
} else {
std::cerr << "GetEndAO RPC failed." << std::endl;
}
get_device_info() 예제
Nrmk::IndyFramework::DeviceInfo dinfo;
if (indy.get_device_info(dinfo)) {
std::cout << "Joints: " << dinfo.num_joints()
<< " Serial: " << dinfo.robot_serial()
<< " Payload: " << dinfo.payload() << std::endl;
}
get_ft_sensor_data()
Nrmk::IndyFramework::FTSensorData ft;
if (indy.get_ft_sensor_data(ft)) {
std::cout << "Fx=" << ft.ft_fx() << " Fy=" << ft.ft_fy() << " Fz=" << ft.ft_fz()
<< " Tx=" << ft.ft_tx() << " Ty=" << ft.ft_ty() << " Tz=" << ft.ft_tz() << std::endl;
}
Hardware I/O Examples
Gripper
Nrmk::IndyFramework::GripperData gdata;
if (indy.get_gripper_data(gdata)) {
std::cout << "[GripperData] type=" << gdata.gripper_type()
<< " pos=" << gdata.gripper_position()
<< " state=" << gdata.gripper_state() << "\n";
} else {
std::cerr << "get_gripper_data failed\n";
}
Nrmk::IndyFramework::GripperCommand gcmd;
gcmd.set_type(Nrmk::IndyFramework::GripperCommand::GRIPPER_ROBOTIQ); // example
gcmd.set_position(50);
gcmd.set_speed(100);
gcmd.set_force(40);
if (indy.set_gripper_command(gcmd)) {
std::cout << "set_gripper_command sent (position=50,speed=100,force=40)\n";
} else {
std::cerr << "set_gripper_command failed\n";
}
RS485 Endtool
Nrmk::IndyFramework::EndtoolRS485Rx write_rx;
write_rx.set_word1(0x1234);
write_rx.set_word2(0xABCD);
if (indy.set_endtool_rs485_rx(write_rx)) {
std::cout << "set_endtool_rs485_rx (word1=0x1234 word2=0xABCD)\n";
} else {
std::cerr << "set_endtool_rs485_rx failed\n";
}
Nrmk::IndyFramework::EndtoolRS485Rx read_rx;
if (indy.get_endtool_rs485_rx(read_rx)) {
std::cout << "[RS485 RX] word1=0x" << std::hex << read_rx.word1()
<< " word2=0x" << read_rx.word2() << std::dec << "\n";
} else {
std::cerr << "get_endtool_rs485_rx failed\n";
}
Nrmk::IndyFramework::EndtoolRS485Tx read_tx;
if (indy.get_endtool_rs485_tx(read_tx)) {
std::cout << "[RS485 TX] word1=0x" << std::hex << read_tx.word1()
<< " word2=0x" << read_tx.word2() << std::dec << "\n";
} else {
std::cerr << "get_endtool_rs485_tx failed\n";
}
모션 명령 함수
모션 명령 함수를 사용하면 로봇의 움직임을 제어할 수 있으며, 특정 위치로 이동하거나 복잡한 모션 경로를 실행할 수 있습니다.
| 메서드 | 설명 |
|---|---|
stop_motion(StopCategory stop_category) |
지정된 정지 범주에 따라 모션 정지 |
move_home() |
로봇을 홈 위치로 이동 |
movej(const std::vector<float> jtarget, const int base_type, const int blending_type, const float blending_radius, const float vel_ratio, const float acc_ratio, const bool const_cond, const int cond_type, const int react_type, DCPDICond di_condition, DCPVarCond var_condition, const bool teaching_mode) |
로봇을 지정된 관절 대상 위치로 이동 |
movej_time(const std::vector<float> jtarget, const int base_type, const int blending_type, const float blending_radius, const float move_time, const bool const_cond, const int cond_type, const int react_type, DCPDICond di_condition, DCPVarCond var_condition, const bool teaching_mode) |
지정된 시간 동안 로봇을 지정된 관절 대상 위치로 이동 |
movel(const std::array<float, 6> ttarget, const int base_type, const int blending_type, const float blending_radius, const float vel_ratio, const float acc_ratio, const bool const_cond, const int cond_type, const int react_type, DCPDICond di_condition, DCPVarCond var_condition, const bool teaching_mode) |
로봇을 지정된 작업공간 위치로 선형 이동 |
movel_time(const std::array<float, 6> ttarget, const int base_type, const int blending_type, const float blending_radius, const float move_time, const bool const_cond, const int cond_type, const int react_type, DCPDICond di_condition, DCPVarCond var_condition, const bool teaching_mode) |
지정된 시간 동안 로봇을 지정된 작업공간 위치로 선형 이동 |
movec(const std::array<float, 6> tpos1, const std::array<float, 6> tpos2, const float angle, const int setting_type, const int move_type, const int base_type, const int blending_type, const float blending_radius, const float vel_ratio, const float acc_ratio, const bool const_cond, const int cond_type, const int react_type, DCPDICond di_condition, DCPVarCond var_condition, const bool teaching_mode) |
로봇을 원형 경로를 따라 이동 |
movec_time(const std::array<float, 6>& tpos1, const std::array<float, 6>& tpos2, float angle, int setting_type, int move_type, int base_type, int blending_type, float blending_radius, float move_time, bool const_cond, int cond_type, int react_type, DCPDICond di_condition, DCPVarCond var_condition) |
지정된 시간 동안 로봇을 원형 경로를 따라 이동 |
movelf(const std::array<float, 6> ttarget, int base_type, int blending_type, float blending_radius, float vel_ratio, float acc_ratio, bool const_cond, int cond_type, int react_type, DCPDICond di_condition, DCPVarCond var_condition, bool teaching_mode) |
힘 유도 작업공간 위치로 선형 이동 (특이점 회피 적용 가능) |
move_conveyor(float object_length, float approach_dist, float retract_dist, float vel_ratio, float acc_ratio) |
컨베이어 진행 방향에 동기화된 Pick/Place 모션 실행 (컨베이어 트래킹) |
move_axis(const std::vector<float> atarget, int base_type, int blending_type, float blending_radius, float vel_ratio, float acc_ratio, bool const_cond, int cond_type, int react_type, DCPDICond di_condition, DCPVarCond var_condition, bool teaching_mode) |
부가축 관절을 대상 위치로 이동 |
move_gcode(const std::string& gcode_file, bool is_smooth_mode, float smooth_radius, float vel_ratio, float acc_ratio) |
입력된 gcode 파일을 따라 로봇을 이동 |
add_joint_waypoint(const std::vector<float>& waypoint) get_joint_waypoint(std::vector<std::vector<float>>& waypoints) clear_joint_waypoint() move_joint_waypoint(float move_time) |
joint waypoints의 집합을 따라 로봇을 이동 |
add_task_waypoint(const std::array<float, 6>& waypoint) get_task_waypoint(std::vector<std::array<float, 6>>& waypoints) clear_task_waypoint() move_task_waypoint(float move_time) |
task waypoints의 집합을 따라 로봇을 이동 |
add_joint_waypoint(const std::vector<float>& waypoint) get_joint_waypoint(std::vector<std::vector<float>>& waypoints) clear_joint_waypoint() move_joint_waypoint(float move_time) |
로봇을 일련의 조인트 웨이포인트로 이동 |
add_task_waypoint(const std::array<float, 6>& waypoint) get_task_waypoint(std::vector<std::array<float, 6>>& waypoints) clear_task_waypoint() move_task_waypoint(float move_time) |
로봇을 일련의 작업 경로점으로 이동 |
move_joint_traj(const std::vector<std::vector<float>>& q_list, const std::vector<std::vector<float>>& qdot_list, const std::vector<std::vector<float>>& qddot_list) |
로봇의 제어 주기에 대한 관절공간의 위치-속도-가속도를 한번에 입력받고 입력된 궤적을 따라 로봇을 이동 |
move_task_traj(const std::vector<std::vector<float>>& p_list, const std::vector<std::vector<float>>& pdot_list, const std::vector<std::vector<float>>& pddot_list) |
로봇의 제어 주기에 대한 작업공간의 위치-속도-가속도를 한번에 입력받고 입력된 궤적을 따라 로봇을 이동 |
주의
모션 명령을 사용할 때는 주의해야 합니다. 명령이 성공적으로 적용되면 로봇이 즉시 움직이기 때문입니다. 펜던트를 통해 로봇을 사용할 때는 사용자가 터치 버튼을 누르고 있는 동안에만 움직일 수 있지만, API를 사용할 때는 프로그램 명령을 통해 움직일 수 있으므로 항상 충돌을 일으킬 수 있는 물체가 없는지 확인하십시오. 특히, 높은 속도 또는 가속도를 설정할 때는 로봇이 예상보다 빠르게 움직일 수 있으므로 안전에 유의해야 합니다.
stop_motion() 예제
지정된 정지 범주에 따라 로봇의 모션을 정지시킵니다.
StopCategory stop_category = StopCategory::SMOOTH_BRAKE;
bool is_success = indy.stop_motion(stop_category);
if (is_success) {
std::cout << "모션이 성공적으로 정지되었습니다." << std::endl;
} else {
std::cerr << "모션 정지 실패." << std::endl;
}
move_home() 예제
로봇을 사전 정의된 홈 위치로 이동시킵니다.
bool is_success = indy.move_home();
if (is_success) {
std::cout << "로봇이 홈 위치로 성공적으로 이동되었습니다." << std::endl;
} else {
std::cerr << "로봇을 홈 위치로 이동 실패." << std::endl;
}
movej() 예제
로봇을 지정된 관절 대상 위치로 이동시킵니다.
std::vector<float> target_joints = {0.0, 0.0, -90.0, 0.0, -90.0, 0.0};
bool is_success = indy.movej(target_joints);
if (is_success) {
std::cout << "MoveJ 명령이 성공적으로 실행되었습니다." << std::endl;
} else {
std::cerr << "MoveJ 명령 실패." << std::endl;
}
movel() 예제
작업 공간의 지정된 선형 대상 위치로 로봇을 이동시킵니다.
std::array<float, 6> target_pose = {350.0, -186.5, 522.0, -180.0, 0.0, 180.0};
bool is_success = indy.movel(target_pose);
if (is_success) {
std::cout << "MoveL 명령이 성공적으로 실행되었습니다." << std::endl;
} else {
std::cerr << "MoveL 명령 실패." << std::endl;
}
movec() 예제
두 개의 지정된 작업 공간 위치를 통과하는 원형 경로를 따라 로봇을 이동시킵니다.
std::array<float, 6> t_pos1 = {241.66, -51.11, 644.20, 0.0, 180.0, 23.3};
std::array<float, 6> t_pos2 = {401.53, -47.74, 647.50, 0.0, 180.0, 23.3};
float angle = 720.0;
bool is_success = indy.movec(tpos1, tpos2, angle);
if (is_success) {
std::cout << "원형 이동이 성공적으로 실행되었습니다." << std::endl;
} else {
std::cerr << "원형 이동 실패." << std::endl;
}
move_axis(...) 예제
로봇 베이스에 결합된 부가측 관절을 제어합니다.
std::array<float,3> start_mm {0.f, 0.f, 0.f};
std::array<float,3> target_mm {200.f, 0.f, 0.f};
bool is_success = indy.move_axis(start_mm, target_mm, false, 50.f, 100.f);
if (is_success) {
std::cout << "move_axis sent (start=[0,0,0]mm target=[200,0,0]mm is_absolute=false vel_ratio=50 acc_ratio=100)\n";
} else {
std::cerr << "move_axis failed (check robot state / servo on / mode)\n";
}
move_gcode() 예제
G-code 파일을 기반으로 모션을 읽고 실행합니다.
std::string gcode_path = "/path/to/gcode/<gcode file>";
bool is_smooth = false;
float smooth_radius = 0.0f;
float velocity_ratio = 15.0f;
float acceleration_ratio = 100.0f;
bool is_success = indy.move_gcode(
gcode_path,
is_smooth,
smooth_radius,
velocity_ratio,
acceleration_ratio
);
if (is_success) {
std::cout << "G-code motion executed successfully." << std::endl;
} else {
std::cerr << "Failed to execute G-code motion." << std::endl;
}
관절 경유점, 작업 경유점을 이용한 Move
Joint Waypoints
관절 경유점은 로봇의 각 관절 각도를 나타내며 여러 관절 경유점을 순차적으로 이동하도록 모션을 만들 수 있게 합니다.
add_joint_waypoint(const std::vector<float>& waypoint) 는 관절 경유점을 경유점 리스트에 추가합니다. 경유점은 타겟 관절 위치를 벡터로 표현합니다.
waypoint: float으로 표현된 벡터이며 1번부터 6번 까지의 관절 각도를 deg 단위로 나타냅니다.
indy.add_joint_waypoint({0, 0, 0, 0, 0, 0});
indy.add_joint_waypoint({-44, 25, -63, 48, -7, -105});
indy.add_joint_waypoint({0, 0, 90, 0, 90, 0});
indy.add_joint_waypoint({-145, 31, -33, 117, -7, -133});
indy.add_joint_waypoint({-90, -15, -90, 0, -75, 0});
get_joint_waypoint() 현재 경유점 리스트에 저장된 관절 경유점 값을 반환 받을 수 있습니다.
std::vector<std::vector<float>> waypoints;
if (indy.get_joint_waypoint(waypoints)) {
std::cout << "Successfully retrieved joint waypoints:" << std::endl;
for (const auto& wp : waypoints) {
for (float joint : wp) {
std::cout << joint << " ";
}
std::cout << std::endl;
}
} else {
std::cerr << "No joint waypoints available." << std::endl;
}
clear_joint_waypoint() 저장된 경유점 리스트를 리셋합니다.
move_joint_waypoint(float move_time) 경유점 리스트에 저장된 관절 경유점을 따라 순차적으로 로봇이 이동합니다.
move_time: (옵션) 각 경유점 간의 이동시간을 설정할 수 있습니다.
Task Waypoints
작업 경유점은 로봇의 작업공간 상의 위치와 자세를 나타내며 여러 작업 경유점을 순차적으로 이동하도록 모션을 만들 수 있게 합니다.
add_task_waypoint(const std::array<float, 6>& waypoint) 는 작업 경유점을 경유점 리스트에 추가합니다. 경유점은 타겟 작업 위치를 벡터로 표현합니다.
waypoint: float으로 표현된 벡터이며 x, y, z 위치와 말단의 u, v, w 방향 각도를 나타냅니다.
indy.add_task_waypoint({-186.54f, -454.45f, 415.61f, 179.99f, -0.06f, 89.98f});
indy.add_task_waypoint({-334.67f, -493.07f, 259.00f, 179.96f, -0.12f, 89.97f});
indy.add_task_waypoint({224.79f, -490.20f, 508.08f, 179.96f, -0.14f, 89.97f});
indy.add_task_waypoint({-129.84f, -416.84f, 507.38f, 179.95f, -0.16f, 89.96f});
indy.add_task_waypoint({-186.54f, -454.45f, 415.61f, 179.99f, -0.06f, 89.98f});
get_task_waypoint(std::vector<std::array<float, 6>>& waypoints) 현재 경유점 리스트에 저장된 작업 경유점 값을 반환 받을 수 있습니다.
std::vector<std::array<float, 6>> t_waypoints;
if (indy.get_task_waypoint(t_waypoints)) {
std::cout << "Successfully retrieved task waypoints:" << std::endl;
for (const auto& wp : t_waypoints) {
for (float task : wp) {
std::cout << task << " ";
}
std::cout << std::endl;
}
} else {
std::cerr << "No task waypoints available." << std::endl;
}
clear_task_waypoint() 저장된 작업 경유점 리스트를 리셋합니다.
move_task_waypoint(float move_time) 경유점 리스트에 저장된 경유점을 따라 순차적으로 로봇이 이동합니다.
move_time: (옵션) 각 경유점 간의 이동시간을 설정할 수 있습니다.
Trajectory Motion
move_joint_traj는 관절 공간 궤적 이동 명령입니다.
아래에서 q_list, qdot_list, qddot_list는 라디안 단위의 관절 위치, 속도 및 가속도의 list 값입니다.
궤적 사이의 시간 간격은 제어 주기이며 기본적으로 250us입니다.
std::vector<std::vector<float>> q_list = {{...}, {...}, ...};
std::vector<std::vector<float>> qdot_list = {{...}, {...}, ...};
std::vector<std::vector<float>> qddot_list = {{...}, {...}, ...};
indy.move_joint_traj(q_list, qdot_list, qddot_list)
move_task_traj는 작업 공간 궤적 이동 명령입니다.
아래에서 p_list, pdot_list, pddot_list는 엔드툴 위치, 속도 및 가속도의 미터 및 라디안 단위의 list 값입니다.
궤적 사이의 시간 단계는 제어 기간이며 기본적으로 250us입니다.
std::vector<std::vector<float>> p_list = {{...}, {...}, ...};
std::vector<std::vector<float>> pdot_list = {{...}, {...}, ...};
std::vector<std::vector<float>> pddot_list = {{...}, {...}, ...};
indy.move_task_traj(p_list, pdot_list, pddot_list)
Waiting Functions
Wait IO: 특정 디지털 또는 아날로그 I/O 신호가 주어진 조건과 일치할 때까지 대기합니다.
Wait Time: 첫 모션 명령이 입력된 후 특정 시간 동안 대기합니다.
Wait Progress: 특정 진행 상태에 도달할 때까지 대기합니다.
Wait Radius: 지정된 반경 내에서 움직임이 완료될 때까지 대기합니다.
Wait Traj: 경로 이동이 완료될 때까지 대기합니다.
- Wait Traj 조건
- TRAJ_STARTED(0): 경로 이동이 막 시작되었음
- TRAJ_ACC_DONE(1): 경로의 가속 구간이 완료되었음
- TRAJ_CRZ_DONE(2): 경로의 순항 구간(일정 속도 구간)이 완료되었음
- TRAJ_DEC_DONE(3): 경로의 감속 구간이 완료되었음
std::vector<float> j_pos_1 = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
indy.movej(j_pos_1, JointBaseType::ABSOLUTE_JOINT, BlendingType_Type::BlendingType_Type_OVERRIDE);
// indy.wait_time(0.1f);
// indy.wait_radius(10);
// indy.wait_traj(TrajCondition::TRAJ_ACC_DONE);
indy.wait_progress(15);
std::vector<float> j_pos_2 = {0.0, 0.0, -90.0, 0.0, -90.0, 0.0};
indy.movej(j_pos_2, JointBaseType::ABSOLUTE_JOINT, BlendingType_Type::BlendingType_Type_OVERRIDE);
wait_io() 사용 예제
특정 디지털 또는 아날로그 I/O 신호가 주어진 조건과 일치할 때까지 대기합니다.
std::vector<Nrmk::IndyFramework::DigitalSignal> di_signals = {
Nrmk::IndyFramework::DigitalSignal(1, Nrmk::IndyFramework::DigitalState::ON),
Nrmk::IndyFramework::DigitalSignal(2, Nrmk::IndyFramework::DigitalState::OFF)
};
std::vector<Nrmk::IndyFramework::DigitalSignal> end_di_signals = {
Nrmk::IndyFramework::DigitalSignal(3, Nrmk::IndyFramework::DigitalState::ON)
};
bool is_success = indy.wait_io(
di_signals, // Digital input signals to wait for
{}, // Digital output signals to wait for
end_di_signals, // Digital input signals to end waiting
{}, // Digital output signals to end waiting
1
);
if (is_success) {
std::cout << "WaitIO condition met successfully." << std::endl;
} else {
std::cerr << "WaitIO condition failed." << std::endl;
}
텔레오퍼레이션 관련 함수
텔레오퍼레이션 관련 함수는 사용자가 로봇을 원격 제어할 수 있도록 하는 기능을 제공합니다. 이 함수들을 통해 로봇의 모션을 실시간으로 조정하고, 다양한 조작 모드에서 로봇을 제어할 수 있습니다. start_teleop 함수를 사용하여 텔레오퍼레이션 모드를 시작하고, stop_teleop 함수로 모드를 종료할 수 있습니다. 또한, movetelej_abs/movetelej_rel와 movetelel_abs/movetelel_rel 함수를 사용하여 각각 관절 공간과 작업 공간에서의 로봇 움직임을 업데이트할 수 있습니다.
Note
텔레오퍼레이션 모션 이용 시 IndyDCP3를 통해 실시간으로 지속적 목표 위치를 업데이트하게 되면 로봇은 이를 스트리밍하여 즉각적이면서 스무스한 모션을 생성합니다. 기존 Motion 명령들 (movej, movel)은 목표 위치로의 경로 생성을 부드럽게 수행하지만 원격제어와 같은 즉각적인 반응을 할 수는 없습니다. 이 점이 텔레오퍼레이션 모션의 특징입니다.
| Function | Description |
|---|---|
start_teleop(TeleMethod method) |
텔레오퍼레이션 모드 시작 |
stop_teleop() |
현재 실행 중인 텔레오퍼레이션 모드 종료 |
get_teleop_device(Nrmk::IndyFramework::TeleOpDevice& device) |
현재 연결된 텔레오퍼레이션 장치에 대한 정보를 가져옵니다. |
get_teleop_state(Nrmk::IndyFramework::TeleOpState& state) |
현재 텔레오퍼레이션 상태를 가져옵니다. |
connect_teleop_device(const std::string& name, Nrmk::IndyFramework::TeleOpDevice_TeleOpDeviceType type, const std::string& ip, uint32_t port) |
지정된 매개변수로 텔레오퍼레이션 장치에 연결합니다. |
disconnect_teleop_device() |
현재 연결된 텔레오퍼레이션 장치의 연결을 해제합니다. |
read_teleop_input(Nrmk::IndyFramework::TeleP& teleop_input) |
텔레오퍼레이션 장치에서 현재 입력 값을 읽어옵니다. |
get_tele_file_list(std::vector<std::string>& files) |
저장된 텔레오퍼레이션 모션 파일 목록을 가져옵니다. |
save_tele_motion(const std::string& name) |
현재 텔레오퍼레이션 모션을 지정된 이름으로 저장합니다. |
load_tele_motion(const std::string& name) |
저장된 텔레오퍼레이션 모션을 이름으로 불러옵니다. |
delete_tele_motion(const std::string& name) |
저장된 텔레오퍼레이션 모션을 이름으로 삭제합니다. |
enable_tele_key(const bool enable) |
텔레오퍼레이션 키 입력을 활성화하거나 비활성화합니다. |
set_play_rate(const float rate) |
텔레오퍼레이션 모션 재생 속도를 설정합니다. |
get_play_rate(float& rate) |
텔레오퍼레이션 모션 재생의 현재 재생 속도를 가져옵니다. |
start_teleop() 예제
지정된 방법으로 원격 제어 모드를 시작합니다.
TeleMethod method = TeleMethod::TELE_JOINT_RELATIVE;
bool is_success = indy.start_teleop(method);
if (is_success) {
std::cout << "원격 제어 모드가 성공적으로 시작되었습니다." << std::endl;
} else {
std::cerr << "원격 제어 모드 시작 실패." << std::endl;
}
stop_teleop() 예제
원격 제어 모드를 종료합니다.
bool is_success = indy.stop_teleop();
if (is_success) {
std::cout << "원격 제어 모드가 성공적으로 종료되었습니다." << std::endl;
} else {
std::cerr << "원격 제어 모드 종료 실패." << std::endl;
}
get_teleop_device() 예제
현재 연결된 텔레오퍼레이션 장치에 대한 정보를 가져옵니다.
Nrmk::IndyFramework::TeleOpDevice device;
bool is_success = indy.get_teleop_device(device);
if (is_success) {
std::cout << "Teleoperation device name: " << device.name() << std::endl;
std::cout << "Device IP: " << device.ip() << std::endl;
} else {
std::cerr << "Failed to retrieve teleoperation device information." << std::endl;
}
get_teleop_state() 예제
현재 텔레오퍼레이션 상태를 가져옵니다.
Nrmk::IndyFramework::TeleOpState state;
bool is_success = indy.get_teleop_state(state);
if (is_success) {
std::cout << "Teleoperation state: " << state.state() << std::endl;
} else {
std::cerr << "Failed to retrieve teleoperation state." << std::endl;
}
connect_teleop_device() 예제
지정된 매개변수로 텔레오퍼레이션 장치에 연결합니다.
std::string device_name = "TeleOpDevice1";
Nrmk::IndyFramework::TeleOpDevice_TeleOpDeviceType type = Nrmk::IndyFramework::TeleOpDevice_TeleOpDeviceType::TeleOpDeviceType_JOYSTICK;
std::string ip = "192.168.0.2";
uint32_t port = 5555;
bool is_success = indy.connect_teleop_device(device_name, type, ip, port);
if (is_success) {
std::cout << "Teleoperation device connected successfully." << std::endl;
} else {
std::cerr << "Failed to connect to teleoperation device." << std::endl;
}
disconnect_teleop_device() 예제
현재 연결된 텔레오퍼레이션 장치의 연결을 해제합니다.
bool is_success = indy.disconnect_teleop_device();
if (is_success) {
std::cout << "Teleoperation device disconnected successfully." << std::endl;
} else {
std::cerr << "Failed to disconnect teleoperation device." << std::endl;
}
read_teleop_input() 예제
텔레오퍼레이션 장치에서 현재 입력 값을 읽어옵니다.
Nrmk::IndyFramework::TeleP teleop_input;
bool is_success = indy.read_teleop_input(teleop_input);
if (is_success) {
std::cout << "Teleoperation input read successfully." << std::endl;
// Process teleop_input as needed
} else {
std::cerr << "Failed to read teleoperation input." << std::endl;
}
set_play_rate() 예제
텔레오퍼레이션 모션 재생 속도를 설정합니다.
float playback_rate = 1.2;
bool is_success = indy.set_play_rate(playback_rate);
if (is_success) {
std::cout << "Playback rate set successfully to " << playback_rate << std::endl;
} else {
std::cerr << "Failed to set playback rate." << std::endl;
}
get_play_rate() 예제
텔레오퍼레이션 모션 재생의 현재 재생 속도를 가져옵니다.
float playback_rate;
bool is_success = indy.get_play_rate(playback_rate);
if (is_success) {
std::cout << "Current playback rate: " << playback_rate << std::endl;
} else {
std::cerr << "Failed to retrieve playback rate." << std::endl;
}
get_tele_file_list() 예제
텔레오퍼레이션 모션 파일 목록을 가져옵니다.
std::vector<std::string> files;
bool is_success = indy.get_tele_file_list(files);
if (is_success) {
std::cout << "Retrieved teleoperation files:" << std::endl;
for (const auto& file : files) {
std::cout << " - " << file << std::endl;
}
} else {
std::cerr << "Failed to retrieve teleoperation file list." << std::endl;
}
save_tele_motion() 예제
텔레오퍼레이션 모션을 지정된 이름으로 저장합니다.
std::string motion_name = "MyTeleMotion";
bool is_success = indy.save_tele_motion(motion_name);
if (is_success) {
std::cout << "Teleoperation motion saved successfully as " << motion_name << std::endl;
} else {
std::cerr << "Failed to save teleoperation motion." << std::endl;
}
load_tele_motion() 예제
텔레오퍼레이션 모션을 이름으로 불러옵니다.
std::string motion_name = "MyTeleMotion";
bool is_success = indy.load_tele_motion(motion_name);
if (is_success) {
std::cout << "Teleoperation motion " << motion_name << " loaded successfully." << std::endl;
} else {
std::cerr << "Failed to load teleoperation motion." << std::endl;
}
delete_tele_motion() 예제
텔레오퍼레이션 모션을 이름으로 삭제합니다.
std::string motion_name = "MyTeleMotion";
bool is_success = indy.delete_tele_motion(motion_name);
if (is_success) {
std::cout << "Teleoperation motion " << motion_name << " deleted successfully." << std::endl;
} else {
std::cerr << "Failed to delete teleoperation motion." << std::endl;
}
enable_tele_key() 예제
텔레오퍼레이션 키 입력을 활성화하거나 비활성화합니다.
bool enable_key = true;
bool is_success = indy.enable_tele_key(enable_key);
if (is_success) {
std::cout << "Teleoperation key input enabled." << std::endl;
} else {
std::cerr << "Failed to enable teleoperation key input." << std::endl;
}
변수 처리 함수
IndyDCP3 C++ API는 부울, 정수, 부동 소수점, 관절 위치(JPos) 및 작업 위치(TPos) 변수와 같은 다양한 유형의 변수를 처리하는 여러 함수를 제공합니다. 이러한 변수는 로봇과 외부 장치 간에 정보를 교환하는 데 사용할 수 있습니다.
| 메서드 | 설명 |
|---|---|
get_bool_variable(std::vector<BoolVariable> &variables) |
Bool 유형 변수를 검색합니다 |
get_int_variable(std::vector<IntVariable> &variables) |
정수형 변수를 검색합니다 |
get_float_variable(std::vector<FloatVariable> &variables) |
부동 소수점 변수를 검색합니다 |
get_jpos_variable(std::vector<JPosVariable> &variables) |
JPos 유형 변수를 검색합니다 |
get_tpos_variable(std::vector<TPosVariable> &variables) |
TPos 유형 변수를 검색합니다 |
set_bool_variable(const std::vector<BoolVariable> &variables) |
Bool 유형 변수를 설정합니다 |
set_int_variable(const std::vector<IntVariable> &variables) |
정수형 변수를 설정합니다 |
set_float_variable(const std::vector<FloatVariable> &variables) |
부동 소수점 변수를 설정합니다 |
set_jpos_variable(const std::vector<JPosVariable> &variables) |
JPos 유형 변수를 설정합니다 |
set_tpos_variable(const std::vector<TPosVariable> &variables) |
TPos 유형 변수를 설정합니다 |
set_plugin_bool_variable(const std::string& name, bool value) / get_plugin_bool_variable(const std::string& name, bool& value) |
Bool 타입 plugin 변수 설정/조회 |
set_plugin_int_variable(const std::string& name, int64_t value) / get_plugin_int_variable(const std::string& name, int64_t& value) |
Int 타입 plugin 변수 설정/조회 |
set_plugin_float_variable(const std::string& name, float value) / get_plugin_float_variable(const std::string& name, float& value) |
Float 타입 plugin 변수 설정/조회 |
set_plugin_jpos_variable(const std::string& name, const std::vector<float>& jpos) / get_plugin_jpos_variable(const std::string& name, std::vector<float>& jpos) |
JPos 타입 plugin 변수 설정/조회 |
set_plugin_tpos_variable(const std::string& name, const std::vector<float>& tpos) / get_plugin_tpos_variable(const std::string& name, std::vector<float>& tpos) |
TPos 타입 plugin 변수 설정/조회 |
get_bool_variable() 예제
로봇에서 Bool 유형 변수의 현재 값을 검색합니다.
std::vector<Nrmk::IndyFramework::BoolVariable> bool_vars;
bool is_success = indy.get_bool_variable(bool_vars);
if (is_success) {
std::cout << "부울 변수가 성공적으로 검색되었습니다." << std::endl;
for (const auto &var : bool_vars) {
std::cout << "주소: " << var.addr() << ", 값: " << var.value() << std::endl;
}
} else {
std::cerr << "부울 변수 검색 실패." << std::endl;
}
get_int_variable() 예제
로봇에서 정수형 변수의 현재 값을 검색합니다.
std::vector<Nrmk::IndyFramework::IntVariable> int_vars;
bool is_success = indy.get_int_variable(int_vars);
if (is_success) {
std::cout << "정수형 변수가 성공적으로 검색되었습니다." << std::endl;
for (const auto &var : int_vars) {
std::cout << "주소: " << var.addr() << ", 값: " << var.value() << std::endl;
}
} else {
std::cerr << "정수형 변수 검색 실패." << std::endl;
}
get_float_variable() 예제
로봇에서 부동 소수점 변수의 현재 값을 검색합니다.
std::vector<Nrmk::IndyFramework::FloatVariable> float_vars;
bool is_success = indy.get_float_variable(float_vars);
if (is_success) {
std::cout << "부동 소수점 변수가 성공적으로 검색되었습니다." << std::endl;
for (const auto &var : float_vars) {
std::cout << "주소: " << var.addr() << ", 값: " << var.value() << std::endl;
}
} else {
std::cerr << "부동 소수점 변수 검색 실패." << std::endl;
}
get_jpos_variable() 예제
로봇에서 관절 위치(JPos) 유형 변수의 현재 값을 검색합니다.
std::vector<Nrmk::IndyFramework::JPosVariable> jpos_vars;
bool is_success = indy.get_jpos_variable(jpos_vars);
if (is_success) {
std::cout << "JPos 변수가 성공적으로 검색되었습니다." << std::endl;
for (const auto &var : jpos_vars) {
std::cout << "주소: " << var.addr() << ", JPos: ";
for (const auto &jpos : var.jpos()) {
std::cout << jpos << " ";
}
std::cout << std::endl;
}
} else {
std::cerr << "JPos 변수 검색 실패." << std::endl;
}
get_tpos_variable() 예제
로봇에서 작업 위치(TPos) 유형 변수의 현재 값을 검색합니다.
std::vector<Nrmk::IndyFramework::TPosVariable> tpos_vars;
bool is_success = indy.get_tpos_variable(tpos_vars);
if (is_success) {
std::cout << "TPos 변수가 성공적으로 검색되었습니다." << std::endl;
for (const auto &var : tpos_vars) {
std::cout << "주소: " << var.addr() << ", TPos: ";
for (const auto &tpos : var.tpos()) {
std::cout << tpos << " ";
}
std::cout << std::endl;
}
} else {
std::cerr << "TPos 변수 검색 실패." << std::endl;
}
set_bool_variable() 예제
로봇의 Bool 유형 변수를 설정합니다.
std::vector<Nrmk::IndyFramework::BoolVariable> bool_vars;
Nrmk::IndyFramework::BoolVariable var1;
var1.set_addr(1);
var1.set_value(true);
bool_vars.push_back(var1);
bool is_success = indy.set_bool_variable(bool_vars);
if (is_success) {
std::cout << "부울 변수가 성공적으로 설정되었습니다." << std::endl;
} else {
std::cerr << "부울 변수 설정 실패." << std::endl;
}
set_int_variable() 예제
로봇의 정수형 변수를 설정합니다.
std::vector<Nrmk::IndyFramework::IntVariable> int_vars;
Nrmk::IndyFramework::IntVariable var1;
var1.set_addr(2);
var1.set_value(42);
int_vars.push_back(var1);
bool is_success = indy.set_int_variable(int_vars);
if (is_success) {
std::cout << "정수형 변수가 성공적으로 설정되었습니다." << std::endl;
} else {
std::cerr << "정수형 변수 설정 실패." << std::endl;
}
set_float_variable() 예제
로봇의 부동 소수점 변수를 설정합니다.
std::vector<Nrmk::IndyFramework::FloatVariable> float_vars;
Nrmk::IndyFramework::FloatVariable var1;
var1.set_addr(3);
var1.set_value(3.14f);
float_vars.push_back(var1);
bool is_success = indy.set_float_variable(float_vars);
if (is_success) {
std::cout << "부동 소수점 변수가 성공적으로 설정되었습니다." << std::endl;
} else {
std::cerr << "부동 소수점 변수 설정 실패." << std::endl;
}
set_jpos_variable() 예제
로봇의 관절 위치(JPos) 유형 변수를 설정합니다.
std::vector<Nrmk::IndyFramework::JPosVariable> jpos_vars;
Nrmk::IndyFramework::JPosVariable var1;
var1.set_addr(1);
var1.add_jpos(0.0f);
var1.add_jpos(0.0f);
var1.add_jpos(-90.0f);
var1.add_jpos(0.0f);
var1.add_jpos(-90.0f);
var1.add_jpos(0.0f);
jpos_vars.push_back(var1);
bool is_success = indy.set_jpos_variable(jpos_vars);
if (is_success) {
std::cout << "JPos 변수가 성공적으로 설정되었습니다." << std::endl;
} else {
std::cerr << "JPos 변수 설정 실패." << std::endl;
}
set_tpos_variable() 예제
로봇의 툴 위치(TPos) 유형 변수를 설정합니다.
std::vector<Nrmk::IndyFramework::TPosVariable> tpos_vars;
Nrmk::IndyFramework::TPosVariable var1;
var1.set_addr(1);
var1.add_tpos(350.0f);
var1.add_tpos(-186.5f);
var1.add_tpos(522.0f);
var1.add_tpos(-180.0f);
var1.add_tpos(0.0f);
var1.add_tpos(180.0f);
tpos_vars.push_back(var1);
bool is_success = indy.set_tpos_variable(tpos_vars);
if (is_success) {
std::cout << "TPos 변수가 성공적으로 설정되었습니다." << std::endl;
} else {
std::cerr << "TPos 변수 설정 실패." << std::endl;
}
set_plugin_bool_variable(), get_plugin_bool_variable()
bool ok = indy.set_plugin_bool_variable("bool_1", true);
std::cout << "set_plugin_bool_variable(bool_1,true): " << (ok?"OK":"FAIL") << "\n";
bool bval=false;
ok = indy.get_plugin_bool_variable("bool_1", bval);
std::cout << "get_plugin_bool_variable(bool_1): " << (ok?"OK":"FAIL") << ", value=" << bval << "\n";
set_plugin_int_variable(), get_plugin_int_variable()
ok = indy.set_plugin_int_variable("int_1", 3);
std::cout << "set_plugin_int_variable(int_1,3): " << (ok?"OK":"FAIL") << "\n";
int64_t ival=0;
ok = indy.get_plugin_int_variable("int_1", ival);
std::cout << "get_plugin_int_variable(int_1): " << (ok?"OK":"FAIL") << ", value=" << ival << "\n";
set_plugin_float_variable(), get_plugin_float_variable()
ok = indy.set_plugin_float_variable("float_1", 0.8f);
std::cout << "set_plugin_float_variable(float_1,0.8): " << (ok?"OK":"FAIL") << "\n";
float fval=0.f;
ok = indy.get_plugin_float_variable("float_1", fval);
std::cout << "get_plugin_float_variable(float_1): " << (ok?"OK":"FAIL") << ", value=" << fval << "\n";
set_plugin_jpos_variable(), get_plugin_jpos_variable()
std::vector<float> jpos = {0.0f, 0.0f, -90.0f, 0.0f, -90.0f, 0.0f};
ok = indy.set_plugin_jpos_variable("ex_home_pose", jpos);
std::cout << "set_plugin_jpos_variable(ex_home_pose): " << (ok?"OK":"FAIL") << "\n";
std::vector<float> jpos_read;
ok = indy.get_plugin_jpos_variable("ex_home_pose", jpos_read);
std::cout << "get_plugin_jpos_variable(ex_home_pose): " << (ok?"OK":"FAIL") << ", size=" << jpos_read.size() << "\n";
set_plugin_tpos_variable(), get_plugin_tpos_variable()
std::vector<float> tpos = {100.f, 0.f, 300.f, 0.f, 90.f, 0.f};
ok = indy.set_plugin_tpos_variable("ex_t_pose", tpos);
std::cout << "set_plugin_tpos_variable(ex_t_pose): " << (ok?"OK":"FAIL") << "\n";
std::vector<float> tpos_read;
ok = indy.get_plugin_tpos_variable("ex_t_pose", tpos_read);
std::cout << "get_plugin_tpos_variable(ex_t_pose): " << (ok?"OK":"FAIL") << ", size=" << tpos_read.size() << "\n";
역기구학 및 시뮬레이션 모드 관련 기능
IndyDCP3 C++ API는 역기구학 수행
, 직접 가르치기 모드 활성화/비활성화, 시뮬레이션 모드 설정 및 로봇을 오류 상태에서 복구하는 기능을 제공합니다.
| 메서드 | 설명 |
|---|---|
inverse_kin(const std::array<float, 6> &tpos, const std::vector<float> &init_jpos, std::vector<float> &jpos) |
목표 작업 공간 위치에 도달하기 위한 관절 위치를 계산합니다 |
set_direct_teaching(bool enable) |
직접 가르치기 모드를 활성화 또는 비활성화합니다 |
set_simulation_mode(bool enable) |
시뮬레이션 모드를 활성화 또는 비활성화합니다 |
recover() |
오류 또는 충돌 상태에서 로봇을 복구합니다 |
inverse_kin() 예제
std::array<float, 6> target_pose = {350.0, -186.5, 522.0, -180.0, 0.0, 180.0};
std::vector<float> init_jpos = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
std::vector<float> calculated_jpos;
bool is_success = indy.inverse_kin(target_pose, init_jpos, calculated_jpos);
if (is_success) {
std::cout << "역기구학 성공. 관절 위치: ";
for (float jp : calculated_jpos) {
std::cout << jp << " ";
}
std::cout << std::endl;
} else {
std::cerr << "역기구학 실패." << std::endl;
}
set_direct_teaching() 예제
bool enable_direct_teaching = true;
bool is_success = indy.set_direct_teaching(enable_direct_teaching);
if (is_success) {
std::cout << "직접 가르치기 모드가 활성화되었습니다." << std::endl;
} else {
std::cerr << "직접 가르치기 모드 활성화 실패." << std::endl;
}
set_simulation_mode() 예제
bool enable_simulation = true;
bool is_success = indy.set_simulation_mode(enable_simulation);
if (is_success) {
std::cout << "시뮬레이션 모드가 활성화되었습니다." << std::endl;
} else {
std::cerr << "시뮬레이션 모드 활성화 실패." << std::endl;
}
recover() 예제
bool is_success = indy.recover();
if (is_success) {
std::cout << "복구 성공." << std::endl;
} else {
std::cerr << "복구 실패." << std::endl;
}
프로그램 제어 함수
프로그램 제어 기능을 사용하면 로봇 프로그램을 시작, 일시 중지, 재개 및 중지할 수 있습니다. 이러한 기능은 미리 작성된 프로그램의 실행 흐름을 관리하는 데 필수적입니다.
| 메서드 | 설명 |
|---|---|
play_program(const std::string &prog_name, int prog_idx) |
이름 또는 인덱스로 프로그램을 시작합니다 |
pause_program() |
현재 실행 중인 프로그램을 일시 중지합니다 |
resume_program() |
일시 중지된 프로그램을 다시 시작합니다 |
stop_program() |
현재 실행 중인 프로그램을 중지합니다 |
play_program() 예제
std::string program_name = "example_program.indy7v2.json";
int program_index = 1;
bool is_success = indy.play_program(program_name, program_index);
if (is_success) {
std::cout << "프로그램이 성공적으로 시작되었습니다." << std::endl;
} else {
std::cerr << "프로그램 시작 실패." << std::endl;
}
pause_program() 예제
bool is_success = indy.pause_program();
if (is_success) {
std::cout << "프로그램이 성공적으로 일시 중지되었습니다." << std::endl;
} else {
std::cerr << "프로그램 일시 중지 실패." << std::endl;
}
resume_program() 예제
bool is_success = indy.resume_program();
if (is_success) {
std::cout << "프로그램이 성공적으로 재개되었습니다." << std::endl;
} else {
std::cerr << "프로그램 재개 실패." << std::endl;
}
stop_program() 예제
bool is_success = indy.stop_program();
if (is_success) {
std::cout << "프로그램이 성공적으로 중지되었습니다." << std::endl;
} else {
std::cerr << "프로그램 중지 실패." << std::endl;
}
IndySDK 사용
IndyDCP3 C++ API는 IndySDK를 활성화하고, 사용자 정의 제어 모드를 설정하고, 제어 게인을 관리하는 기능을 제공합니다. 이러한 기능은 사용자 정의 컨트롤러를 개발하려는 고급 사용자에게 중요합니다.
| 메서드 | 설명 |
|---|---|
activate_sdk(const SDKLicenseInfo &request, SDKLicenseResp &response) |
IndySDK를 활성화합니다 |
set_custom_control_mode(bool mode) |
사용자 정의 제어 모드를 설정합니다 |
get_custom_control_mode(int &mode) |
현재 사용자 정의 제어 모드를 검색합니다 |
set_custom_control_gain(const CustomGainSet &gain_set) |
사용자 컨트롤러에 대한 사용자 정의 제어 게인을 설정합니다 |
get_custom_control_gain(CustomGainSet &gain_set) |
현재 사용자 정의 제어 게인 설정을 검색합니다 |
set_joint_control_gain(const std::vector<float>& kp, const std::vector<float>& kv, const std::vector<float>& kl2) |
Joint-Level 컨트롤러의 제어게인 설정 |
get_joint_control_gain(std::vector<float>& kp, std::vector<float>& kv, std::vector<float>& kl2) |
Joint-Level 컨트롤러의 제어게인 확인 |
set_task_control_gain(const std::vector<float>& kp, const std::vector<float>& kv, const std::vector<float>& kl2) |
Task-Level 컨트롤러의 제어게인 설정 |
get_task_control_gain(std::vector<float>& kp, std::vector<float>& kv, std::vector<float>& kl2) |
Task-Level 컨트롤러의 제어게인 확인 |
set_impedance_control_gain(const std::vector<float>& mass, const std::vector<float>& damping, const std::vector<float>& stiffness, const std::vector<float>& kl2) |
임피던스 제어게인 설정 |
get_impedance_control_gain(std::vector<float>& mass, std::vector<float>& damping, std::vector<float>& stiffness, std::vector<float>& kl2) |
현재 임피던스 제어게인 확인 |
set_force_control_gain(const std::vector<float>& kp, const std::vector<float>& kv, const std::vector<float>& kl2, const std::vector<float>& mass, const std::vector<float>& damping, const std::vector<float>& stiffness, const std::vector<float>& kpf, const std::vector<float>& kif) |
힘 제어게인 설정 |
get_force_control_gain(std::vector<float>& kp, std::vector<float>& kv, std::vector<float>& kl2, std::vector<float>& mass, std::vector<float>& damping, std::vector<float>& stiffness, std::vector<float>& kpf, std::vector<float>& kif) |
현재 힘 제어게인 확인 |
activate_sdk() 예제
Nrmk::IndyFramework::SDKLicenseInfo request;
request.set_license_key("YOUR_LICENSE_KEY");
request.set_expire_date("yyyy-mm-dd");
Nrmk::IndyFramework::SDKLicenseResp response;
bool is_success = indy.activate_sdk(request, response);
if (is_success) {
std::cout << "SDK 활성화됨: " << (response.activated() ? "예" : "아니오") << std::endl;
std::cout << "응답 코드: " << response.response().code() << ", 메시지: " << response.response().msg() << std::endl;
} else {
std::cerr << "SDK 활성화 실패." << std::endl;
}
set_custom_control_mode() 및 get_custom_control_mode() 예제
int mode = 0;
bool is_success = indy.set_custom_control_mode(mode);
if (is_success) {
std::cout << "사용자 정의 제어 모드가 성공적으로 설정되었습니다." << std::endl;
} else {
std::cerr << "사용자 정의 제어 모드 설정 실패." << std::endl;
}
int get_mode;
bool is_success = indy.get_custom_control_mode(get_mode);
if (is_success) {
std::cout << "사용자 정의 제어 모드: " << get_mode << std::endl;
} else {
std::cerr << "사용자 정의 제어 모드 검색 실패." << std::endl;
}
set_custom_control_gain() 예제
Nrmk::IndyFramework::CustomGainSet gain_set;
gain_set.add_gain0(0.0);
gain_set.add_gain0(0.0);
gain_set.add_gain0(0.0);
gain_set.add_gain0(0.0);
gain_set.add_gain0(0.0);
gain_set.add_gain0(0.0);
bool is_success = indy.set_custom_control_gain(gain_set);
if (is_success) {
std::cout << "사용자 정의 제어 게인이 성공적으로 설정되었습니다." << std::endl;
} else {
std::cerr << "사용자 정의 제어 게인 설정 실패." << std::endl;
}
get_custom_control_gain() 예제
Nrmk::IndyFramework::CustomGainSet gain_set;
bool is_success = indy.get_custom_control_gain(gain_set);
if (is_success) {
std::cout << "사용자 정의 제어 게인이 성공적으로 검색되었습니다." << std::endl;
for (int i = 0; i < gain_set.gain0_size(); ++i) {
std::cout << "Gain0: " << gain_set.gain0(i) << " ";
}
std::cout << std::endl;
} else {
std::cerr << "사용자 정의 제어 게인 검색 실패." << std::endl;
}
set_joint_control_gain() 예제
std::vector<float> kp = {...};
std::vector<float> kv = {...};
std::vector<float> kl2 = {...};
bool is_success = indy.set_joint_control_gain(kp, kv, kl2);
if (is_success) {
std::cout << "Joint control gains set successfully." << std::endl;
} else {
std::cerr << "Failed to set joint control gains." << std::endl;
}
get_joint_control_gain() 예제
std::vector<float> kp, kv, kl2;
bool is_success = indy.get_joint_control_gain(kp, kv, kl2);
if (is_success) {
std::cout << "Joint control gains retrieved successfully." << std::endl;
std::cout << "KP: ";
for (const auto& value : kp) std::cout << value << " ";
std::cout << "\nKV: ";
for (const auto& value : kv) std::cout << value << " ";
std::cout << "\nKL2: ";
for (const auto& value : kl2) std::cout << value << " ";
std::cout << std::endl;
} else {
std::cerr << "Failed to retrieve joint control gains." << std::endl;
}
set_task_control_gain() 예제
std::vector<float> kp = {...};
std::vector<float> kv = {...};
std::vector<float> kl2 = {...};
bool is_success = indy.set_task_control_gain(kp, kv, kl2);
if (is_success) {
std::cout << "Task control gains set successfully." << std::endl;
} else {
std::cerr << "Failed to set task control gains." << std::endl;
}
get_task_control_gain() 예제
std::vector<float> kp, kv, kl2;
bool is_success = indy.get_task_control_gain(kp, kv, kl2);
if (is_success) {
std::cout << "Task control gains retrieved successfully." << std::endl;
std::cout << "KP: ";
for (const auto& value : kp) std::cout << value << " ";
std::cout << "\nKV: ";
for (const auto& value : kv) std::cout << value << " ";
std::cout << "\nKL2: ";
for (const auto& value : kl2) std::cout << value << " ";
std::cout << std::endl;
} else {
std::cerr << "Failed to retrieve task control gains." << std::endl;
}
set_impedance_control_gain() 예제
std::vector<float> mass = {...};
std::vector<float> damping = {...};
std::vector<float> stiffness = {...};
std::vector<float> kl2 = {...};
bool is_success = indy.set_impedance_control_gain(mass, damping, stiffness, kl2);
if (is_success) {
std::cout << "Impedance control gains set successfully." << std::endl;
} else {
std::cerr << "Failed to set impedance control gains." << std::endl;
}
get_impedance_control_gain() 예제
std::vector<float> mass, damping, stiffness, kl2;
bool is_success = indy.get_impedance_control_gain(mass, damping, stiffness, kl2);
if (is_success) {
std::cout << "Impedance control gains retrieved successfully." << std::endl;
std::cout << "Mass: ";
for (const auto& value : mass) std::cout << value << " ";
std::cout << "\nDamping: ";
for (const auto& value : damping) std::cout << value << " ";
std::cout << "\nStiffness: ";
for (const auto& value : stiffness) std::cout << value << " ";
std::cout << "\nKL2: ";
for (const auto& value : kl2) std::cout << value << " ";
std::cout << std::endl;
} else {
std::cerr << "Failed to retrieve impedance control gains." << std::endl;
}
set_force_control_gain() 예제
std::vector<float> kp = {...};
std::vector<float> kv = {...};
std::vector<float> kl2 = {...};
std::vector<float> mass = {...};
std::vector<float> damping = {...};
std::vector<float> stiffness = {...};
std::vector<float> kpf = {...};
std::vector<float> kif = {...};
bool is_success = indy.set_force_control_gain(kp, kv, kl2, mass, damping, stiffness, kpf, kif);
if (is_success) {
std::cout << "Force control gains set successfully." << std::endl;
} else {
std::cerr << "Failed to set force control gains." << std::endl;
}
get_force_control_gain() 예제
std::vector<float> kp, kv, kl2, mass, damping, stiffness, kpf, kif;
bool is_success = indy.get_force_control_gain(kp, kv, kl2, mass, damping, stiffness, kpf, kif);
if (is_success) {
std::cout << "Force control gains retrieved successfully." << std::endl;
std::cout << "KP: ";
for (const auto& value : kp) std::cout << value << " ";
std::cout << "\nKV: ";
for (const auto& value : kv) std::cout << value << " ";
std::cout << "\nKL2: ";
for (const auto& value : kl2) std::cout << value << " ";
std::cout << "\nMass: ";
for (const auto& value : mass) std::cout << value << " ";
std::cout << "\nDamping: ";
for (const auto& value : damping) std::cout << value << " ";
std::cout << "\nStiffness: ";
for (const auto& value : stiffness) std::cout << value << " ";
std::cout << "\nKPF: ";
for (const auto& value : kpf) std::cout << value << " ";
std::cout << "\nKIF: ";
for (const auto& value : kif) std::cout << value << " ";
std::cout << std::endl;
} else {
std::cerr << "Failed to retrieve force control gains." << std::endl;
}
유틸리티 기능
유틸리티 기능은 데이터 로깅 및 시뮬레이션 모드 설정과 같은 추가 기능을 제공합니다.
| 메서드 | 설명 |
|---|---|
start_log() |
실시간 데이터 로깅 시작 |
end_log() |
실시간 데이터 로깅을 종료하고 파일로 저장 |
wait_for_operation_state(op_state) |
로봇이 특정 운영 상태에 도달할 때까지 대기 |
wait_for_motion_state(motion_state) |
로봇이 특정 모션 상태에 도달할 때까지 대기 |
set_friction_comp_state(const bool enable) |
마찰 보상 활성화 / 비활성화 |
get_friction_comp_state() |
마찰 보상의 현재 상태 불러오기 |
set_mount_pos(float rot_y, float rot_z) |
Y와 Z방향 회전으로 로봇 베이스의 마운팅 각도 설정 |
get_mount_pos(float &rot_y, float &rot_z) |
로봇 베이스의 현재 마운팅 각도 불러오기 |
set_brakes(const std::vector<bool>& brake_state_list) |
각 모터의 브레이크 상태 설정 |
set_servo_all(const bool enable) |
모든 서보 활성화 / 비활성화 |
set_servo(const uint32_t index, const bool enable) |
특정 인덱스의 서보 활설화 / 비활성화 |
set_endtool_led_dim(const uint32_t led_dim) |
엔드 이펙터의 LED 밝기 설정 |
execute_tool(const std::string& name) |
입력된 이름의 툴 함수 실행 |
get_el5001(int& status, int& value, int& delta, float& average) |
EL5001 장치로부터 데이터 불러오기 |
get_el5101(int& status, int& value, int& latch, int& delta, float& average) |
EL5101 장치로부터 데이터 불러오기 |
get_brake_control_style(int& style) |
현재 브레이크 제어 방법 불러오기 |
set_conveyor_name(const std::string& name) |
컨베이어의 이름 설정 |
set_conveyor_encoder(int encoder_type, int64_t channel1, int64_t channel2, int64_t sample_num, float mm_per_tick, float vel_const_mmps, bool reversed) |
컨베이어 엔코더의 환경설정 |
set_conveyor_trigger(int trigger_type, int64_t channel, bool detect_rise) |
컨베이어 트리거 설정 |
set_conveyor_offset(float offset_mm) |
컨베이어 작업의 offset 값 설정 (밀리미터 단위) |
set_conveyor_starting_pose(const std::vector<float>& jpos, const std::vector<float>& tpos) |
컨베이어 작업의 시작 joint 및 task 위치 설정 |
set_conveyor_terminal_pose(const std::vector<float>& jpos, const std::vector<float>& tpos) |
컨베이어 작업의 마지막 joint 및 task 위치 설정 |
set_compliance_mode(bool enable, const std::vector<float>* stiffness) |
컴플라이언스 모드를 활성화/비활성화(옵션: 강성) |
get_compliance_mode(bool &enabled, std::vector<float>& stiffness) |
컴플라이언스 모드 상태와 강성 조회 |
set_force_mode(const std::map<std::string, float>& force_mode_cfg) |
힘제어 모드 설정 (축 방향, 목표 힘/토크) |
get_force_mode(std::map<std::string, float>& force_mode_cfg) |
현재 힘제어 설정 가져오기 |
get_transformed_ft_sensor_data(std::array<float,6>& wrench_ref, std::array<float,6>& wrench_tool) |
참조 좌표계와 툴 좌표계로 변환된 FT 센서 데이터 |
get_ft_zero(std::array<float,6>& bias) |
현재 FT 센서 영점(bias) 불러오기 |
get_load_factors(std::vector<float>& load_factors) |
로드 팩터 추정 데이터 불러오기 |
push_bus_event(uint32_t event_id, const std::vector<int32_t>& args) |
내부 버스 이벤트 게시 |
catch_bus_event(uint32_t event_id, uint32_t timeout_ms, std::vector<int32_t>& args) |
내부 버스 이벤트 대기 |
get_friction_comp(std::map<std::string,float>& params) |
마찰 보상 파라미터 불러오기 |
set_friction_comp(const std::map<std::string,float>& params) |
마찰 보상 파라미터 설정 |
get_coll_sens_level(int &level) |
충돌 민감도 레벨 불러오기 |
set_coll_sens_level(int level) |
충돌 민감도 레벨 설정 |
get_coll_sens_param(std::map<std::string,float>& params) |
충돌 임계값 파라미터 가져오기 |
set_coll_sens_param(const std::map<std::string,float>& params) |
충돌 임계값 파라미터 설정 |
get_coll_policy(int &policy, float &sleep_time, float &gravity_time) |
충돌 정책 가져오기 |
set_coll_policy(int policy, float sleep_time, float gravity_time) |
충돌 정책 설정 |
get_default_coll_sens_param(std::map<std::string,float>& params) |
기본 충돌 임계값 파라미터 불러오기 |
get_collison_model_margin(float &collision_margin, float &recover_margin) |
충돌 모델 마진 불러오기 |
set_collison_model_margin(float collision_margin, float recover_margin) |
충돌 모델 마진 설정 |
get_home_pos(std::vector<float>& jpos) |
홈 위치의 관절 값 가져오기 |
set_home_pos(const std::vector<float>& jpos) |
홈 위치의 관절 값 설정 |
get_ref_frame(std::array<float,6>& fpos) |
참조 좌표예 자세 가져오기 |
set_ref_frame(const std::array<float,6>& fpos) |
참조 좌표예 자세 설정 |
set_ref_frame_planar(const std::array<float,6>& fpos0, const std::array<float,6>& fpos1, const std::array<float,6>& fpos2) |
3개의 자세로 생성된 평면의 참조 좌표계 설정 |
save_reference_frame(const std::vector<std::array<float,6>>& frames, const std::string& default_name) |
참조 좌표계 저장 |
load_reference_frame(std::vector<std::array<float,6>>& frames, std::string &default_name) |
참조 좌표계 불러오기 |
get_tool_frame_list(std::map<std::string,std::array<float,6>>& frames) |
툴 좌표계 리스트 불러오기 |
set_tool_frame_list(const std::map<std::string,std::array<float,6>>& frames) |
툴 좌표계 리스트 설정 |
get_tool_list(std::map<std::string,std::map<std::string,float>>& tool_props) |
툴 속성 리스트 가져오기 |
set_tool_list(const std::map<std::string,std::map<std::string,float>>& tool_props) |
툴 속성 리스트 설정 |
get_tool_property(std::map<std::string,float>& props) |
현재 툴의 물리적 특성 가져오기 |
set_tool_property(const std::map<std::string,float>& props) |
현재 툴의 물리적 특성 설정 |
get_pack_pos(std::vector<float>& jpos) |
패키징 자세의 관절 값 가져오기 |
get_path_config(std::map<std::string,std::string>& info) |
Config 파일의 경로 불러오기 |
set_locked_joint(uint32_t index) |
잠금 관절 인덱스 설정 |
set_tool_link(uint32_t index) |
툴 링크의 인덱스 설정 |
get_custom_pos_list(std::map<std::string,std::array<float,6>>& poses) |
커스텀 위치 목록 불러오기 |
set_custom_pos_list(const std::map<std::string,std::array<float,6>>& poses) |
커스텀 위치 목록 설정 |
get_tool_shape_list(std::map<std::string,std::vector<float>>& shapes) |
툴 형상 모델 불러오기 |
set_tool_shape_list(const std::map<std::string,std::vector<float>>& shapes) |
툴 형상 모델 설정 |
get_environment_list(std::map<std::string,std::vector<float>>& envs) |
환경 모델 불러오기 |
set_environment_list(const std::map<std::string,std::vector<float>>& envs) |
환경 모델 설정 |
get_sensorless_params(std::map<std::string,float>& params) |
센서리스 컴플라이언스 파라미터 불러오기 |
set_sensorless_params(const std::map<std::string,float>& params) |
센서리스 컴플라이언스 파라미터 설정 |
get_compliance_control_joint_gain(std::map<std::string,float>& gains) |
컴플라이언스 제어 관절 게인 불러오기 |
set_compliance_control_joint_gain(const std::map<std::string,float>& gains) |
컴플라이언스 제어 관절 게인 설정 |
get_on_start_program_config(std::map<std::string,std::string>& cfg) |
자동 실행 프로그램 불러오기 |
set_on_start_program_config(const std::map<std::string,std::string>& cfg) |
자동 실행 프로그램 설정 |
get_auto_servo_off(bool &enable, float &time_s) |
자동 서보 오프 설정 불러오기 |
set_auto_servo_off(bool enable, float time_s) |
자동 서보 오프 설정 |
get_teleop_params(float &smooth_factor, float &cutoff_freq, float &error_gain) |
텔레오퍼레이션 필터 파라미터 불러오기 |
set_teleop_params(float smooth_factor, float cutoff_freq, float error_gain) |
텔레오퍼레이션 필터 파라미터 설정 |
get_kinematics_params(std::map<std::string,float>& params) |
기구학 파라미터 불러오기 |
get_io_data(std::map<std::string,int>& io) |
모든 IO 데이터 불러오기 |
set_safety_limits(const std::map<std::string,float>& limits) |
파워 / TCP 힘 / TCP 속도의 안전 한계값 설정 |
get_safety_limits(std::map<std::string,float>& limits) |
파워 / TCP 힘 / TCP 속도의 안전 한계값 불러오기 |
set_safety_stop_config(const std::map<std::string,int>& cfg) |
안전 정지 설정 |
get_safety_stop_config(std::map<std::string,int>& cfg) |
안전 정지 설정 불러오기 |
set_reduced_speed(float speed) |
감속 모드의 속도 설정 |
get_reduced_speed(float &speed) |
감속 모드의 속도 불러오기 |
get_reduced_ratio(float &ratio) |
감속 모드의 속도 비율 불러오기 |
request_safety_function(int id, int state) |
안전기능의 상태 전환 요청 |
get_safety_function_state(std::map<std::string,int>& states) |
안전 기능의 상태 확인 |
get_safety_control_data(std::map<std::string,float>& data) |
안전 데이터 확인 |
set_auto_mode(bool on) |
자동 모드 상태 설정 (true: 자동 / false: 수동) |
check_auto_mode(bool &on) |
자동 모드 상태 확인 (true: 자동 / false: 수동) |
check_reduced_mode(bool &active) |
감속 모드 활성화 여부 확인 |
get_control_info(std::map<std::string,std::string>& info) |
제어기 정보 확인 |
check_aproach_retract_valid(const std::map<std::string,float>& params, bool &valid) |
Approach/Retract 가능 여부 확인 |
get_pallet_point_list(const std::map<std::string,float>& cfg, std::vector<std::array<float,6>>& points) |
팔레타이징 포인트 리스트 불러오기 |
move_recover_joint(const std::vector<float>& jtarget, int base_type) |
충돌/Violation 이후 Recover MoveJ 실행 |
start_log() 및 end_log() 예제
bool is_success = indy.start_log();
if (is_success)
{
std::cout << "데이터 로깅을 시작했습니다." << std::endl;
}
// 시간이 지난 후...
is_success = indy.end_log();
if (is_success) {
std::cout << "데이터 로깅이 종료되고 데이터가 저장되었습니다." << std::endl;
}
이 두 함수는 실시간 데이터 로깅에 사용됩니다. start_log()를 호출하면 로봇의 데이터가 메모리에 저장됩니다. 일정 시간이 지난 후 end_log()를 호출하면 메모리 로깅이 중지되고 STEP 내 파일에 작성됩니다. 실시간 데이터 로깅 파일은 다음 경로에서 찾을 수 있습니다:
/home/user/release/IndyDeployments/RTlog/RTLog.csv
더 자세한 사용법 및 고급 기능은 C++ 클라이언트를 참조하세요. Neuromeka Github 저장소.
wait_for_operation_state(op_state)
예를 들어, 로봇이 MOVING 상태에 도달할 때까지 기다리고 싶다면, 다음과 같이 호출할 수 있습니다.
bool is_success = indy.wait_for_operation_state(OpState::OP_MOVING);
if (is_success) {
std::cout << "로봇이 목표 위치에 도달했습니다." << std::endl;
} else {
std::cerr << "로봇이 목표 위치에 도달하는 데 실패했습니다." << std::endl;
}
wait_for_motion_state(motion_state)
motion_state:is_target_reached(목표 도달 여부)is_in_motion(모션 진행 중)is_pausing(일시 중지 상태)is_stopping(정지 상태)has_motion(모션 발생 여부)
예를 들어, 로봇의 모션이 완료될 때까지 기다리고 싶다면, 'is_target_reached' 상태를 사용하여 다음과 같이 호출할 수 있습니다.
bool is_success = indy.wait_for_motion_state("is_target_reached");
if (is_success) {
std::cout << "로봇이 목표 위치에 도달했습니다." << std::endl;
} else {
std::cerr << "로봇이 목표 위치에 도달하는 데 실패했습니다." << std::endl;
}
set_friction_comp_state() 예제
bool is_success = indy.set_friction_comp_state(true);
if (is_success) {
std::cout << "Friction compensation enabled successfully." << std::endl;
} else {
std::cerr << "Failed to enable friction compensation." << std::endl;
}
get_friction_comp_state() 예제
bool is_enabled = indy.get_friction_comp_state();
if (is_enabled) {
std::cout << "Friction compensation is currently enabled." << std::endl;
} else {
std::cout << "Friction compensation is currently disabled." << std::endl;
}
set_mount_pos(float rot_y, float rot_z) 예제
Y와 Z방향 회전으로 로봇 베이스의 마운팅 각도를 설정합니다.
float rotation_y = 10.0f; // Rotation around Y-axis in degrees
float rotation_z = 5.0f; // Rotation around Z-axis in degrees
bool is_success = indy.set_mount_pos(rotation_y, rotation_z);
if (is_success) {
std::cout << "Mounting angles set successfully." << std::endl;
} else {
std::cerr << "Failed to set mounting angles." << std::endl;
}
get_mount_pos(float &rot_y, float &rot_z) 예제
로봇 베이스의 현재 마운팅 각도를 불러옵니다.
float rotation_y, rotation_z;
bool is_success = indy.get_mount_pos(rotation_y, rotation_z);
if (is_success) {
std::cout << "Retrieved mounting angles:" << std::endl;
std::cout << "Rotation Y: " << rotation_y << " degrees" << std::endl;
std::cout << "Rotation Z: " << rotation_z << " degrees" << std::endl;
} else {
std::cerr << "Failed to retrieve mounting angles." << std::endl;
}
set_brakes(const std::vector<bool>& brake_state_list) 예제
각 모터의 브레이크 상태를 설정합니다.
std::vector<bool> brake_states = {true, false, true, true, false, false};
bool is_success = indy.set_brakes(brake_states);
if (is_success) {
std::cout << "Brakes set successfully." << std::endl;
} else {
std::cerr << "Failed to set brakes." << std::endl;
}
set_servo_all(const bool enable) 예제
bool enable_servos = true;
bool is_success = indy.set_servo_all(enable_servos);
if (is_success) {
std::cout << "All servos enabled successfully." << std::endl;
} else {
std::cerr << "Failed to enable all servos." << std::endl;
}
set_servo(const uint32_t index, const bool enable) 예제
특정 인덱스의 서보를 활설화 또는 비활성화합니다.
uint32_t servo_index = 3;
bool enable_servo = true;
bool is_success = indy.set_servo(servo_index, enable_servo);
if (is_success) {
std::cout << "Servo " << servo_index << " enabled successfully." << std::endl;
} else {
std::cerr << "Failed to enable servo " << servo_index << "." << std::endl;
}
set_endtool_led_dim(const uint32_t led_dim) 예제
엔드 이펙터 LED의 밝기를 설정합니다.
uint32_t led_brightness = ...;
bool is_success = indy.set_endtool_led_dim(led_brightness);
if (is_success) {
std::cout << "End-effector LED brightness set to " << led_brightness << "." << std::endl;
} else {
std::cerr << "Failed to set LED brightness." << std::endl;
}
execute_tool(const std::string& name) 예제
std::string tool_name = "GripperOpen";
bool is_success = indy.execute_tool(tool_name);
if (is_success) {
std::cout << "Tool function '" << tool_name << "' executed successfully." << std::endl;
} else {
std::cerr << "Failed to execute tool function '" << tool_name << "'." << std::endl;
}
get_el5001(int& status, int& value, int& delta, float& average) 예제
EL5001 장치로부터 데이터를 불러옵니다.
int status, value, delta;
float average;
bool is_success = indy.get_el5001(status, value, delta, average);
if (is_success) {
std::cout << "EL5001 Data:" << std::endl;
std::cout << "Status: " << status << ", Value: " << value << ", Delta: " << delta << ", Average: " << average << std::endl;
} else {
std::cerr << "Failed to retrieve data from EL5001 device." << std::endl;
}
get_el5101(int& status, int& value, int& latch, int& delta, float& average) 예제
EL5101 장치로부터 데이터를 불러옵니다.
int status, value, latch, delta;
float average;
bool is_success = indy.get_el5101(status, value, latch, delta, average);
if (is_success) {
std::cout << "EL5101 Data:" << std::endl;
std::cout << "Status: " << status << ", Value: " << value << ", Latch: " << latch << ", Delta: " << delta << ", Average: " << average << std::endl;
} else {
std::cerr << "Failed to retrieve data from EL5101 device." << std::endl;
}
get_brake_control_style(int& style) 예제
현재 브레이크의 제어 방법을 불러옵니다.
int style;
bool is_success = indy.get_brake_control_style(style);
if (is_success) {
std::cout << "Brake control style: " << style << std::endl;
} else {
std::cerr << "Failed to retrieve brake control style." << std::endl;
}
set_conveyor_name(const std::string& name) 예제
컨베이어의 이름을 설정합니다.
std::string conveyor_name = "MainConveyor";
bool is_success = indy.set_conveyor_name(conveyor_name);
if (is_success) {
std::cout << "Conveyor name set to '" << conveyor_name << "'." << std::endl;
} else {
std::cerr << "Failed to set conveyor name." << std::endl;
}
set_conveyor_encoder(...) 예제
int encoder_type = 1; // Type of encoder
int64_t channel1 = 0, channel2 = 1, sample_num = 100;
float mm_per_tick = 0.01, vel_const_mmps = 500.0;
bool reversed = false;
bool is_success = indy.set_conveyor_encoder(encoder_type, channel1, channel2, sample_num, mm_per_tick, vel_const_mmps, reversed);
if (is_success) {
std::cout << "Conveyor encoder configured successfully." << std::endl;
} else {
std::cerr << "Failed to configure conveyor encoder." << std::endl;
}
set_conveyor_trigger(int trigger_type, int64_t channel, bool detect_rise) 예제
int trigger_type = 2; // Trigger type
int64_t channel = 0;
bool detect_rise = true;
bool is_success = indy.set_conveyor_trigger(trigger_type, channel, detect_rise);
if (is_success) {
std::cout << "Conveyor trigger set successfully." << std::endl;
} else {
std::cerr << "Failed to set conveyor trigger." << std::endl;
}
set_conveyor_offset(float offset_mm) 예제
컨베이어 작업에 대해 밀리미터 단위의 offset 값을 설정합니다.
float offset = ...;
bool is_success = indy.set_conveyor_offset(offset);
if (is_success) {
std::cout << "Conveyor offset set to " << offset << " mm." << std::endl;
} else {
std::cerr << "Failed to set conveyor offset." << std::endl;
}
set_conveyor_starting_pose(const std::vector<float>& jpos, const std::vector<float>& tpos) 예제
컨베이어 작업의 시작 joint 및 task 위치 설정합니다.
std::vector<float> joint_positions = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
std::vector<float> task_positions = {};
bool is_success = indy.set_conveyor_starting_pose(joint_positions, task_positions);
if (is_success) {
std::cout << "Conveyor starting pose set successfully." << std::endl;
} else {
std::cerr << "Failed to set conveyor starting pose." << std::endl;
}
set_conveyor_terminal_pose(const std::vector<float>& jpos, const std::vector<float>& tpos) 예제
컨베이어 작업의 마지막 joint 및 task 위치 설정합니다.
std::vector<float> joint_positions = {0.0, 0.0, -90.0, 0.0, -90.0, 0.0};
std::vector<float> task_positions = {};
bool is_success = indy.set_conveyor_terminal_pose(joint_positions, task_positions);
if (is_success) {
std::cout << "Conveyor terminal pose set successfully." << std::endl;
} else {
std::cerr << "Failed to set conveyor terminal pose." << std::endl;
}
set_compliance_mode(), get_compliance_mode() 예제
Nrmk::IndyFramework::ComplianceMode mode;
mode.set_enable(true);
int stiffness_vals[6] = {1000,1000,800,50,50,50};
for (int v : stiffness_vals) mode.add_stiffness(v);
bool ok = indy.set_compliance_mode(mode);
std::cout << "set_compliance_mode: " << (ok ? "OK" : "FAIL") << "\n";
Nrmk::IndyFramework::ComplianceMode mode_read;
ok = indy.get_compliance_mode(mode_read);
std::cout << "get_compliance_mode: " << (ok ? "OK" : "FAIL");
if (ok) {
std::cout << " enable=" << mode_read.enable()
<< " stiffness_size=" << mode_read.stiffness_size()
<< " [";
for (int i = 0; i < mode_read.stiffness_size(); ++i) {
if (i) std::cout << ",";
std::cout << mode_read.stiffness(i);
}
std::cout << "]";
}
std::cout << "\n";
get_transformed_ft_sensor_data() 예제
Nrmk::IndyFramework::TransformedFTSensorData tft;
bool ok = indy.get_transformed_ft_sensor_data(tft);
std::cout << "get_transformed_ft_sensor_data: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " Fx="<<tft.ft_fx()<<" Fy="<<tft.ft_fy()<<" Fz="<<tft.ft_fz()
<< " Tx="<<tft.ft_tx()<<" Ty="<<tft.ft_ty()<<" Tz="<<tft.ft_tz();
}
std::cout << "\n";
get_ft_zero() 예제
bool ft_zero_ok = indy.get_ft_zero();
std::cout << "get_ft_zero: " << (ft_zero_ok ? "OK" : "FAIL") << "\n";
get_load_factors()
Nrmk::IndyFramework::GetLoadFactorsRes load;
bool ok = indy.get_load_factors(load);
std::cout << "get_load_factors: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " percents=[";
for (int i=0;i<load.percents_size();++i){ if(i) std::cout<<","; std::cout<<load.percents(i); }
std::cout << "] torques=[";
for (int i=0;i<load.torques_size();++i){ if(i) std::cout<<","; std::cout<<load.torques(i); }
std::cout << "]";
}
std::cout << "\n";
get_load_factors:
status: OK
percents: [0, 0, 0, 0, 0, 0]
torques: [-2.57318e-21, 0.00467472, 0.00420347, -7.87171e-16, 0.00145352, -2.36064e-19]
push_bus_event(),catch_bus_event() 예제
const uint32_t EVENT_ID_PART_ARRIVED = 10;
Nrmk::IndyFramework::BusEvent bevent;
bevent.set_event_id(EVENT_ID_PART_ARRIVED);
bevent.set_text_data("Part Arrived");
bool ok = indy.push_bus_event(bevent);
std::cout << "push_bus_event(10): " << (ok?"OK":"FAIL") << "\n";
Nrmk::IndyFramework::CatchBusEventReq req;
req.set_event_id(EVENT_ID_PART_ARRIVED);
req.set_timeout(5.0f);
Nrmk::IndyFramework::BusEvent caught;
ok = indy.catch_bus_event(req, caught);
std::cout << "catch_bus_event(10): " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " event_id=" << caught.event_id()
<< " text='" << caught.text_data() << "'";
}
std::cout << "\n";
get_friction_comp(),set_friction_comp() 예제
Nrmk::IndyFramework::FrictionCompSet fric;
bool ok = indy.get_friction_comp(fric);
std::cout << "get_friction_comp: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " control_enable="<<fric.control_comp_enable()
<< " teaching_enable="<<fric.teaching_comp_enable()
<< " control_levels="<<fric.control_comp_levels_size()
<< " teaching_levels="<<fric.teaching_comp_levels_size();
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_friction_comp(fric);
std::cout << "set_friction_comp(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_friction_comp:
status: OK
control_enable: 0
teaching_enable: 0
control_levels: 6
teaching_levels: 6
set_friction_comp: OK
get_coll_sens_level(),set_coll_sens_level() 예제
unsigned int level=0;
bool ok = indy.get_coll_sens_level(level);
std::cout << "get_coll_sens_level: " << (ok?"OK":"FAIL");
if (ok) std::cout << " level=" << level;
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_coll_sens_level(level);
std::cout << "set_coll_sens_level(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_coll_sens_param(),set_coll_sens_param(),get_default_coll_sens_param() 예제
Nrmk::IndyFramework::CollisionThresholds thr;
bool ok = indy.get_coll_sens_param(thr);
std::cout << "get_coll_sens_param: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " j_torque_bases=[";
for (int i=0;i<thr.j_torque_bases_size();++i) { if (i) std::cout << ","; std::cout << thr.j_torque_bases(i); }
std::cout << "]";
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_coll_sens_param(thr);
std::cout << "set_coll_sens_param(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
Nrmk::IndyFramework::CollisionThresholds def_thr;
ok = indy.get_default_coll_sens_param(def_thr);
std::cout << "get_default_coll_sens_param: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " j_torque_bases=[";
for (int i=0;i<def_thr.j_torque_bases_size();++i) { if (i) std::cout << ","; std::cout << def_thr.j_torque_bases(i); }
std::cout << "]";
}
std::cout << "\n";
get_coll_sens_param:
status: OK
j_torque_bases: [28.6619, 39.3071, 12.5298, 500, 3.2722, 3.94439]
set_coll_sens_param: OK
get_default_coll_sens_param:
status: OK
j_torque_bases: [36.5185, 35.8493, 13.2479, 5.48176, 3.25222, 2.24444]
get_coll_policy(),set_coll_policy() 예제
Nrmk::IndyFramework::CollisionPolicy policy;
bool ok = indy.get_coll_policy(policy);
std::cout << "get_coll_policy: " << (ok?"OK":"FAIL");
if (ok) std::cout << " policy="<<policy.policy()
<< " sleep="<<policy.sleep_time()
<< " gravity="<<policy.gravity_time();
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_coll_policy(policy);
std::cout << "set_coll_policy(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_collison_model_margin(),set_collison_model_margin() 예제
Nrmk::IndyFramework::CollisionModelMargin margin;
bool ok = indy.get_collison_model_margin(margin);
std::cout << "get_collison_model_margin: " << (ok?"OK":"FAIL");
if (ok) std::cout << " collision_margin="<<margin.collision_margin()
<< " recover_margin="<<margin.recover_margin();
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_collison_model_margin(margin);
std::cout << "set_collison_model_margin(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_collison_model_margin:
status: OK
collision_margin: 0.01
recover_margin: 0.0
set_collison_model_margin: OK
get_home_pos(),set_home_pos() 예제
Nrmk::IndyFramework::JointPos home;
bool ok = indy.get_home_pos(home);
std::cout << "get_home_pos: " << (ok?"OK":"FAIL");
if (ok) std::cout << " size=" << home.jpos_size();
std::cout << "\n";
if (ok) {
Nrmk::IndyFramework::JointPos new_home;
float vals[6] = {0,0,-90,0,-90,0};
for (float v : vals) new_home.add_jpos(v);
bool set_ok = indy.set_home_pos(new_home);
std::cout << "set_home_pos: " << (set_ok?"OK":"FAIL") << "\n";
}
get_ref_frame(),set_ref_frame() 예제
std::array<float,6> fpos{};
bool ok = indy.get_ref_frame(fpos);
std::cout << "get_ref_frame: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " fpos=["<<fpos[0]<<","<<fpos[1]<<","<<fpos[2]<<","<<fpos[3]<<","<<fpos[4]<<","<<fpos[5]<<"]";
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_ref_frame(fpos);
std::cout << "set_ref_frame(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_tool_frame_list(),set_tool_frame_list() 예제
Nrmk::IndyFramework::ToolFrameList tfl;
bool ok = indy.get_tool_frame_list(tfl);
std::cout << "get_tool_frame_list: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " frames=[";
for (int i=0;i<tfl.tool_frames_size();++i) {
if (i) std::cout << ";";
const auto& tf = tfl.tool_frames(i);
std::cout << tf.name() << ":[";
for (int j=0;j<tf.tpos_size();++j) { if (j) std::cout << ","; std::cout << tf.tpos(j); }
std::cout << "]";
}
std::cout << "] default=" << tfl.default_name();
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_tool_frame_list(tfl);
std::cout << "set_tool_frame_list(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_tool_frame_list:
status: OK
frames:
- name: tool_0
tpos: [0, 0, 0, 0, 0, 0]
default: tool_0
set_tool_frame_list: OK
get_tool_list(),set_tool_list() 예제
Nrmk::IndyFramework::ToolList tlist;
bool ok = indy.get_tool_list(tlist);
std::cout << "get_tool_list: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " tools=[";
for (int i=0;i<tlist.tools_size();++i) {
if (i) std::cout << ";";
std::cout << tlist.tools(i).name();
}
std::cout << "]";
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_tool_list(tlist);
std::cout << "set_tool_list(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_tool_list:
status: OK
tools: [gripper_Init, gripper_Reset, gripper_on, gripper_off]
set_tool_list: OK
get_tool_property(),set_tool_property() 예제
Nrmk::IndyFramework::ToolProperties tp;
bool ok = indy.get_tool_property(tp);
std::cout << "get_tool_property: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " mass="<<tp.mass();
std::cout << " com=[";
for (int i=0;i<tp.center_of_mass_size();++i){ if(i) std::cout<<","; std::cout<<tp.center_of_mass(i); }
std::cout << "] inertia=[";
for (int i=0;i<tp.inertia_size();++i){ if(i) std::cout<<","; std::cout<<tp.inertia(i); }
std::cout << "]";
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_tool_property(tp);
std::cout << "set_tool_property(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_tool_property:
status: OK
mass: 0
com: [0, 0, 0]
inertia: [0, 0, 0, 0, 0, 0]
set_tool_property: OK
get_pack_pos() 예제
std::vector<float> pack_jpos;
bool ok = indy.get_pack_pos(pack_jpos);
std::cout << "get_pack_pos: " << (ok?"OK":"FAIL");
if (ok) std::cout << " jpos_size=" << pack_jpos.size();
std::cout << "\n";
get_pack_pos() 예제
std::vector<float> pack_jpos;
bool ok = indy.get_pack_pos(pack_jpos);
std::cout << "get_pack_pos: " << (ok?"OK":"FAIL");
if (ok) std::cout << " jpos_size=" << pack_jpos.size();
std::cout << "\n";
get_path_config() 예제
Nrmk::IndyFramework::PathConfig pconf;
bool ok = indy.get_path_config(pconf);
std::cout << "get_path_config: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " config_path='" << pconf.config_path() << "' safety_path_list=[";
for (int i=0;i<pconf.safety_path_list_size();++i) {
if (i) std::cout << ";";
std::cout << pconf.safety_path_list(i);
}
std::cout << "]";
}
std::cout << "\n";
get_path_config:
status: OK
config_path: "/home/user/dev/runtest/Release/IndyDeployment/../IndyConfigurations/Cobot/Configs"
safety_path_list:
- "/home/user/dev/runtest/Release/IndyDeployment/../IndyConfigurations/Cobot/Params/CollisionGain.json"
- "/home/user/dev/runtest/Release/IndyDeployment/../IndyConfigurations/Cobot/Params/ControlGain.json"
- "/home/user/dev/runtest/Release/IndyDeployment/../IndyConfigurations/Cobot/Configs/SafetyConfig.json"
set_locked_joint(), set_tool_link() 예제
bool lock_ok = indy.set_locked_joint(5);
std::cout << "set_locked_joint(5): " << (lock_ok?"OK":"FAIL") << "\n";
bool tool_link_ok = indy.set_tool_link(6);
std::cout << "set_tool_link(6): " << (tool_link_ok?"OK":"FAIL") << "\n";
get_custom_pos_list(), set_custom_pos_list() 예제
Nrmk::IndyFramework::CustomPosList cplist;
bool ok = indy.get_custom_pos_list(cplist);
std::cout << "get_custom_pos_list: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " custom_pos=[";
for (int i=0;i<cplist.custom_pos_size();++i) {
if (i) std::cout << ";";
const auto& cp = cplist.custom_pos(i);
std::cout << cp.name() << ":[";
for (int j=0;j<cp.jpos_size();++j) { if (j) std::cout << ","; std::cout << cp.jpos(j); }
std::cout << "]";
}
std::cout << "]";
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_custom_pos_list(cplist);
std::cout << "set_custom_pos_list(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_custom_pos_list:
status: OK
custom_pos:
- name: test_1
jpos: [5.62114, -13.5501, -62.8307, -8.22606, -103.113, -0.0466959]
- name: test_2
jpos: [32.5509, -0.193804, -91.9896, -6.77046, -91.9321, -3.7074]
set_custom_pos_list: OK
get_tool_shape_list(), set_tool_shape_list() 예제
Nrmk::IndyFramework::ToolShapeList tshapes;
bool ok = indy.get_tool_shape_list(tshapes);
std::cout << "get_tool_shape_list: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " geometries=[";
for (int i=0;i<tshapes.geometries_size();++i) {
if (i) std::cout << ";";
const auto& g = tshapes.geometries(i);
std::cout << g.name() << "(shapes=" << g.shapes_size() << ")";
}
std::cout << "]";
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_tool_shape_list(tshapes);
std::cout << "set_tool_shape_list(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_environment_list(), set_environment_list() 예제
Nrmk::IndyFramework::EnvironmentList envs;
bool ok = indy.get_environment_list(envs);
std::cout << "get_environment_list: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " envs=[";
for (int i=0;i<envs.environments_size();++i) {
if (i) std::cout << ";";
const auto& e = envs.environments(i);
std::cout << e.name() << "(zones=" << e.zones_size() << ")";
}
std::cout << "] default=" << envs.default_name();
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_environment_list(envs);
std::cout << "set_environment_list(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_sensorless_params(), set_sensorless_params() 예제
Nrmk::IndyFramework::SensorlessParams sparams;
bool ok = indy.get_sensorless_params(sparams);
std::cout << "get_sensorless_params: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " tau_bound=[";
for (int i=0;i<sparams.tau_bound_size();++i) { if (i) std::cout << ","; std::cout << sparams.tau_bound(i); }
std::cout << "]";
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_sensorless_params(sparams);
std::cout << "set_sensorless_params(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_compliance_control_joint_gain(), set_compliance_control_joint_gain() 예제
Nrmk::IndyFramework::ComplianceGainSet gains;
ok = indy.get_compliance_control_joint_gain(gains);
std::cout << "get_compliance_control_joint_gain: " << (ok?"OK":"FAIL")
<< (ok ? " kp_size=" + std::to_string(gains.kp_size()) : "") << "\n";
if (ok) {
bool set_ok = indy.set_compliance_control_joint_gain(gains);
std::cout << "set_compliance_control_joint_gain(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_on_start_program_config(), set_on_start_program_config() 예제
Nrmk::IndyFramework::OnStartProgramConfig onstart;
ok = indy.get_on_start_program_config(onstart);
std::cout << "get_on_start_program_config: " << (ok?"OK":"FAIL")
<< (ok ? " index=" + std::to_string(onstart.index()) : "") << "\n";
if (ok) {
bool set_ok = indy.set_on_start_program_config(onstart);
std::cout << "set_on_start_program_config(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_auto_servo_off(),set_auto_servo_off() 예제
Nrmk::IndyFramework::AutoServoOffConfig as;
bool ok = indy.get_auto_servo_off(as);
std::cout << "get_auto_servo_off: " << (ok?"OK":"FAIL");
if (ok) std::cout << " enable="<<as.enable() << " time="<<as.time();
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_auto_servo_off(as);
std::cout << "set_auto_servo_off(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_teleop_params(),set_teleop_params() 예제
Nrmk::IndyFramework::TeleOpParams tele;
ok = indy.get_teleop_params(tele);
std::cout << "get_teleop_params: " << (ok?"OK":"FAIL");
if (ok) std::cout << " smooth_factor="<<tele.smooth_factor()
<< " cutoff_freq="<<tele.cutoff_freq()
<< " error_gain="<<tele.error_gain();
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_teleop_params(tele);
std::cout << "set_teleop_params(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_teleop_params:
status: OK
smooth_factor: 0.6
cutoff_freq: 1000
error_gain: 1.2
set_teleop_params: OK
get_kinematics_params() 예제
Nrmk::IndyFramework::KinematicsParams kin;
bool ok = indy.get_kinematics_params(kin);
std::cout << "get_kinematics_params: " << (ok?"OK":"FAIL") << "\n";
if (ok) {
for (int i=0;i<kin.mdh_size();++i) {
const auto& l = kin.mdh(i);
std::cout << " mdh["<<i<<"] idx="<<l.index()
<< " parent="<<l.parent()
<< " a="<<l.a() << " d0="<<l.d0()
<< " alpha="<<l.alpha() << " theta0="<<l.theta0()
<< " type="<<l.type() << "\n";
}
}
get_kinematics_params:
status: OK
mdh:
- {idx: 0, parent: -1, a: 0, d0: 300, alpha: 0, theta0: 0, type: 0}
- {idx: 1, parent: 0, a: 0, d0: 0, alpha: 90, theta0: 90, type: 0}
- {idx: 2, parent: 1, a: 450, d0: 0, alpha: 0, theta0: 90, type: 0}
- {idx: 3, parent: 2, a: 0, d0: 350, alpha: 90, theta0: 180, type: 0}
- {idx: 4, parent: 3, a: 0, d0: 186.5,alpha: 90, theta0: 0, type: 0}
- {idx: 5, parent: 4, a: 0, d0: 228, alpha: -90, theta0: 0, type: 0}
get_io_data() 예제
Nrmk::IndyFramework::IOData io;
bool ok = indy.get_io_data(io);
std::cout << "get_io_data: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " di_count="<<io.di_size()
<< " do_count="<<io.do__size()
<< " ai_count="<<io.ai_size()
<< " ao_count="<<io.ao_size();
if (io.di_size()>0) {
int show = std::min(io.di_size(), 8);
std::cout << " di_sample=[";
for (int i=0;i<show;++i) {
if (i) std::cout << ";";
std::cout << io.di(i).address() << ":" << io.di(i).state();
}
std::cout << "]";
if (io.di_size()>show) std::cout << " +"<<(io.di_size()-show);
}
}
std::cout << "\n";
get_io_data:
status: OK
di_count: 32
do_count: 32
ai_count: 8
ao_count: 8
di_sample: ["0:2","1:2","2:2","3:2","4:2","5:2","6:2","7:2"]
di_remaining: 24
get_safety_limits(),set_safety_limits() 예제
Nrmk::IndyFramework::SafetyLimits sl;
ok = indy.get_safety_limits(sl);
std::cout << "get_safety_limits: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << std::fixed << std::setprecision(1)
<< " power="<<sl.power_limit()<<" ("<<sl.power_limit_ratio()<<"%)"
<< " tcp_force="<<sl.tcp_force_limit()<<" ("<<sl.tcp_force_limit_ratio()<<"%)"
<< " tcp_speed="<<sl.tcp_speed_limit()<<" ("<<sl.tcp_speed_limit_ratio()<<"%)";
std::cout << " j_upper=[";
for (int i=0;i<sl.joint_upper_limits_size();++i){ if(i) std::cout<<","; std::cout<<sl.joint_upper_limits(i); }
std::cout << "] j_lower=[";
for (int i=0;i<sl.joint_lower_limits_size();++i){ if(i) std::cout<<","; std::cout<<sl.joint_lower_limits(i); }
std::cout << "]";
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_safety_limits(sl);
std::cout << "set_safety_limits(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_safety_limits:
status: OK
power_limit: {value: 1000.0, ratio_percent: 100.0}
tcp_force_limit: {value: 50.0, ratio_percent: 100.0}
tcp_speed_limit: {value: 500.0, ratio_percent: 100.0}
joint_upper_limits: [175.0, 175.0, 175.0, 175.0, 175.0, 215.0]
joint_lower_limits: [-175.0, -175.0, -175.0, -175.0, -175.0, -215.0]
set_safety_limits: OK
get_safety_stop_config(),set_safety_stop_config() 예제
Nrmk::IndyFramework::SafetyStopConfig ssc;
ok = indy.get_safety_stop_config(ssc);
std::cout << "get_safety_stop_config: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " jpos_cat="<<ssc.joint_position_limit_stop_cat()
<< " jvel_cat="<<ssc.joint_speed_limit_stop_cat()
<< " jtau_cat="<<ssc.joint_torque_limit_stop_cat()
<< " tvel_cat="<<ssc.tcp_speed_limit_stop_cat()
<< " tforce_cat="<<ssc.tcp_force_limit_stop_cat()
<< " power_cat="<<ssc.power_limit_stop_cat()
<< " safegd_stop_cat_size="<<ssc.safegd_stop_cat_size();
if (ssc.safegd_stop_cat_size()>0) {
std::cout << " safegd_stop_cat=[";
for(int i=0;i<ssc.safegd_stop_cat_size();++i){ if(i) std::cout<<","; std::cout<<ssc.safegd_stop_cat(i); }
std::cout << "]";
}
if (ssc.safegd_type_size()>0) {
std::cout << " safegd_type=[";
for(int i=0;i<ssc.safegd_type_size();++i){ if(i) std::cout<<","; std::cout<<ssc.safegd_type(i); }
std::cout << "]";
}
}
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_safety_stop_config(ssc);
std::cout << "set_safety_stop_config(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_safety_stop_config:
status: OK
jpos_cat: 0
jvel_cat: 2
jtau_cat: 2
tvel_cat: 2
tforce_cat: 2
power_cat: 2
safegd_stop_cat: [2, 2]
safegd_type: [1, 1]
set_safety_stop_config: OK
get_reduced_speed(),set_reduced_speed(),get_reduced_ratio() 예제
float rspeed=0.f; ok = indy.get_reduced_speed(rspeed);
std::cout << "get_reduced_speed: " << (ok?"OK":"FAIL");
if (ok) std::cout << " speed="<<rspeed;
std::cout << "\n";
float rratio=0.f; ok = indy.get_reduced_ratio(rratio);
std::cout << "get_reduced_ratio: " << (ok?"OK":"FAIL");
if (ok) std::cout << " ratio="<<rratio;
std::cout << "\n";
if (ok) {
bool set_ok = indy.set_reduced_speed(rspeed);
std::cout << "set_reduced_speed(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_reduced_speed:
status: OK
speed: 250.0
get_reduced_ratio:
status: OK
ratio: 25.0
set_reduced_speed: OK
get_safety_function_state(),request_safety_function() 예제
Nrmk::IndyFramework::SafetyFunctionState sfs;
ok = indy.get_safety_function_state(sfs);
std::cout << "get_safety_function_state: " << (ok?"OK":"FAIL");
if (ok) std::cout << " id="<<sfs.id()<<" state="<<sfs.state();
std::cout << "\n";
if (ok) {
Nrmk::IndyFramework::SafetyFunctionState req;
req.set_id(sfs.id());
req.set_state(sfs.state());
bool set_ok = indy.request_safety_function(req);
std::cout << "request_safety_function(echo): " << (set_ok?"OK":"FAIL") << "\n";
}
get_safety_control_data() 예제
Nrmk::IndyFramework::SafetyControlData scd;
ok = indy.get_safety_control_data(scd);
std::cout << "get_safety_control_data: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " safety_state(id="<<scd.safety_state().id()
<< ",state="<<scd.safety_state().state()<<")"
<< " auto_mode="<<scd.auto_mode()
<< " reduced_mode="<<scd.reduced_mode()
<< " enabler_pressed="<<scd.enabler_pressed();
}
std::cout << "\n";
get_safety_control_data:
status: OK
safety_state: {id: 0, state: 0}
auto_mode: 0
reduced_mode: 0
enabler_pressed: 0
set_auto_mode(),check_auto_mode(),check_reduced_mode() 예제
Nrmk::IndyFramework::CheckAutoModeRes am;
ok = indy.check_auto_mode(am);
std::cout << "check_auto_mode: " << (ok?"OK":"FAIL");
if (ok) std::cout << " on="<<am.on();
std::cout << "\n";
if (ok && !am.on()) {
bool set_ok = indy.set_auto_mode(true);
std::cout << "set_auto_mode(true): " << (set_ok?"OK":"FAIL") << "\n";
}
Nrmk::IndyFramework::CheckReducedModeRes rm;
ok = indy.check_reduced_mode(rm);
std::cout << "check_reduced_mode: " << (ok?"OK":"FAIL");
if (ok) std::cout << " on="<<rm.on();
std::cout << "\n";
get_control_info() 예제
Nrmk::IndyFramework::ControlInfo cinfo;
ok = indy.get_control_info(cinfo);
std::cout << "get_control_info: " << (ok?"OK":"FAIL");
if (ok) std::cout << " version="<<cinfo.control_version()
<< " model="<<cinfo.robot_model();
std::cout << "\n";
check_aproach_retract_valid() 예제
std::array<float,6> zeros{0,0,0,0,0,0};
std::vector<float> init_jpos(6,0.f);
Nrmk::IndyFramework::CheckAproachRetractValidRes car_res;
ok = indy.check_aproach_retract_valid(zeros, init_jpos, zeros, zeros, car_res);
std::cout << "check_aproach_retract_valid: " << (ok?"OK":"FAIL");
if (ok) {
std::cout << " is_valid=" << car_res.is_valid();
std::cout << " tar_pos=[";
for (int i=0;i<car_res.tar_pos_size();++i){ if(i) std::cout<<","; std::cout<<car_res.tar_pos(i); }
std::cout << "] approach_pos=[";
for (int i=0;i<car_res.approach_pos_size();++i){ if(i) std::cout<<","; std::cout<<car_res.approach_pos(i); }
std::cout << "] retract_pos=[";
for (int i=0;i<car_res.retract_pos_size();++i){ if(i) std::cout<<","; std::cout<<car_res.retract_pos(i); }
std::cout << "]";
}
std::cout << "\n";
check_aproach_retract_valid:
status: OK
is_valid: 1
tar_pos: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
approach_pos: [0.0, -186.5, 1328.0, 180.0, 180.0, 180.0]
retract_pos: [0.0, -186.5, 1328.0, 180.0, 180.0, 180.0]
get_pallet_point_list() 예제
std::array<float,6> zeros2{0,0,0,0,0,0};
std::vector<float> init_jpos2(6,0.f);
Nrmk::IndyFramework::GetPalletPointListRes pallet_res;
ok = indy.get_pallet_point_list(zeros2, init_jpos2, zeros2, zeros2, /*pattern*/1, /*width*/100, /*height*/100, pallet_res);
std::cout << "get_pallet_point_list: " << (ok?"OK":"FAIL");
if (ok) std::cout << " points=" << pallet_res.pallet_points_size();
std::cout << "\n";
if (ok && pallet_res.pallet_points_size()>0) {
const auto& pp = pallet_res.pallet_points(0);
std::cout << " first.tar_pos_sz="<<pp.tar_pos_size()
<< " approach_pos_sz="<<pp.approach_pos_size()
<< " retract_pos_sz="<<pp.retract_pos_size()
<< " tar_jpos_sz="<<pp.tar_jpos_size() << "\n";
}