Introduction
1. SDK introduction
The NRC_HOST SDK provides a set of rapidly integratable network interfaces, allowing developers to focus on higher-level development without concerning themselves with the underlying protocol details. This enhances development efficiency and supports platforms such as Linux and Windows, as well as various advanced programming languages, making it convenient for developers to choose the most suitable platform for their development needs.
2. Compatibility
Category | Compatibility range |
---|---|
System | Supports x86, x86_64, ARM, ARM64 architectures |
Development environment | Use the corresponding IDE for your preferred development language, such as Qtcreator, VS Studio, VSCode, etc. recommended for Qt, Python, C# |
3. SDK integration package directory structure
├── Demo: DEMO for using NRC_HOST, which includes the integrated SDK. You can refer to the DEMO for integrating the SDK. Before integration, please test the DEMO to understand the calling principles. ├── SDK: NRC_HOST SDK │ └── libnrc_host.so └── NRC_HOST document: SDK Integration Document.pdf
4. API call flowchart
![Quick start flowchart](Quick start flowchart.png)
5. SDK project configuration
The following instructions will explain how to configure a QT project on the Linux platform. If your project is in Python or C#, please refer to the Python Quick Integration or C# Quick Integration guides.
Create a new QT project, then create a 'lib' directory in the project directory. Place the libnrc_host.so library in the 'lib' directory, and the interface.h file in the project's root directory.
![Project example](Project example.png)
Right-click on the project name, choose "Add Existing File", select the interface.h file, and after adding it, right-click on the project name again. Choose "Add Library" to include the libnrc_host.so library in the project. The modified .pro file should appear as follows. ![pro file](pro file.png)
You'll notice that the .pro file now contains the following additional lines:
interface.h
LIBS += -L$$PWD/lib -lnrc_host
Alternatively, if you are familiar with .pro projects, you can directly add the above two lines in the .pro file. This will achieve the same effect as using the right-click method.
6. Quick integration
6.1 Connecting to the controller
int connect_robot(const char* ip,const char* port,const char* robotName);
Robot connection parameter description:
Parameter | Type | Description | Required |
---|---|---|---|
ip | const char* | IP address of the controller (default: 192.168.1.13) | Yes |
port | const char* | Service port of the controller (6001) | Yes |
robotName | const char* | Custom controller name | Yes |
Robot connection return value: 0: connection successful, non-0: connection failed, please refer to the error code chapter to check the reason based on the specific return value.
We open the mainwindow.cpp file and add the following code in its constructor to connect our controller.
const char robot_ip[] = "192.168.1.15";
const char robot_port[] = "6001";
const char robot_name[] = "myRobotNo1";
if(connect_robot(robot_ip,robot_port,robot_name) == 0)
{
std::cout << "Connection successful" << std::endl;
} else {
std::cout << "Connection failed" << std::endl;
}
Note that the connect_robot function is blocking, which means that the program will block at this line until connect_robot returns the connection result.
6.2 Basic controller status
6.2.1 Connection status
int get_connection_status(const char* robotName);
Robot connection parameter description:
Parameter | Type | Description | Required |
---|---|---|---|
robotName | const char* | Custom controller name | Yes |
Robot connection return value: 1: Connected, 0: Not connected, -2: robotName does not exist.
6.2.2 Servo state
The controller defines four servo states: stop state, ready state, alarm state, and running state. Note that any instructions related to movements can only be used in the running state.
Functions involved in this subsection:
- Get servo state
int get_servo_state(const char* robotName);
Function parameter description: |Parameter|Type|Description|Required| |:--:|:--:|:--|:--:| |robotName|const char*|Custom controller name|Yes|
Function return value: 0: Stop state; 1: Ready state; 2: Alarm state; 3: Running state; -1: Timeout waiting for status retrieval; -2: Target controller does not exist.
- Set servo state
int set_servo_state(int state,const char* robotName);
Function parameter description: |Parameter|Type|Description|Required| |:--:|:--:|:--|:--:| |state|int|0: Set the servo to stopped state; 1: Set the servo to ready state|Yes| |robotName|const char*|Custom controller name|Yes|
Function return value: Return the result of get_servo_state().
- Set robot to power on
int set_servo_poweron(const char* robotName);
Function parameter description: |Parameter|Type|Description|Required| |:--:|:--:|:--|:--:| |robotName|const char*|Custom controller name|Yes|
Function return value: Return the result of get_servo_state().
- Set robot to power off
int set_servo_poweroff(const char* robotName);
Function parameter description: |Parameter|Type|Description|Required| |:--:|:--:|:--|:--:| |robotName|const char*|Custom controller name|Yes|
Function return value: Return the result of get_servo_state().
- Clear servo alarm
int clear_error(const char* robotName);
Function parameter description: |Parameter|Type|Description|Required| |:--:|:--:|:--|:--:| |robotName|const char*|Custom controller name|Yes|
Function return value: 0: Cleared successfully; -1: Servo not in alarm state; -2: Target controller does not exist.
The following code shows how to power on a robot in teach mode
//robot_name is the parameter used when connecting to the robot
clear_error(robot_name);
int state = get_servo_state(robot_name);
if(state == 0)
{
std::cout << "The servo is in stop state, it will first perform the ready operation before powering on." << std::endl;
set_servo_state(1,robot_name);
set_servo_poweron(robot_name);
} else if(state == 1)
{
std::cout << "The servo is in ready state and will perform the power-on operation." << std::endl;
set_servo_poweron(robot_name);
}else if(state == 2) {
std::cout << "The servo is in alarm state, please call the error clearing function clear_error." << std::endl;
} else if(state == 3) {
std::cout << "The servo is currently in running state." << std::endl;
}
6.2.3 Simple motion
In the previous section, we showed how to power on the robot. Next, we will explain how to make the robot move.
Functions involved in this section:
- Joint interpolation
int robot_movej(double *pos,int vel,int coord,int acc, int dec,const char* robotName);
Parameter description: |Parameter|Type|Description|Required| |:--:|:--:|:--|:--:| |pos|double|Position array, length 7|Yes| |vel|int|Joint interpolation speed [1,100], in %|Yes| |coord|int|Coordinate system, 0: joint, 1: Cartesian, 2: tool, 3: user|Yes| |acc|int|Acceleration [1,100]|Yes| |dec|int|Deceleration [1,100]|Yes| |robotName|const char|Custom controller name|Yes|
Function return value: 0: Successful call; -2: Target controller does not exist.
- Linear interpolation
int robot_movel(double *pos,int vel,int coord,int acc, int dec,const char* robotName);
Parameter description: |Parameter|Type|Description|Required| |:--:|:--:|:--|:--:| |pos|double|Position array, length 7|Yes| |vel|int|Linear interpolation speed [1, maximum speed set in Cartesian parameters, in mm/s]|Yes| |coord|int|Coordinate system, 0: joint, 1: Cartesian, 2: tool, 3: user|Yes| |acc|int|Acceleration [1,100]|Yes| |dec|int|Deceleration [1,100]|Yes| |robotName|const char|Custom controller name|Yes|
Function return value: 0: Successful call; -2: Target controller does not exist.
- Get robot running state
int get_robot_running_state(const char* robotName);
Parameter description: |Parameter|Type|Description|Required| |:--:|:--:|:--|:--:| |robotName|const char*|Custom controller name|Yes|
Function return value: 0: Stop; 1: Pause; 2: Running; -1: Timeout waiting for controller reply; -2: Target controller does not exist.
- Get current robot position
int get_current_position(double* pos, int coord,const char* robotName);
Parameter description: |Parameter|Type|Description|Required| |:--:|:--:|:--|:--:| |pos|double|Return value position array, length 7|Yes| |coord|int|The coordinate system of the coordinates to be queried|Yes| |robotName|const char|Custom controller name|Yes|
Function return value: -1: Timeout waiting for controller reply; -2: Target controller does not exist.
The following code snippet shows how to make the robot move in teach mode after powering on in section 6.2.2
//robot_name is the parameter used when connecting to the robot
double pos[7] = {0};
//Move the robot to position 0
robot_movej(pos, 50 /*vel*/, 0 /*coord*/, 80 /*acc*/, 80/*dec*/, robot_name);
QThread::msleep(100);
while(get_robot_running_state(robot_name) == 2)
{
QThread::msleep(100);
}
std::cout << "Current joint position:" << std::endl;
get_current_position(pos,0,robot_name);
for(int i = 0;i < 7;i++)
{
std::cout << i+1 << "Axis angle:" <<pos[i] << "; " ;
}
std::cout << std::endl;
//At the current joint angles, decrease the angle by 50 degrees for axis 1
pos[0] -= 50;
robot_movej(pos, 50 /*vel*/, 0 /*coord*/, 80 /*acc*/, 80/*dec*/, robot_name);
//Wait for robot_movej to finish
QThread::msleep(100);
while(get_robot_running_state(robot_name) == 2)
{
QThread::msleep(100);
}
std::cout << "Joint position after movement:" << std::endl;
get_current_position(pos,0,robot_name);
for(int i = 0;i < 7;i++)
{
std::cout << i+1 << "Axis angle:" <<pos[i] << "; ";
}
std::cout << std::endl;
Connection successful
Servo is currently in running state.
Current joint position:
Axis 1: 98.1972; Axis 2: 0; Axis 3: 0; Axis 4: 0; Axis 5: 0; Axis 6: 0; Axis 7: 0;
Joint position after movement:
Axis 1: 48.197; Axis 2: 0; Axis 3: 0; Axis 4: 0; Axis 5: 0; Axis 6: 0; Axis 7: 0;
If we want to perform joint interpolation in Cartesian coordinates, what should we do?
We just need to change the coordinates in variable "pos" to Cartesian coordinates It is still the same code, but this time we are getting Cartesian coordinates when obtaining the position
//robot_name is the parameter when connecting to the robot
double pos[7] = {0};
//Move the robot to position 0
robot_movej(pos, 50 /*vel*/, 0 /*coord*/, 80 /*acc*/, 80/*dec*/, robot_name);
QThread::msleep(100);
while(get_robot_running_state(robot_name) == 2)
{
QThread::msleep(100);
}
std::cout << "Current Cartesian position:" << std::endl;
get_current_position(pos,1,robot_name);
std::cout << "[X]:" << pos[0] << "; [Y]:" << pos[1] << "; [Z]:" <<pos[2] << "[A]:" << pos[3] << "; [B]:" << pos[4] << "; [C]:" <<pos[5] << std::endl;
//Decrease by 20 in the X direction from the current position
pos[0] -= 20;
robot_movej(pos, 50 /*vel*/, 1 /*coord*/, 80 /*acc*/, 80/*dec*/, robot_name);
QThread::msleep(100);
while(get_robot_running_state(robot_name) == 2)
{
QThread::msleep(100);
}
std::cout << "Cartesian position after movement:" << std::endl;
get_current_position(pos,1,robot_name);
std::cout << "[X]:" << pos[0] << "; [Y]:" << pos[1] << "; [Z]:" <<pos[2] << "[A]:" << pos[3] << "; [B]:" << pos[4] << "; [C]:" <<pos[5] << std::endl;
Connection successful
Servo is currently in running state.
Current Cartesian position:
[X]:127.285; [Y]:-151.678; [Z]:198; [A]:3.14156; [B]:3.08149e-05; [C]:0.872667
Cartesian position after movement:
[X]:107.287; [Y]:-151.678; [Z]:198.002; [A]:3.14153; [B]:4.15234e-05; [C]:0.872667
The "movej" function above can move the robot to the target position, but the trajectory in space is not a straight line. How can we perform a linear motion in space? We can use the "robot_movel" function.
//robot_name is the parameter when connecting to the robot
double pos[7] = {0};
//Move the robot to position 0
robot_movej(pos, 50 /*vel*/, 0 /*coord*/, 80 /*acc*/, 80/*dec*/, robot_name);
QThread::msleep(100);
while(get_robot_running_state(robot_name) == 2)
{
QThread::msleep(100);
}
std::cout << "Current Cartesian position:" << std::endl;
get_current_position(pos,1,robot_name);
std::cout << "[X]:" << pos[0] << "; [Y]:" << pos[1] << "; [Z]:" <<pos[2]
<< "[A]:" << pos[3] << "; [B]:" << pos[4] << "; [C]:" <<pos[5] << std::endl;
//Decrease by 20 in the X direction from the current position
pos[0] -= 20;
robot_movel(pos, 800 /*vel*/, 1 /*coord*/, 80 /*acc*/, 80/*dec*/, robot_name);
QThread::msleep(100);
while(get_robot_running_state(robot_name) == 2)
{
QThread::msleep(100);
}
std::cout << "Cartesian position after movement:" << std::endl;
get_current_position(pos,1,robot_name);
std::cout << "[X]:" << pos[0] << "; [Y]:" << pos[1] << "; [Z]:" <<pos[2]
<< "[A]:" << pos[3] << "; [B]:" << pos[4] << "; [C]:" <<pos[5] << std::endl;
For more interface introductions, please refer to the API page.