C++ IndyDCP3 Client
To use the IndyDCP3 client with C++, follow the steps below. This guide assumes that you have the appropriate development environment set up with C++17 or later.
Installation Requirements
- Requires CMake for project configuration and building.
- A C++ compiler that supports C++17 or later.
- IndyDCP3 library files and headers.
Installation Instructions
On Linux
1. Install gRPC
This gRPC installation guide for Linux is summarized from gRPC website. For more information, please visit grpc.io.
Choose a directory to hold locally installed packages. This page assumes that the environment variable MY_INSTALL_DIR holds this directory path. For example:
Ensure that the directory exists:Add the local bin folder to your path variable, for example:
Install CMake You need version 3.13 or later of cmake. Install it by following these instructions:
Check the version of cmake:On Linux, the system-wide CMake version might be outdated. To install a more recent version in your local installation directory, use:
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
Install other required tools Install the basic tools required to build gRPC:
Clone the grpc repo and its submodules:
git clone --recurse-submodules -b v1.59.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc
Build and Install gRPC and Protocol Buffers
gRPC applications often use Protocol Buffers for service definitions and data serialization, as in the example code that follows. To build and locally install gRPC and Protocol Buffers, run:
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
Important
Note
It is strongly recommended to install gRPC locally with a properly set CMAKE_INSTALL_PREFIX, as there is no simple way to uninstall gRPC after a global installation.
2. Download and Build example
Clone the Example Repository
Navigate to the C++ Folder
Create and Enter the Build Directory
Run CMake Configuration and Build the Example
If you need to rebuild the .proto files, set -DBUILD_PROTO=ON. The build_proto executable file will be generated. After running this file, the generated proto files will be located in the proto/cpp_generated folder.C++ (On Windows)
It is recommended to use Visual Studio Code for this setup.
1. Setup your environment
Install Visual Studio Code - Install following extensions: C/C++, C/C++ Extension Pack and CMake Tools.
Install vs_BuildTools - In BuildTools option, please choose Desktop Development with C++ and Visual Studio extension development.
2. Install GRPC
When you are all set, please open Developer Command Prompt and run the following commands:
Create build folder
Configure and build using 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 ../..
Build and install grpc
3. Download and Build example
Clone the Example Repository
Open Visual Studio Code and open neuromeka-package/cpp/ folder Config your build with settings.json in .vscode folder. If you need to rebuild the .proto files, set -DBUILD_PROTO=ON. The build_proto executable file will be generated.
Then, modify the CMakeList.txt. Change following lines to point to your grpc installation directory.
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")
Open Visual Studio Code Press Ctrl+Shift+P or go to View -> Command Palette to open the Command Palette, and choose the following commands: - CMake: Scan for kits: To scan for compilers on your computer. - CMake: Select a kit: To select a specific compiler (e.g., Visual Studio Build Tools 2022 Release - amd64).
When you are done, press the Build button at the bottom left.
Using IndyDCP3
To create a client object, include the IndyDCP3
class header from the IndyDCP3 library and initialize it with the robot's IP address.
#include "indydcp3.h"
int main() {
IndyDCP3 indy("192.168.xxx.xxx");
// Use the indy object to interact with the robot...
return 0;
}
192.168.xxx.xxx
: IP address of the robot controller.
Methods and Functions
Below is a list of protocol functions that can be called using the IndyDCP3 object. Please refer to the usage methods and input/output examples for each function.
Real-Time Data Acquisition Functions
You can retrieve the robot's current motion status, control data, state, servo motor state, error information, and program status.
Method | Description |
---|---|
get_robot_data() |
Robot status data |
get_control_state() |
Control state |
get_motion_data() |
Motion data |
get_servo_data() |
Servo data |
get_violation_data() |
Error data |
get_program_data() |
Robot program data |
get_robot_data()
Nrmk::IndyFramework::ControlData2 control_data;
bool is_success = indy.get_robot_data(control_data);
if (is_success) {
// Process 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
: Robot operating hoursrunning_mins
: Robot operating minutesrunning_secs
: Robot operating secondsop_state
: Robot state as defined in theOpState
classOpState
: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) {
// Access joint positions
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
: Current positions (deg), velocities (deg/s), and accelerations (deg/s²) of each jointqdes
,qdotdes
,qddotdes
: Target positions (deg), velocities (deg/s), and accelerations (deg/s²) of each jointp
,pdot
,pddot
: Current workspace pose positions (mm), velocities (mm/s), and accelerations (mm/s²)pdes
,pdotdes
,pddotdes
: Target workspace pose positions (mm), velocities (mm/s), and accelerations (mm/s²)tau
,tau_act
,tau_ext
: Current input torques, actual torques, and external torques (Nm) for each jointtau_jts
,tau_jts_raw1
,tau_jts_raw2
: joint torque sensor values.
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
: Status codes (CiA402) for each joint servotemperatures
: Temperatures for each joint servovoltages
: Voltages for each joint servocurrents
: Currents for each joint servoservo_actives
: Activation state of each joint servo (true/false)brake_actives
: Activation state of the brakes for each joint servo (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();
}
{
'violation_code': '262144',
'j_index': 4,
'i_args': [2],
'f_args': [0.0012204262],
'violation_str': 'EMG Button Activated'
}
j_index
: Index of the joint where the violation occurredi_args
: Integer information about the violationf_args
: Float information about the violationviolation_str
: Error messageviolation_code
: Error code
violation_code (Binary) | violation_str |
---|---|
0b00 | None |
0b01 << 0 | Joint [axisIdx/DOF] Position Error Over Limit (Current: X deg, Desired: Y, Limit: Z) |
0b01 << 1 | Joint [axisIdx/DOF] Position Close To Limit (Current: X deg, Allowed: A ~ B) |
0b01 << 2 | Joint [axisIdx/DOF] Velocity Close To Limit (Current: X deg/s, Allowed: A ~ B) |
0b01 << 6 | TCP Singular Closed |
0b01 << 7 | Joint [axisIdx/DOF] Position Exceeded Limit (Current: X, Allowed: A ~ B) |
0b01 << 8 | Joint [axisIdx/DOF] Velocity Exceeded Limit (Current: X, Allowed: A ~ B) |
0b01 << 9 | Joint [axisIdx/DOF] Torque Exceeded Limit (Current: X, Allowed: A ~ B) |
0b01 << 10 | TCP Speed Limit: X m/s |
0b01 << 11 | TCP Force Limit: X N |
0b01 << 12 | Power Over Limit (Current: X, Allowed: Y) |
0b01 << 13 | Standstill Failed |
0b01 << 14 | Loss of Conty Communication |
0b01 << 15 | Loss of IndyKey Communication |
0b01 << 16 | Safety Guard Input 1 |
0b01 << 17 | Safety Guard Input 2 |
0b01 << 18 | EMG Button Activated |
0b01 << 19 | Robot Specs Reading Failed |
0b01 << 20 | Connection Lost - Master: masterState, Detected Joints Num: numSlavesDetected / DOF+2 |
0b01 << 21 | Motor Status Error: joint [axisIdx/DOF], Code = errorCode |
0b01 << 22 | Motor Over Current: joint [axisIdx/DOF], Code errorCode |
0b01 << 23 | Motor Over Heated: joint [axisIdx/DOF], Temperature X celsius |
0b01 << 24 | Motor Error Bit: joint [axisIdx/DOF], Code = errorCode |
0b01 << 25 | Motor Low Battery: joint [axisIdx/DOF], Code = errorCode |
0b01 << 26 | Motor Firmware Error |
0b01 << 27 | Task Time Over Limit (Current: X us, Allowed: Y us) |
0b01 << 28 | Soft Reset Failed |
0b01 << 29 | Auto Servo-Off Activated |
0b01 << 30 | TeleOp Starting Point Too Far |
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
: Name of the currently running program fileprogram_state
: Program execution stateProgramState
:IDLE(0)
,RUNNING(1)
,PAUSING(2)
,STOPPING(3)
running_hours
: Program operating time (hours)running_mins
: Program operating time (minutes)running_secs
: Program operating time (seconds)program_alarm
: Alarm of Conty Flow controlprogram_annotation
: Annotation of Conty Flow control
I/O Device Related Functions
I/O Device functions are used to interact with various robot hardware components like digital and analog I/O, end-tool I/O, and sensors.
Method | Description |
---|---|
get_di(DigitalList &data) |
Retrieves IO board DI data |
get_do(DigitalList &data) |
Retrieves IO board DO data |
set_do(const DigitalList &data) |
Sets IO board DO data |
get_ai(AnalogList &data) |
Retrieves IO board AI data |
get_ao(AnalogList &data) |
Retrieves IO board AO data |
set_ao(const AnalogList &data) |
Sets IO board AO data |
get_endtool_di(EndtoolSignalList &data) |
Retrieves end-tool DI data |
get_endtool_do(EndtoolSignalList &data) |
Retrieves end-tool DO data |
set_endtool_do(const EndtoolSignalList &data) |
Sets end-tool DO data |
get_endtool_ai(AnalogList &data) |
Retrieves end-tool AI data |
get_endtool_ao(AnalogList &data) |
Retrieves end-tool AO data |
set_endtool_ao(const AnalogList &data) |
Sets end-tool AO data |
get_device_info(DeviceInfo &data) |
Retrieves device information |
get_ft_sensor_data(FTSensorData &data) |
Retrieves end-tool F/T sensor data |
get_di()
Example
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 << " Address: " << di_data.signals(i).address()
<< ", State: " << di_data.signals(i).state() << std::endl;
}
}
get_do()
, set_do()
Example
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()
Example
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 << " Address: " << ai_data.signals(i).address()
<< ", Voltage: " << ai_data.signals(i).voltage() << std::endl; //mV
}
}
address
0 and 1. The remaining channels are spare.
get_ao()
, set_ao()
Example
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()
Example
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()
Example
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()
Example
This can only be used with the RevE endtool board.
The RevE endtool board has two AI channels, which are assigned to address
0 and 1, respectively. The remaining channels are reserved.
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()
Example
This can only be used with the RevE endtool board.
The RevE endtool board has two AO channels, which are assigned to address
0 and 1, respectively. The remaining channels are reserved.
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;
}
Motion Command Functions
Motion command functions allow you to control the robot's movement, whether it's stopping, moving to specific positions, or executing complex motion paths.
Method | Description |
---|---|
stop_motion(StopCategory stop_category) |
Stops motion according to the specified stop category |
move_home() |
Moves the robot to the home position |
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) |
Moves the robot to a specified joint target position |
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) |
Moves the robot to a specified joint target position over a specified time |
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) |
Moves the robot to a specified linear target position |
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) |
Moves the robot to a specified linear target position over a specified time |
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) |
Moves the robot along a circular path |
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) |
Executes a circular motion in task space over a specified time |
move_gcode(const std::string& gcode_file, bool is_smooth_mode, float smooth_radius, float vel_ratio, float acc_ratio) |
Executes a motion defined in a G-code file |
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) |
Move the robot through a set of 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) |
Move the robot through a set of task waypoints |
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 the robot along a joint position-velocity-acceleration trajectory of full control frequency |
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) |
Move the robot along a workspace position-velocity-acceleration trajectory of full control frequency |
Warning
Be cautious when using motion commands, as the robot will move immediately if the command is successfully applied. While using the robot through the pendant allows movement only while the user is holding the touch button, using the API allows movement through program commands, so always ensure the area is clear of objects that could cause collisions. Especially, be mindful of safety if setting high speeds or accelerations, as the robot may move faster than expected.
stop_motion()
Example
Stops the robot's motion according to the specified stop category.
StopCategory stop_category = StopCategory::SMOOTH_BRAKE;
bool is_success = indy.stop_motion(stop_category);
if (is_success) {
std::cout << "Motion stopped successfully." << std::endl;
} else {
std::cerr << "Failed to stop motion." << std::endl;
}
move_home()
Example
Moves the robot to the predefined home position.
bool is_success = indy.move_home();
if (is_success) {
std::cout << "Robot moved to home position successfully." << std::endl;
} else {
std::cerr << "Failed to move robot to home position." << std::endl;
}
movej()
Example
Moves the robot to a specified joint target position.
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 command executed successfully." << std::endl;
} else {
std::cerr << "MoveJ command failed." << std::endl;
}
movel()
Example
Moves the robot to a specified linear target position in the workspace.
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 command executed successfully." << std::endl;
} else {
std::cerr << "MoveL command failed." << std::endl;
}
movec()
Example
Moves the robot along a circular path passing through two specified workspace positions.
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 << "Circular move executed successfully." << std::endl;
} else {
std::cerr << "Failed to execute circular move." << std::endl;
}
move_gcode()
Example
Executes a motion defined in a G-code file.
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 and move task waypoints
Joint Waypoints
Joint waypoints are specific positions for each of the robot's joints that the robot will move through sequentially.
add_joint_waypoint(const std::vector<float>& waypoint)
adds a joint waypoint to the list of waypoints. The waypoint is a vector representing the target positions for each joint of the robot.
waypoint
: a vector of floats, each representing a joint position in degrees.
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()
retrieves the current list of joint waypoints that have been added. This allows you to review or verify the waypoints before executing the movement.
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()
clears the current list of joint waypoints. This function is useful if you need to reset the waypoints and start adding new ones.
move_joint_waypoint(float move_time)
moves the robot through the sequence of joint waypoints that have been added. The robot will attempt to reach each waypoint sequentially.
move_time
: (optional) The time in seconds for the robot to move through the waypoints. If not provided, the robot will move normally.
Task Waypoints
Task waypoints refer to specific positions and orientations in space that the robot's endtool should move through.
add_task_waypoint(const std::array<float, 6>& waypoint)
adds a task waypoint to the list of waypoints. The waypoint is an array representing the target position and orientation in Cartesian space.
waypoint
: an array of six floats representing the x, y, z position and the roll, pitch, yaw orientation of the endtool.
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)
retrieves the current list of task waypoints that have been added. This allows you to review or verify the waypoints before executing the movement.
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()
clears the current list of task waypoints. This function is useful if you need to reset the waypoints and start adding new ones.
move_task_waypoint(float move_time)
moves the robot's endtool through the sequence of task waypoints that have been added. The robot will attempt to reach each waypoint sequentially.
move_time
: (optional) The time in seconds for the robot to move through the waypoints. If not provided, the robot will move normally.
Trajectory Motion
move_joint_traj
is a joint-space trajectory movement movement command.
Below, q_list
, qdot_list
, qddot_list
are list
values of joint position, velocity and acceleration in radians.
The time step between trajectory is the control period, which is 250us by default.
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
is a task-space trajectory movement movement command.
Below, p_list
, pdot_list
, pddot_list
are list
values of endtool position, velocity and acceleration in meters and radians.
The time step between trajectory is the control period, which is 250us by default.
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: Waits for specific digital or analog I/O signals to meet the given conditions.
Wait Time: Waits for a specified time, after starting the first motion command.
Wait Progress: Waits for progress status.
Wait Radius: Waits until movement within a specified radius is complete.
Wait Traj: Waits until trajectory movement is complete.
- Wait Traj conditions
- TRAJ_STARTED(0)
: trajectory has just started
- TRAJ_ACC_DONE(1)
: acceleration phase of the trajectory has been completed
- TRAJ_CRZ_DONE(2)
: cruising phase (constant speed phase) of the trajectory has been completed.
- TRAJ_DEC_DONE(3)
: deceleration phase of the trajectory has been completed.
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()
Example
Waits for specified digital and analog I/O signals to meet the given conditions.
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)
};
std::vector<Nrmk::IndyFramework::DigitalSignal> set_do_signals = {
Nrmk::IndyFramework::DigitalSignal(4, 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, // Conjunction (AND condition)
set_do_signals, // Digital output signals to set during wait
{}, // Digital output signals to set upon end
{}, // Analog output signals to set during wait
{} // Analog output signals to set upon end
);
if (is_success) {
std::cout << "WaitIO condition met successfully." << std::endl;
} else {
std::cerr << "WaitIO condition failed." << std::endl;
}
Teleoperation Related Functions
Teleoperation-related functions provide the capability to remotely control the robot. These functions allow real-time adjustment of the robot's motion and control in various operation modes. You can start the teleoperation mode using the start_teleop
function and end the mode using the stop_teleop
function. Additionally, you can update robot movements in joint space and workspace using the movetelej
and movetelel
functions, respectively.
Note
When using teleoperation motion through IndyDCP3, continuously updating the target position in real-time allows the robot to stream and generate smooth and immediate motion. Traditional Motion commands (movej
, movel
) perform path generation smoothly but cannot respond immediately like remote control. This is a characteristic of teleoperation motion.
Function | Description |
---|---|
start_teleop(TeleMethod method) |
Starts teleoperation mode |
stop_teleop() |
Ends teleoperation mode |
get_teleop_device(Nrmk::IndyFramework::TeleOpDevice& device) |
Retrieve information about the currently connected teleoperation device |
get_teleop_state(Nrmk::IndyFramework::TeleOpState& state) |
Retrieve the current state of teleoperation |
connect_teleop_device(const std::string& name, Nrmk::IndyFramework::TeleOpDevice_TeleOpDeviceType type, const std::string& ip, uint32_t port) |
Connect to a teleoperation device with specified parameters |
disconnect_teleop_device() |
Disconnect the currently connected teleoperation device |
read_teleop_input(Nrmk::IndyFramework::TeleP& teleop_input) |
Read the current input values from the teleoperation device |
set_play_rate(const float rate) |
Set the playback rate for teleoperation motion |
get_play_rate(float& rate) |
Retrieve the current playback rate for teleoperation motion |
get_tele_file_list(std::vector<std::string>& files) |
Retrieve a list of saved teleoperation motion files |
save_tele_motion(const std::string& name) |
Save the current teleoperation motion with a specified name |
load_tele_motion(const std::string& name) |
Load a saved teleoperation motion by name |
delete_tele_motion(const std::string& name) |
Delete a saved teleoperation motion by name |
enable_tele_key(const bool enable) |
Enable or disable teleoperation key input |
start_teleop()
Example
Starts teleoperation mode with the specified method.
TeleMethod method = TeleMethod::TELE_JOINT_RELATIVE;
bool is_success = indy.start_teleop(method);
if (is_success) {
std::cout << "Teleoperation mode started successfully." << std::endl;
} else {
std::cerr << "Failed to start teleoperation mode." << std::endl;
}
stop_teleop()
Example
Stops the teleoperation mode.
bool is_success = indy.stop_teleop();
if (is_success) {
std::cout << "Teleoperation mode stopped successfully." << std::endl;
} else {
std::cerr << "Failed to stop teleoperation mode." << std::endl;
}
get_teleop_device()
Example
Retrieve information about the currently connected teleoperation 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()
Example
Retrieve the current teleoperation 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()
Example
Connects to a teleoperation device with specified parameters.
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()
Example
Disconnects the currently connected teleoperation 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()
Example
Reads the current input values from the teleoperation device.
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()
Example
Sets the playback rate for teleoperation motion.
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()
Example
Retrieves the current playback rate for teleoperation motion.
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()
Example
Retrieves a list of saved teleoperation motion files.
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()
Example
Saves the current teleoperation motion with a specified name.
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()
Example
Loads a saved teleoperation motion by name.
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()
Example
Deletes a saved teleoperation motion by name.
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()
Example
Enables or disables teleoperation key input.
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;
}
Variable Handling Functions
The IndyDCP3 C++ API provides several functions to handle different types of variables, such as boolean, integer, float, joint position (JPos), and task position (TPos) variables. These variables can be used to exchange information between the robot and external devices.
Method | Description |
---|---|
get_bool_variable(std::vector<BoolVariable> &variables) |
Retrieves Bool type variables |
get_int_variable(std::vector<IntVariable> &variables) |
Retrieves Integer type variables |
get_float_variable(std::vector<FloatVariable> &variables) |
Retrieves Float type variables |
get_jpos_variable(std::vector<JPosVariable> &variables) |
Retrieves JPos type variables |
get_tpos_variable(std::vector<TPosVariable> &variables) |
Retrieves TPos type variables |
set_bool_variable(const std::vector<BoolVariable> &variables) |
Sets Bool type variables |
set_int_variable(const std::vector<IntVariable> &variables) |
Sets Integer type variables |
set_float_variable(const std::vector<FloatVariable> &variables) |
Sets Float type variables |
set_jpos_variable(const std::vector<JPosVariable> &variables) |
Sets JPos type variables |
set_tpos_variable(const std::vector<TPosVariable> &variables) |
Sets TPos type variables |
get_bool_variable()
Example
Retrieves the current values of Bool type variables from the robot.
std::vector<Nrmk::IndyFramework::BoolVariable> bool_vars;
bool is_success = indy.get_bool_variable(bool_vars);
if (is_success) {
std::cout << "Bool variables retrieved successfully." << std::endl;
for (const auto &var : bool_vars) {
std::cout << "Address: " << var.addr() << ", Value: " << var.value() << std::endl;
}
} else {
std::cerr << "Failed to retrieve Bool variables." << std::endl;
}
get_int_variable()
Example
Retrieves the current values of Integer type variables from the robot.
std::vector<Nrmk::IndyFramework::IntVariable> int_vars;
bool is_success = indy.get_int_variable(int_vars);
if (is_success) {
std::cout << "Integer variables retrieved successfully." << std::endl;
for (const auto &var : int_vars) {
std::cout << "Address: " << var.addr() << ", Value: " << var.value() << std::endl;
}
} else {
std::cerr << "Failed to retrieve Integer variables." << std::endl;
}
get_float_variable()
Example
Retrieves the current values of Float type variables from the robot.
std::vector<Nrmk::IndyFramework::FloatVariable> float_vars;
bool is_success = indy.get_float_variable(float_vars);
if (is_success) {
std::cout << "Float variables retrieved successfully." << std::endl;
for (const auto &var : float_vars) {
std::cout << "Address: " << var.addr() << ", Value: " << var.value() << std::endl;
}
} else {
std::cerr << "Failed to retrieve Float variables." << std::endl;
}
get_jpos_variable()
Example
Retrieves the current values of Joint Position (JPos) type variables from the robot.
std::vector<Nrmk::IndyFramework::JPosVariable> jpos_vars;
bool is_success = indy.get_jpos_variable(jpos_vars);
if (is_success) {
std::cout << "JPos variables retrieved successfully." << std::endl;
for (const auto &var : jpos_vars) {
std::cout << "Address: " << var.addr() << ", JPos: ";
for (const auto &jpos : var.jpos()) {
std::cout << jpos << " ";
}
std::cout << std::endl;
}
} else {
std::cerr << "Failed to retrieve JPos variables." << std::endl;
}
get_tpos_variable()
Example
Retrieves the current values of Task Position (TPos) type variables from the robot.
std::vector<Nrmk::IndyFramework::TPosVariable> tpos_vars;
bool is_success = indy.get_tpos_variable(tpos_vars);
if (is_success) {
std::cout << "TPos variables retrieved successfully." << std::endl;
for (const auto &var : tpos_vars) {
std::cout << "Address: " << var.addr() << ", TPos: ";
for (const auto &tpos : var.tpos()) {
std::cout << tpos << " ";
}
std::cout << std::endl;
}
} else {
std::cerr << "Failed to retrieve TPos variables." << std::endl;
}
set_bool_variable()
Example
Sets the values of Bool type variables in the robot.
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 << "Bool variables set successfully." << std::endl;
} else {
std::cerr << "Failed to set Bool variables." << std::endl;
}
set_int_variable()
Example
Sets the values of Integer type variables in the robot.
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 << "Integer variables set successfully." << std::endl;
} else {
std::cerr << "Failed to set Integer variables." << std::endl;
}
set_float_variable()
Example
Sets the values of Float type variables in the robot.
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 << "Float variables set successfully." << std::endl;
} else {
std::cerr << "Failed to set Float variables." << std::endl;
}
set_jpos_variable()
Example
Sets the values of Joint Position (JPos) type variables in the robot.
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 variables set successfully." << std::endl;
} else {
std::cerr << "Failed to set JPos variables." << std::endl;
}
set_tpos_variable()
Example
Sets the values of Tool Position (TPos) type variables in the robot.
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 variables set successfully." << std::endl;
} else {
std::cerr << "Failed to set TPos variables." << std::endl;
}
Inverse Kinematics and Simulation Mode Related Functions
The IndyDCP3 C++ API provides functions for performing inverse kinematics, enabling/disabling direct teaching mode, setting simulation mode, and recovering the robot from error states.
Method | Description |
---|---|
inverse_kin(const std::array<float, 6> &tpos, const std::vector<float> &init_jpos, std::vector<float> &jpos) |
Calculates joint positions to reach a target workspace position |
set_direct_teaching(bool enable) |
Enables or disables direct teaching mode |
set_simulation_mode(bool enable) |
Enables or disables simulation mode |
recover() |
Recovers the robot from an error or collision state |
inverse_kin()
Example
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 << "Inverse kinematics successful. Joint positions: ";
for (float jp : calculated_jpos) {
std::cout << jp << " ";
}
std::cout << std::endl;
} else {
std::cerr << "Inverse kinematics failed." << std::endl;
}
set_direct_teaching()
Example
bool enable_direct_teaching = true;
bool is_success = indy.set_direct_teaching(enable_direct_teaching);
if (is_success) {
std::cout << "Direct teaching mode enabled." << std::endl;
} else {
std::cerr << "Failed to enable direct teaching mode." << std::endl;
}
set_simulation_mode()
Example
bool enable_simulation = true;
bool is_success = indy.set_simulation_mode(enable_simulation);
if (is_success) {
std::cout << "Simulation mode enabled." << std::endl;
} else {
std::cerr << "Failed to enable simulation mode." << std::endl;
}
recover()
Example
bool is_success = indy.recover();
if (is_success) {
std::cout << "Recovery successful." << std::endl;
} else {
std::cerr << "Recovery failed." << std::endl;
}
Program Control Functions
Program control functions allow you to start, pause, resume, and stop robot programs. These functions are essential for managing the execution flow of pre-written programs.
Method | Description |
---|---|
play_program(const std::string &prog_name, int prog_idx) |
Starts a program by name or index |
pause_program() |
Pauses the currently running program |
resume_program() |
Resumes a paused program |
stop_program() |
Stops the currently running program |
play_program()
Example
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 << "Program started successfully." << std::endl;
} else {
std::cerr << "Failed to start program." << std::endl;
}
pause_program()
Example
bool is_success = indy.pause_program();
if (is_success) {
std::cout << "Program paused successfully." << std::endl;
} else {
std::cerr << "Failed to pause program." << std::endl;
}
resume_program()
Example
bool is_success = indy.resume_program();
if (is_success) {
std::cout << "Program resumed successfully." << std::endl;
} else {
std::cerr << "Failed to resume program." << std::endl;
}
stop_program()
Example
bool is_success = indy.stop_program();
if (is_success) {
std::cout << "Program stopped successfully." << std::endl;
} else {
std::cerr << "Failed to stop program." << std::endl;
}
Using IndySDK
The IndyDCP3 C++ API provides functions to activate the IndySDK, set custom control modes, and manage control gains. These functions are crucial for advanced users who want to develop custom controllers.
Method | Description |
---|---|
activate_sdk(const SDKLicenseInfo &request, SDKLicenseResp &response) |
Activates the IndySDK |
set_custom_control_mode(bool mode) |
Sets the custom control mode |
get_custom_control_mode(int &mode) |
Retrieves the current custom control mode |
set_custom_control_gain(const CustomGainSet &gain_set) |
Sets custom control gain for the user controller |
get_custom_control_gain(CustomGainSet &gain_set) |
Retrieves the current custom control gain settings |
set_joint_control_gain(const std::vector<float>& kp, const std::vector<float>& kv, const std::vector<float>& kl2) |
Set the control gains for joint-level control |
get_joint_control_gain(std::vector<float>& kp, std::vector<float>& kv, std::vector<float>& kl2) |
Retrieve the control gains for joint-level control |
set_task_control_gain(const std::vector<float>& kp, const std::vector<float>& kv, const std::vector<float>& kl2) |
Set the control gains for task-level control |
get_task_control_gain(std::vector<float>& kp, std::vector<float>& kv, std::vector<float>& kl2) |
Retrieve the control gains for task-level control |
set_impedance_control_gain(const std::vector<float>& mass, const std::vector<float>& damping, const std::vector<float>& stiffness, const std::vector<float>& kl2) |
Set the impedance control gains |
get_impedance_control_gain(std::vector<float>& mass, std::vector<float>& damping, std::vector<float>& stiffness, std::vector<float>& kl2) |
Retrieve the impedance control gains |
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) |
Set the force control gains |
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) |
Retrieve the force control gains |
activate_sdk()
Example
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 Activated: " << (response.activated() ? "Yes" : "No") << std::endl;
std::cout << "Response Code: " << response.response().code() << ", Message: " << response.response().msg() << std::endl;
} else {
std::cerr << "Failed to activate SDK." << std::endl;
}
set_custom_control_mode()
and get_custom_control_mode()
Example
int mode = 0;
bool is_success = indy.set_custom_control_mode(mode);
if (is_success) {
std::cout << "Custom control mode set successfully." << std::endl;
} else {
std::cerr << "Failed to set custom control mode." << std::endl;
}
int get_mode;
bool is_success = indy.get_custom_control_mode(get_mode);
if (is_success) {
std::cout << "Custom control mode: " << get_mode << std::endl;
} else {
std::cerr << "Failed to get custom control mode." << std::endl;
}
set_custom_control_gain()
Example
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 << "Custom control gain set successfully." << std::endl;
} else {
std::cerr << "Failed to set custom control gain." << std::endl;
}
get_custom_control_gain()
Example
Nrmk::IndyFramework::CustomGainSet gain_set;
bool is_success = indy.get_custom_control_gain(gain_set);
if (is_success) {
std::cout << "Custom control gains retrieved successfully." << 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 << "Failed to retrieve custom control gains." << std::endl;
}
set_joint_control_gain()
Example
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()
Example
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()
Example
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()
Example
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()
Example
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()
Example
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()
Example
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()
Example
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;
}
Utility Functions
Utility functions provide additional features such as data logging and setting simulation mode.
Method | Description |
---|---|
start_log() |
Starts realtime data logging |
end_log() |
Ends and saves realtime data logging |
wait_for_operation_state(op_state) |
Allows you to wait until the robot reaches a specific operation state. |
wait_for_motion_state(motion_state) |
Allows you to wait until the robot reaches a specific motion state. |
set_friction_comp_state(const bool enable) |
Enable or disable friction compensation |
get_friction_comp_state() |
Retrieve the current state of friction compensation |
set_mount_pos(float rot_y, float rot_z) |
Set the mounting angles for the robot base using Y and Z rotations |
get_mount_pos(float &rot_y, float &rot_z) |
Retrieve the current mounting angles for the robot base |
set_brakes(const std::vector<bool>& brake_state_list) |
Set the brake states for each motor |
set_servo_all(const bool enable) |
Enable or disable all servos |
set_servo(const uint32_t index, const bool enable) |
Enable or disable a specific servo by index |
set_endtool_led_dim(const uint32_t led_dim) |
Set the LED brightness for the end-effector tool |
execute_tool(const std::string& name) |
Execute a tool function by its name |
get_el5001(int& status, int& value, int& delta, float& average) |
Retrieve data from the EL5001 device |
get_el5101(int& status, int& value, int& latch, int& delta, float& average) |
Retrieve data from the EL5101 device |
get_brake_control_style(int& style) |
Retrieve the current brake control style |
set_conveyor_name(const std::string& name) |
Set the name of the conveyor |
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) |
Configure the conveyor encoder settings |
set_conveyor_trigger(int trigger_type, int64_t channel, bool detect_rise) |
Set the conveyor trigger settings |
set_conveyor_offset(float offset_mm) |
Set the offset value for the conveyor (in millimeters) |
set_conveyor_starting_pose(const std::vector<float>& jpos, const std::vector<float>& tpos) |
Set the starting joint and task poses for the conveyor |
set_conveyor_terminal_pose(const std::vector<float>& jpos, const std::vector<float>& tpos) |
Set the terminal joint and task poses for the conveyor |
start_log()
and end_log()
Example
bool is_success = indy.start_log();
if (is_success) {
std::cout << "Started data logging." << std::endl;
}
// After some time...
is_success = indy.end_log();
if (is_success) {
std::cout << "Ended data logging and saved data." << std::endl;
}
These two functions are used for realtime data logging. Upon calling start_log(), the robot's data is stored in memory. After a certain period, calling end_log() stops the memory logging and writes it to a file within STEP. The realtime data logging file can be found at the following path:
/home/user/release/IndyDeployments/RTlog/RTLog.csv
For more detailed usage and advanced features, please refer to C++ client at Neuromeka Github repository.
wait_for_operation_state(op_state)
For example, if you want to wait until the robot is in the MOVING state, you can call:
bool is_success = indy.wait_for_operation_state(OpState::OP_MOVING);
if (is_success) {
std::cout << "The robot has reached the target position." << std::endl;
} else {
std::cerr << "Failed to wait for the robot to reach the target position." << std::endl;
}
wait_for_motion_state(motion_state)
motion_state
:is_target_reached
is_in_motion
is_pausing
is_stopping
has_motion
For instance, if you want to wait until the robot's motion is complete, indicated by the state 'is_target_reached', you can call:
bool is_success = indy.wait_for_motion_state("is_target_reached");
if (is_success) {
std::cout << "The robot has reached the target position." << std::endl;
} else {
std::cerr << "Failed to wait for the robot to reach the target position." << std::endl;
}
set_friction_comp_state()
Example
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()
Example
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)
Example
Sets the mounting angles for the robot base using rotation angles around the Y and Z axes.
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)
Example
Retrieves the current mounting angles for the robot base.
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)
Example
Sets the brake states for each motor.
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)
Example
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)
Example
Enables or disables a specific servo by its index.
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)
Example
Sets the LED brightness for the end-effector tool.
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)
Example
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)
Example
Retrieves data from the EL5001 device.
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)
Example
Retrieves data from the EL5101 device.
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)
Example
Retrieves the current brake control 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)
Example
Sets the name of the conveyor.
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(...)
Example
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)
Example
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)
Example
Sets the offset value for the conveyor.
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)
Example
Sets the starting joint and task poses for the conveyor.
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)
Example
Sets the terminal joint and task poses for the conveyor.
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;
}