C++ IndyDCP client
C++ IndyDCP client 는 IndyDCP Protocol 을 기반으로 Indy 를 제어할 수 있는 C++ class 입니다. 모든 관련 함수는 IndyDCPConnector.h 에 선언되어 있습니다.
설치
C++ IndyDCP client 의 소스파일과 프로젝트 파일은 다운로드 페이지에서 사용중인 Indy SW와 동일버전으로 다운로드 해주시기 바랍니다.
C++ IndyDCP client 는 WIndows와 Linux 두 OS에서 사용할 수 있습니다. 윈도우 환경에서 실행시킬 경우 아래 경로의 Visual Studio 프로젝트를 여시면 됩니다.
- /IndyDCPClientWindows/IndyDCPClientWindows.sln
Notes
Visual Studio에서 "precompiled header"와 관련된 에러가 발생할 경우 아래와 같이 관련 옵션을 해제하십시오.
- 프로젝트 속성 페이지, "구성 속성 > C/C++ > 미리 컴파일된 헤더" 탭으로 이동
- "미리 컴파일된 헤더" 옵션을 "사용 안 함"으로 변경.
Socket 통신의 초기화와 종료
C++ IndyDCP client 를 사용하기 전, OS별로 아래와 같이 socket 통신을 사용하기 위한 라이브러리 초기화를 수행해야 합니다. Windows의 경우 별도의 종료 함수도 호출해주어야 합니다.
Indy와의 연결 및 연결 해제
Indy 와의 모든 통신은 IndyDCPConnector.h 에 선언되어 있는 IndyDCPConnector 클래스를 통해 수행할 수 있습니다. IndyDCPConnector 객체를 초기화하기 위해서는, Indy 의 종류와 IP 주소를 입력해야 합니다. 사용 가능한 모든 로봇 종류는 NRMKIndy::Service::DCP namespace 안에 정의되어 있습니다.
#include "IndyDCPConnector.h"
using namespace NRMKIndy::Service::DCP;
//Indy 초기화
IndyDCPConnector connector("로봇.IP를.여기에.입력", ROBOT_INDY7);
//Indy에 연결
connector.connect()
///////////////////////////
// Indy 작업이 들어갈 부분 //
//////////////////////////
//Indy 연결 해제
connector.disconnect()
C++ IndyDCP 명령어 리스트
아래는 IndyDCP 전체 명령어 중 일부에 대한 사용 예시들을 나타냅니다. 예시에 포함되지 않은 명령어는 전체 명령어 리스트에서 확인할 수 있으며 사용방법에 대해서는 다운받은 C++ IndyDCP 코드를 참고해주시기 바랍니다.
Note
모든 **IndyDCPConnector** 함수의 반환 값은 정수 에러 코드로 함수의 기능과는 관련이 없습니다. 요청한 값에 대한 반환은 참조자를 통해 반환합니다 (call-by-reference).
함수 | 기능 |
---|---|
stopEmergency() | 비상정지 실행 |
resetRobot() | 로봇 리셋 |
setServoOnOff(const char * const servoVec) setServoOnOff(const bool * const servoVec) setServoOnOff(std::initializer_list |
servoVec 값에 따라 서보 On/Off |
setBrakeOnOff(const char * const brakeVec) setBrakeOnOff(const bool * const brakeVec) setBrakeOnOff(std::initializer_list |
brakeVec 값에 따라 브레이크 On/Of |
stopMotion() | 로봇 모션 중지 |
executeMoveCommand(const std::string & cmdName) | Conty를 통해 티칭된 cmdName 이름을 가진 Move Command 실행 |
moveJointHome() | 홈 포지션으로 이동 |
moveJointZero() | 제로 포지션으로 이동 |
moveJointTo(const double * const qvec) moveJointTo(std::initializer_list |
모든 관절 각도를 qvec의 값으로 이동 |
moveJointBy(const double * const qvec) moveJointBy(std::initializer_list |
모든 관절 각도를 qvec의 값 만큼 상대적으로 이동 |
moveTaskTo(const double * const pvec) moveTaskTo(std::initializer_list |
로봇 엔드 이펙터를 pvec의 6 자유도 위치로 이동 |
moveTaskBy(const double * const pvec) moveTaskBy(std::initializer_list |
로봇 엔드 이펙터를 pvec 의 6 자유도 값 만큼 상대적으로 이동 |
startCurrProgram() | 현재 로드된 로봇 프로그램 실행 |
pauseProgram() | 현재 현재 실행중인 프로그램 일시정지 |
resumeProgram() | 현재 일시정지된 프로그램 재개 |
stopProgram() | 현재 프로그램 중지 |
startRegisteredDefaultProgram() | 현재 등록된 기본 콘티 프로그램 실행 |
registerDefaultProgram(int idx) | idx 1-10번 기본 프로그램 등록 |
getRegisteredDefaultProgram(int &ret) | 현재 등록된 기본 프로그램 번호 요청 |
isRobotRunning(bool& ret) | 로봇 소프트웨어의 동작 여부를 확인 |
isRobotReady(bool& ret) | 로봇이 동작 가능한 상태인 지 확인 |
isEmergencyStopped(bool& ret) | 로봇이 비상 정지 상태인 지 확인 |
isCollided(bool& ret) | 로봇이 충돌 감지로 인해 정지되어 있는 지 확인 |
isErrorState(bool& ret) | 로봇이 에러 상태인 지 확인 |
isMoveFinished(bool& ret) | 로봇의 동작이 멈춘 상태인 지 확인 |
isBusy(bool& ret) | 로봇이 움직이는 도중인 지 확인 |
isHome(bool& ret) | 로봇이 홈 포지션에 있는 지를 확인 |
isZero(bool& ret) | 로봇이 제로 포지션에 있는 지를 확인 |
isInResetting(bool& ret) | 로봇이 리셋 도중인 지 확인 |
isDirectTeachingMode(bool& ret) | 로봇이 직접교시 모드인 지 확인 |
isTeachingMode(bool& ret) | 로봇이 교시 모드인 지 확인 (직접 교시, 조그) |
isProgramRunning(bool& ret) | 로봇이 동작 프로그램을 수행중인 지 확인 |
isProgramPaused(bool& ret) | 로봇의 동작 프로그램이 일시정지 되었는 지 확인 |
isContyConnected(bool& ret) | 로봇에 Conty 가 연결되었는 지 확인 |
changeToDirectTeachingMode() | 로봇 직접교시 모드 진입 |
finishDirectTeachingMode() | 로봇 직접교시 모드 종료 |
moveC(const double * const pvec) moveC(std::initializer_list |
via_point 와 end_point 를 이용하여 cirle 이동 |
setmoveCAngle(const double * const pvec)() setmoveCAngle(std::initializer_list |
moveC 이동시 이동할 각도 설정 |
setmoveCVel(const double * const pvec) setmoveCVel(std::initializer_list |
moveC 이동시 이동할 속도 설정 |
setmoveCAcc(const double * const pvec) setmoveCAcc(std::initializer_list |
moveC 이동시 이동할 가속도 설정 |
startTele(int mode) | mode 에 따라 TeleOperation 실행 |
stopTele() | TeleOperation 정지 |
TelemoveJ(const double * const pvec) TelemoveJ(std::initializer_list |
모든 관절 각도를 qvec의 값으로 이동 (동작하고 있는 TeleOP Mode 에 따라 절대, 상대 움직임) |
TelemoveL(const double * const pvec); TelemoveL(std::initializer_list |
로봇 엔드 이펙터를 pvec의 6 자유도 위치로 이동 (동작하고 있는 TeleOP Mode 에 따라 절대, 상대 움직임) |
setDefaultTCP(const double * const tcpVec) setDefaultTCP(std::initializer_list |
기본 TCP값을 tcpVec 로 설정 |
resetDefaultTCP() | 기본 TCP값 리셋 |
setTCPCompensation(const double * const tcpVec) setTCPCompensation(std::initializer_list |
TCP 보정값을 tcpVec 로 설정 |
resetTCPCompensation() | TCP 보정값 리셋 |
setReferenceFrame(const double * const refFrameVec) setReferenceFrame(std::initializer_list |
Reference 프레임 값을 refFrameVec 으로 설정 |
resetReferenceFrame() | Reference 프레임 값 리셋 |
setCollisionDetectionLevel(int level) | 충돌감지 민감도 레벨 설정 (1-5) |
setJointBoundaryLevel(int level) | JointMove 기본 속도/가속도 한계 레벨 설정 (1-9) |
setTaskBoundaryLevel(int level) | TaskMove 기본 속도/가속도 한계 레벨 설정 (1-9) |
setJointBlendingRadius(double radius) | JointMove 블랜딩 반경을 radius 값으로 설정 |
setTaskBlendingRadius(double radius) | TaskMove 블랜딩 반경 radius 값으로 설정 |
setJointWaypointTime(double time) | JointMove의 웨이포인트간 이동시간을 time 으로 설정 |
setTaskWaypointTime(double time) | TaskMove의 웨이포인트간 이동시간을 time 으로 설정 |
setTaskBaseMode(int mode) | TaskMove 제어 기준 축 설정 (0 = Reference frame, 1 = TCP frame) |
getDefaultTCP(double * const ret) | 기본 TCP값 요청 |
getTCPCompensation(double * const ret) | TCP 보정값 요청 |
getReferenceFrame(double * const ret) | Reference Frame 값 요청 |
getCollisionDetectionLevel(int &ret) | 충돌감지 민감도 레벨 값 요청 |
getJointBoundaryLevel(int &ret) | JointMove 기본 속도/가속도 한계 레벨값 요청 |
getTaskBoundaryLevel(int &ret) | TaskMove 기본 속도/가속도 한계 레벨값 요청 |
getJointBlendingRadius(double &ret) | JointMove 기본 블렌딩 반경값 요청 |
getTaskBlendingRadius(double &ret) | TaskMove 기본 블렌딩 반경값 요청 |
getJointWaypointTime(double &ret) | JointMove의 웨이포인트 간 이동시간 요청 |
getTaskWaypointTime(double &ret) | TaskMvoe의 웨이포인트 간 이동시간 요청 |
getTaskBaseMode(int &ret) | TaskMove 제어 기준 축 요청 |
getRobotRunningTime(double &ret) | 로봇 초기화 이후 총 실행시간 요청 |
getControlMode(int &ret) | 현재 로봇의 제어 모드 요청 |
getJointServoState(char * const ret) getJointServoState(char * const retServo, char * const retBrake) getJointServoState(bool * const retServo, bool * const retBrake) |
각 관절 축의 Servo, Brake 상태 요청 |
getJointPosition(double * const ret) | 현재 로봇의 Joint 각도 위치 요청 |
getJointVelocity(double * const ret) | 현재 로봇의 Joint 각속도 요청 |
getTaskPosition(double * const ret) | 현재 로봇의 Task 위치 요청 |
getTaskVelocity(double * const ret) | 현재 로봇의 Task 속도 요청 |
getTorque(double * const ret) | 현재 로봇의 토크 요청 |
getLastEmergencyInfo(int & retCode, int * const retIntArgs, double * const retDoubleArgs) | 로봇의 가장 최근 Emergency 상태 정보 요청 |
getSmartDigitalInput(int idx, char & ret) | idx 번 DI 채널의 값을 참조 변수인 ret 에 저장 |
getSmartDigitalInputs(char * const & ret) | 모든 DI 값을 한번에 획득. 각 채널의 값들은 참조 변수 ret 의 각 bit에 나뉘어 저장 |
setSmartDigitalOutput(int idx, char val) | idx 번 DO 채널에 val 의 값을 할당 |
setSmartDigitalOutputs(const char * const val) | 모든 DO 채널에 값을 할당. 각 채널의 값들은 val의 각 bit 값으로 할당 |
getSmartDigitalOutput(int idx, char & ret) | idx 번 DO 채널의 값을 참조 변수인 ret 에 저장 |
getSmartDigitalOutputs(char * const & ret) | 모든 DO 값을 한번에 획득. 각 채널의 값들은 참조 변수 ret 의 각 bit에 나뉘어 저장 |
getSmartAnalogInput(int idx, int & ret) | idx 번 AI 채널의 값을 획득. 결과는 참조변수인 ret에 저장 (범위 0~10000) |
setSmartAnalogOutput(int idx, int val) | idx 번 AO 채널에 val 값을 할당 (범위 0-10000) |
getSmartAnalogOutput(int idx, int & ret) | idx 번 AO 채널의 값을 참조 변수인 ret 에 저장. (범위 0-10000) |
setEndtoolDigitalOutput(int endtoolType, char val) | 입력한 endtoolType의 DO에 val 값을 할당 (endtoolType 값: 0 = NPN, 1 = PNP, 2 = Not use, 3 = eModi) |
getEndtoolDigitalOutput(int endtoolType, char & ret) | 입력한 endtoolType의 DO 값을 획득. 결과는 참조변수인 ret에 저장 (endtoolType 값: 0 = NPN, 1 = PNP, 2 = Not use, 3 = eModi) |
getRobotCanFTSensorRaw(int * const ret) | 로봇 앤드툴 CAN포트에 연결된 FT 센서의 raw 데이터값 수신 |
getRobotCanFTSensorTransformed(double * const ret) | 로봇 앤드툴 CAN포트에 연결된 FT 센서의 변환된 데이터값 수신 |
getCBCanFTSensorRaw(int * const ret) | 컨트롤박스의 CAN포트에 연결된 FT 센서의 raw 데이터값 수신 |
getCBCanFTSensorTransformed(double * const ret) | 컨트롤박스의 CAN포트에 연결된 FT 센서의 변환된 데이터값 수신 |
단위
- 6 자유도 위치 는 3차원 위치를 나타내는 3 개의 double 값과(x, y, z), 3차원 회전을 나타내는 3개의 double 각도 값으로(θx, θy, θz) 구성, 회전은 z-y-x의 순서로 적용.
- 위치와 각도의 단위는 각각 미터 (m), 도 (°).
- 모든 관절 값은 ° 단위로 표시.
간단한 모션과 DIO 예제
이 장에서는 간단한 로봇 동작과 DIO 제어를 포함한 예제를 소개합니다. 명확한 예시를 위해, 로봇은 Indy7, IP 주소는 192.168.0.100 로 가정합니다.
Warning
코드를 실행할 경우 로봇이 움직입니다. 로봇 주변의 공간을 비워 주세요!
#if defined (LINUX)
#include <unistd.h>
#elif defined (WINDOWS)
#pragma comment(lib,"ws2_32") //Must Link Winsock Library "ws2_32.dll"
#endif
#include <stdio.h>
#include <iostream>
#include "IndyDCPConnector.h"
using namespace std;
using namespace NRMKIndy::Service::DCP;
IndyDCPConnector connector("192.168.0.100", ROBOT_INDY7); // set the robot ip
void WaitFinish(IndyDCPConnector& connector) {
// Wait for motion finishing
bool fin = false;
do {
#if defined (LINUX)
sleep(0.5);
#elif defined(WINDOWS)
Sleep(500);
#endif
connector.isMoveFinished(fin); // check if motion finished
} while (!fin);
}
int main(int argc, char* argv[])
{
#if defined(WINDOWS)
initWinSock();
#endif
cout << "Connecting to the robot" << endl;
connector.connect();
bool ready;
connector.isRobotReady(ready);
if (ready) {
cout << "Robot is ready" << endl;
cout << "Go to zero position" << endl;
connector.moveJointZero();
WaitFinish(connector);
cout << "Go to home position" << endl;
connector.moveJointHome();
WaitFinish(connector);
double q[6];
cout << "Current joint values: " << endl;
connector.getJointPosition(q);
for(int i = 0;i<6;i++){ cout << q[i] << ","; }
cout << endl;
cout << "Rotate last joint by 10 degrees" << endl;
connector.moveJointBy({ 0,0,0,0,0,10 });
WaitFinish(connector);
cout << "Move joints to the saved values" << endl;
connector.moveJointTo(q);
WaitFinish(connector);
cout << "Move along waypoints" << endl;
connector.moveJointWaypointSet({
0, 0, 0, 0, 0, 0,
0, -15, -90, 0, -75, 0,
0, 0, 0, 0, 0, 0,
0, 15, 90, 0, 75, 0
});
WaitFinish(connector);
cout << "Current end-effector position:" << endl;
double p[6];
connector.getTaskPosition(p);
for (int i = 0; i < 6; i++) { cout << p[i] << ","; }
cout << endl;
cout << "Move end-effector upward by 5 cm" << endl;
connector.moveTaskBy({ 0,0,0.05,0,0,0 });
WaitFinish(connector);
cout << "Move end-effector to saved position" << endl;
connector.moveTaskTo(p);
WaitFinish(connector);
char ret;
cout << "Read DI 20: " << endl;
connector.getSmartDigitalInput(20, ret);
cout << ret << endl;
cout << "Write DO 4 as HIGH";
connector.setSmartDigitalOutput(4, 1);
cout << "Disconnecting robot" << endl;
connector.disconnect();
}
#if defined(WINDOWS)
cleanupWinSock(); // cleanup socket
#endif
}