Skip to content

C++ IndyDCP client

C++ IndyDCP client is a C++ class for users to interface with Indy based on IndyDCP Protocol. Users can use every function by including single header file, IndyDCPConnector.h.

Installation

Please download the source file and project file of C++ IndyDCP client in the same version as Indy SW in Download Page.

C++ IndyDCP client is tested and verified in both Windows and Linux. If you want to use IndyDCP client in Windows environment, you can open Visual Studio project in below path.

  • /IndyDCPClientWindows/IndyDCPClientWindows.sln

Notes

1
2
If you encounter an error related to precompiled header in the Visual Studio, try disabling precompiled header usage.
- In the project property menu, naviate to "Configuration Properties > C/C++ > Precompiled Headers" section, then change the "Precompiled Header" setting to "Not Using Precompiled Headers".

Initializing and terminating socket

Before using C++ IndyDCP client, the socket library should be Initialized. Socket initialization and termination is done in different ways in Windows and Linux.

  • Windows
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Link Winsock Library "ws2_32.dll"
#pragma comment(lib,"ws2_32")

// Initializaing WinSock
initWinSock();

///////////////////////
// Do task with Indy //
///////////////////////

// Terminating WinSock
cleanupWinSock();
  • Linux
1
2
3
4
5
6
7
#include <unistd.h>

///////////////////////
// Do task with Indy //
///////////////////////

// No termination required.

Connecting to and disconnecting from your Indy

All communication with Indy can be done using IndyDCPConnector class, defined in IndyDCPConnector.h. To initialize IndyDCPConnector, the IP address and name of the robot is required. All available robot names are defined in the namespace, NRMKIndy::Service::DCP.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include "IndyDCPConnector.h"
using namespace NRMKIndy::Service::DCP;

//Initialize Indy
IndyDCPConnector connector("put.robot.ip.here", ROBOT_INDY7);

//connect to Indy
connector.connect()

///////////////////////
// Do task with Indy //
///////////////////////

//disconnect from Indy
connector.disconnect()

C++ IndyDCP Command List

The following shows examples of C++ IndyDCP commands. Commands not included in the example can be found in the whole command list. For more information about how to use it, please refer to the downloaded C ++ IndyDCP code.

Note

1
The return value of every method in **IndyDCPConnector** is an integer, which represents an error code. The requested value are returned through references (call-by-reference).

Function Description
stopEmergency() Emergency stop
resetRobot() Reset robot
setServoOnOff(const char * const servoVec)
setServoOnOff(const bool * const servoVec)
setServoOnOff(std::initializer_list servoVec)

Servo on/off depending on servoVec
setBrakeOnOff(const char * const brakeVec)
setBrakeOnOff(const bool * const brakeVec)
setBrakeOnOff(std::initializer_list brakeVec)

