6.6.5 minimal_instruction_sample.cpp
This example (5_minimal_instruction_sample.cpp) demonstrates a step-by-step instruction flow
for controlling the robot using the API:
register monitoring callbacks,
open/close the controller connection,
request control authority,
turn Servo On and check system/version,
switch robot mode/system,
execute a simple joint motion (
movej),test inverse kinematics (
ikin),and send/stop a DRL script.
Each function is mapped to a numeric key (1~8), so users can trigger individual operations one by one and observe how the API behaves in real time.
This example is located in the following path:
API-DRFL/example/Linux_64/5_minimal_instruction_sample.cpp
See the example on the Doosan Robotics API-DRFL GitHub.
Watch the full walk-through on the Doosan Robotics Official Youtube.
Setup & Global Variables
The example uses a global controller object and several flags to track control status.
#include "../../include/DRFLEx.h"
using namespace DRAFramework;
CDRFLEx Drfl;
bool g_bHasControlAuthority = FALSE;
bool g_TpInitailizingComplted = FALSE;
bool g_mStat = FALSE;
bool g_Stop = FALSE;
bool moving = FALSE;
A DRL script string and helper flags are also defined.
std::string strDrl =
"\r\n\
loop = 0\r\n\
while loop < 1003:\r\n\
movej(posj(10,10.10,10,10.10), vel=60, acc=60)\r\n\
movej(posj(00,00.00,00,00.00), vel=60, acc=60)\r\n\
loop+=1\r\n";
bool bAlterFlag = FALSE;
These globals are used throughout the example to store the DRFLEx instance, track whether control authority has been granted, control motion stop/pause/resume, and prepare DRL motion tests.
Callback Registration
When the user presses 1, the example registers several monitoring and event callbacks.
case '1':
{
Drfl.set_on_monitoring_data_ex(OnMonitoringDataExCB);
Drfl.set_on_monitoring_ctrl_io_ex(OnMonitoringCtrlIOExCB);
Drfl.set_on_log_alarm(OnLogAlarm);
Drfl.set_on_disconnected(OnDisConnected);
// Optional callbacks (commented):
// Drfl.set_on_monitoring_state(OnMonitoringStateCB);
// Drfl.set_on_tp_initializing_completed(OnTpInitializingCompleted);
// Drfl.set_on_tp_popup(OnTpPopup);
// Drfl.set_on_tp_log(OnTpLog);
// Drfl.set_on_tp_progress(OnTpProgress);
// Drfl.set_on_tp_get_user_input(OnTpGetuserInput);
// Drfl.set_on_rt_monitoring_data(OnRTMonitoringData);
std::cout << "Register Callbacks !! " << std::endl;
}
break;
These callbacks allow the application to monitor task/world poses and IO status, receive alarm information (OnLogAlarm), automatically reconnect when disconnected (OnDisConnected),
and optionally integrate with TP events and real-time monitoring.
Example console output:
input key : 1
Register Callbacks !!
Connection to Controller
Pressing 2 opens a TCP/IP connection to the controller.
case '2':
{
assert(Drfl.open_connection("192.168.137.100"));
std::cout << "Open Connection !! " << std::endl;
}
break;
The example uses
192.168.137.100assuming a real controller.For a virtual mode, replace this with the
127.0.0.1.
Example console output:
input key : 2
Open Connection !!
Servo On & Monitoring Version
Key 4 enables Servo, configures monitoring version, and prints system information.
case '4':
{
Drfl.setup_monitoring_version(1);
Drfl.set_robot_control(CONTROL_SERVO_ON);
Drfl.set_digital_output(GPIO_CTRLBOX_DIGITAL_INDEX_10, TRUE);
SYSTEM_VERSION tSysVerion = { '\0', };
Drfl.get_system_version(&tSysVerion);
std::cout << "System version: " << tSysVerion._szController << std::endl;
std::cout << "Library version: " << Drfl.get_library_version() << std::endl;
while ((Drfl.get_robot_state() != STATE_STANDBY) || !g_bHasControlAuthority)
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "Servo On !! " << std::endl;
}
break;
setup_monitoring_version(1)selects the newer monitoring context.set_robot_control(CONTROL_SERVO_ON)turns Servo On.The loop waits until both robot state = STANDBY and control authority are satisfied.
Example console output:
input key : 4
System version: GF03020000
Library version: GL013300
Servo On !!
Robot Mode & System Configuration
Key 5 switches to AUTONOMOUS mode and REAL system.
case '5':
{
assert(Drfl.set_robot_mode(ROBOT_MODE_AUTONOMOUS));
assert(Drfl.set_robot_system(ROBOT_SYSTEM_REAL));
std::cout << "Set Auto Mode !!" << std::endl;
}
break;
ROBOT_MODE_AUTONOMOUSenables programmatic motion execution.ROBOT_SYSTEM_REALindicates that the motion is executed on a real robot. Also you can changeROBOT_SYSTEM_VIRTUALif you want to execute in virtual mode.
Example console output:
input key : 5
Set Auto Mode !!
Joint Motion Execution
Key 6 executes a simple joint-space motion using movej.
case '6':
{
std::cout << "Move Start !! " << std::endl;
float p1[6] = {0, 0, 10, 0, 10, 0};
Drfl.movej(p1, 60, 30);
float p2[6] = {0, 0, 0, 0, 0, 0};
Drfl.movej(p2, 30, 30);
std::cout << "Move End !! " << std::endl;
}
break;
First move: joint 3 and 5 move to 10 deg at velocity 60, acceleration 30.
Second move: all joints return to 0 deg at velocity 30, acceleration 30.
Example console output:
input key : 6
Move Start !!
Move End !!
Kinematics Test
Key 7 demonstrates how to use the inverse kinematics function ikin.
case '7':
{
// Motion execution using kinematics functions
float x1[6] = {370.9, 719.7, 651.5, 90, -180, 0}; // task-space pose for IK conversion
LPROBOT_POSE res = Drfl.ikin(x1, 2); // ROBOT_POSE structure contains 6 float elements
// Store the IK result using a shallow copy
float q1[6] = {0,};
for (int i = 0; i < 6; i++) {
q1[i] = res->_fPosition[i]; // Copy elements from the returned LPROBOT_POSE
}
std::cout << " Get ikin Success (Task Space -> Joint Space) !! " << std::endl;
// Optionally: Drfl.movej(q1, 60, 30);
}
break;
ikincomputes a joint-space solution from a given task-space pose.The result can be used directly in a subsequent
movejcommand.
Example console output:
input key : 7
Get ikin Success (Task Space -> Joint Space) !!
DRL Script Execution
Key 8 sends and executes a DRL script that performs two movej motions.
case '8':
{
// DRL script example
std::string strDrl =
"movej([0, 0, 10, 0, 10, 0], 60, 30)\n"
"movej([0, 0, 0, 0, 0, 0], 60, 30)\n";
// Implements a simple DRL script that moves the robot between two positions using movej commands
Drfl.drl_start(ROBOT_SYSTEM_REAL, strDrl); // Use ROBOT_SYSTEM_REAL for actual hardware execution
Drfl.set_on_program_stopped(OnProgramStopped);
std::cout << "Sent DRL Script !!" << std::endl;
}
break;
The registered OnProgramStopped callback handles program termination.
void OnProgramStopped(const PROGRAM_STOP_CAUSE) {
Drfl.drl_stop();
std::cout << "program stopped" << std::endl;
}
During execution, alarm logs may appear when the DRL program stops.
input key : 8
Sent DRL Script !!
input key : Alarm Info: group(1), index(2007), param(), param(), param()
program stopped
This confirms that the DRL script was sent the program executed and the stop event and alarm were handled correctly.
Note
A DRL script string and helper flags are also defined.
In this minimal sample, a shorter inline DRL script is used in key 8 for clarity,
while the global strDrl shows an example of a more complex looped motion that can
be reused or extended in user applications.
string strDrl =
"\r\n\
loop = 0\r\n\
while loop < 1003:\r\n\
movej(posj(10,10.10,10,10.10), vel=60, acc=60)\r\n\
movej(posj(00,00.00,00,00.00), vel=60, acc=60)\r\n\
loop+=1\r\n";
Xenomai / Real-time Environment Notes
This sample also supports building in a Xenomai-based real-time environment.
When compiled with the __XENO__ macro, the following code paths are enabled.
#ifdef __XENO__
#include <rtdk.h>
#include <native/task.h>
#include <native/timer.h>
#else
// Standard Linux / non-RT environment
#endif // __XENO__
In the main loop, the real-time task is scheduled with a fixed period.
#ifdef __XENO__
unsigned long overrun = 0;
const double tick = 1000000; // 1 ms
rt_task_set_periodic(nullptr, TM_NOW, tick);
if (rt_task_wait_period(&overrun) == -ETIMEDOUT) {
std::cout << __func__ << ": over-runs: " << overrun << std::endl;
}
#else
std::this_thread::sleep_for(std::chrono::microseconds(1000));
#endif // __XENO__
In non-RT environments, the loop simply sleeps using
std::this_thread::sleep_for.In Xenomai RT environments, the loop is driven by
rt_task_set_periodicandrt_task_wait_periodto achieve deterministic timing and to detect possible overruns.
These blocks are independent from the DRFLEx API logic itself and are only required when deploying the sample in a strict real-time control environment.