Brake on/off depending on brakeVec
stopMotion() Stop robot motion
executeMoveCommand(const std::string & cmdName) Execute Move Command, which has name cmdName, teached by Conty
moveJointHome() Move Indy to the home position
moveJointZero() Move Indy to the zero position
moveJointTo(const double * const qvec)
moveJointTo(std::initializer_list qvec)
Move every joints of Indy to the values in qvec
moveJointBy(const double * const qvec)
moveJointBy(std::initializer_list qvec)
Move every joints of Indy by the values in qvec, relatively from current angles
moveTaskTo(const double * const pvec)
moveTaskTo(std::initializer_list pvec)
Move end-effector of Indy to the 6 DoF position described by pvec
moveTaskBy(const double * const pvec)
moveTaskBy(std::initializer_list pvec)
Move end-effector of Indy by the 6 DoF transformation described by pvec, relatively from current position
startCurrProgram() Execute the loaded robot program
pauseProgram() Pause robot program in currently running state
resumeProgram() Resume the paused robot program
stopProgram() Stop the robot program
startRegisteredDefaultProgram() Execute the registered default robot program
registerDefaultProgram(int idx) Register default robot program by an index 1 to 10
getRegisteredDefaultProgram(int &ret) Request the registered default robot program's index
isRobotRunning(bool& ret) Check if robot software is runnig
isRobotReady(bool& ret) Check if robot is ready to move
isEmergencyStopped(bool& ret) Check if robot is stopped by emergency
isCollided(bool& ret) Check if robot is stopped by collision
isErrorState(bool& ret) Check if robot is in error state
isBusy(bool& ret) Check if robot is in motion
isMoveFinished(bool& ret) Check if robot is not moving
isHome(bool& ret) Check if robot is at the home position
isZero(bool& ret) Check if robot is at the zero position
isInResetting(bool& ret) Check if robot is restting
isDirectTeachingMode(bool& ret) Check if robot is direct teaching mode
isTeachingMode(bool& ret) Check if robot is teaching mode (direct teaching or jogging)
isProgramRunning(bool& ret) Check if robot is runnig a program
isProgramPaused(bool& ret) Check if robot program is paused
isContyConnected(bool& ret) Check if Conty is connected to the robot
changeToDirectTeachingMode() Start the direct teaching mode
finishDirectTeachingMode() Terminate the direct teaching mode
addJointWaypointSet(const double * const qvec)
addJointWaypointSet(std::initializer_list qvec)
Add a joint waypoint
removeJointWaypointSet() Remove the last joint waypoint
clearJointWaypointSet() Clear all joint waypoints
executeJointWaypointSet() Start moving along the saved joint waypoints
addTaskWaypointSet(const double * const pvec)
addTaskWaypointSet(std::initializer_list pvec)
Add an end-effector waypoint
removeTaskWaypointSet() Remove the last end-effector waypoint
clearTaskWaypointSet() Clear all end-effector waypoints
executeTaskWaypointSet() Start moving along the saved end-effector waypoints
setDefaultTCP(const double * const tcpVec)
setDefaultTCP(std::initializer_list tcpVec)
Set default TCP value as tcpVec
resetDefaultTCP() Reset the default TCP value
setTCPCompensation(const double * const tcpVec)
setTCPCompensation(std::initializer_list tcpVec)
Set TCP compensation value as tcpVec
resetTCPCompensation() Reset the TCP compensation value
setReferenceFrame(const double * const refFrameVec)
setReferenceFrame(std::initializer_list refFrameVec)
Set the Reference frame value as refFrameVec
resetReferenceFrame() Reset the Reference frame value
setJointBoundaryLevel(int level) Set the limit level of velocity/acceleration of JointMove (1-9)
setTaskBoundaryLevel(int level) Set the limit level of velocity/acceleration of TaskMove (1-9)
setJointBlendingRadius(double radius) Set blend radius of JointMove as radius
setTaskBlendingRadius(double radius) Set blend radius of TaskMove as radius
setJointWaypointTime(double time) Set travel time between waypoints of JointMove as time
setTaskWaypointTime(double time) Set travel time between waypoints of TaskMove as time
getDefaultTCP(double * const ret) Request for default TCP value
getTCPCompensation(double * const ret) Request for TCP compensation value
getReferenceFrame(double * const ret) Request for Reference Frame value
getCollisionDetectionLevel(int &ret) Request for collision detection sensitivity level value
getJointBoundaryLevel(int &ret) Request for the limit level of velocity/acceleration of JointMove
getTaskBoundaryLevel(int &ret) Request for the limit level of velocity/acceleration of TaskMove
getJointBlendingRadius(double &ret) Request for the blend radius of JointMove
getTaskBlendingRadius(double &ret) Request for the blend radius of TaskMove
getJointWaypointTime(double &ret) Request for the travel time between waypoints of JointMove
getTaskWaypointTime(double &ret) Request for the travel time between waypoints of TaskMove
getTaskBaseMode(int &ret) Request for based frame mode of TaskMove
getRobotRunningTime(double &ret) Request for total runtime after robot initialization
getControlMode(int &ret) Request for current robot control mode
getJointServoState(char * const ret)
getJointServoState(char * const retServo, char * const retBrake)
getJointServoState(bool * const retServo, bool * const retBrake)

Request for status of servo and brake
getJointPosition(double * const ret) Request for current joint angles
getJointVelocity(double * const ret) Request for current joint angular velocity
getTaskPosition(double * const ret) Request for current task position
getTaskVelocity(double * const ret) Request for current task velocity
getTorque(double * const ret) Request for current robot torques
getLastEmergencyInfo(int & retCode, int * const retIntArgs, double * const retDoubleArgs) Request the latest emergency status information of the robot
getSmartDigitalInput(int idx, char & ret) Request value of idx-th DI channel. The result is stored in the reference variable ret
getSmartDigitalInputs(char * const & ret) Request all DIs' values. The each DI value is stored in each bit of ret
setSmartDigitalOutput(int idx, char val) Assign idx-th DO channel value to val value
setSmartDigitalOutputs(const char * const val) Assign values to all DO channels. The value of each channel is assigned to each bit value of val
getSmartAnalogInput(int idx, int & ret) Request idx-th AI channel values. The result is stored in ret (range 0-10000)
setSmartAnalogOutput(int idx, int val) Assign idx-th AO channel value to val value (range 0-10000)
getRobotCanFTSensorRaw(int * const ret) Request for the raw data of FT sensor connected to robot end-tool CAN port
getRobotCanFTSensorTransformed(double * const ret) Request for transformed data value of FT sensor connected to robot end-tool CAN port
getCBCanFTSensorRaw(int * const ret) Request for raw data value of FT sensor connected to CAN port of control box
getCBCanFTSensorTransformed(double * const ret) Request for transformed data value of FT sensor connected to CAN port of control box
readDirectVariable(int type, int addr, void * ret) Read single value of direct variable with type type and addr address
readDirectVariables(int type, int addr, int len, void * ret) Read success value of len length of direct variable with type type and addr address
writeDirectVariable(int type, int addr, void * ptrVal) Write a single ptrVal value to a direct variable with type type and addr address
writeDirectVariables(int type, int addr, int len, void * ptrVal) Write consecutive ptrVal values len length to a direct variable with type type and addr address

Units

  • 6 DoF position is composed of 3 doubles for tranlations (x, y, z) and 3 doubles for orientation (θx, θy, θz). The rotation is applied in the order of z-y-x. The translations are in meters and orientations are in degrees.
  • All joint angles are represented in degrees.

Simple motion & DIO example

In this section, an example code for simple robot motion and DIO control will be introduced. In this example, we assume the robot is Indy7 and the robot's IP address is 192.168.0.100.

Warning

1
If you run the code, the robot will move! Clear the space around the robot.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
#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
}