6.6.2 **minimal_rt_monitoring_sample.cpp**
---------------------------------------------
This example (``2_minimal_rt_monitoring_sample.cpp``) shows a **minimal realtime
monitoring** setup using the DRFLEx API:
- open the **realtime (RT) monitoring** channel with ``connect_rt_control()``,
- configure the RT session with ``set_rt_control_output()``,
- register an RT monitoring callback (``set_on_rt_monitoring_data``),
- and start/stop RT monitoring with simple console input.
.. figure:: /tutorials/images/tutorials/2_minimal_rt_monitoring_sample.gif
:alt: 2_minimal_rt_monitoring_sample
:width: 100%
:align: center
.. raw:: html
.. Caution::
**Realtime monitoring and control are supported only on a real robot system.** The sample sets ``IP_ADDRESS`` to ``127.0.0.1``; set it to the IP address of the real controller (for example ``192.168.137.100``) before running it.
This example is located in the following path: |br|
``API-DRFL/example/Linux_64/2_minimal_rt_monitoring_sample.cpp``
See the example on the `Doosan Robotics API-DRFL GitHub `_.
Overview & Global Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The sample starts by selecting the DRCF protocol version and creating a global
DRFLEx instance.
The sample sets ``DRCF_VERSION`` to 2 unless the compiler defines it. For a DRCF v3 controller, pass ``-DDRCF_VERSION=3`` to the compiler.
.. code-block:: cpp
#ifndef DRCF_VERSION
#define DRCF_VERSION 2 // Set 2 or 3 according to drcf version, or pass -DDRCF_VERSION=3.
#endif
#include "../../include/DRFLEx.h"
#include
#include
#include
using namespace DRAFramework;
// ...
const std::string IP_ADDRESS = "127.0.0.1";
CDRFLEx robot; // Instance for APIs
bool get_control_access = false; // Variable to check control authority
bool is_standby = false; // Variable to check whether the robot state is standby.
#define GREEN "\033[1;32m"
#define CYAN "\033[1;36m"
- ``DRCF_VERSION``: must match the controller firmware (e.g. 2 or 3).
- ``IP_ADDRESS``: set to ``127.0.0.1`` in the sample. Replace it with the IP address of the **real controller**.
- Color macros (``GREEN``, ``CYAN``) are used to print colored output in the terminal.
Realtime Connection Setup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The main function first opens the realtime monitoring connection.
.. code-block:: cpp
int main(){
// Connect to the drcf cotnroller.
bool ret = robot.connect_rt_control(IP_ADDRESS);
std::cout << "open connection return value " << ret << std::endl;
if (true != ret) {
std::cout << "Cannot open connection to robot @ " << IP_ADDRESS
<< std::endl;
return 1;
}
// For rt - monitoring, we don't need to have "Getting control access".
// however, for rt-writing like servoj_rt, we still need to have "control access" and "state standby".
- ``connect_rt_control(IP_ADDRESS)`` opens the **UDP realtime channel** to the controller.
- If the connection fails (e.g. wrong IP, no real controller), the program prints
an error and exits.
- **RT monitoring only** (read-only) does **not** require control authority.
- **RT writing** (e.g. ``servoj_rt``, torque commands) does not require control authority either, but the robot must be in **STATE_STANDBY** or **STATE_MOVING**. The comment in the sample that says RT writing needs control access is outdated.
RT Monitoring Callback
~~~~~~~~~~~~~~~~~~~~~~~~~
The example registers a **lambda callback** to receive realtime state data.
.. code-block:: cpp
robot.set_on_rt_monitoring_data([](LPRT_OUTPUT_DATA_LIST data)->void{
if (!data) return;
auto ms = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count();
printf(GREEN "[%.3f] === Robot State ===\n", ms / 1000.0);
printf(CYAN "Joint Position: ");
for (int i = 0; i < 6; ++i) {
printf("%.3f%s", data->actual_joint_position[i], (i < 5) ? ", " : "\n");
}
printf(CYAN "Joint Velocity: ");
for (int i = 0; i < 6; ++i) {
printf("%.3f%s", data->actual_joint_velocity[i], (i < 5) ? ", " : "\n");
}
printf(CYAN "Joint Torque: ");
for (int i = 0; i < 6; ++i) {
printf("%.3f%s", data->actual_joint_torque[i], (i < 5) ? ", " : "\n");
}
printf(CYAN "Gravity Torque: ");
for (int i = 0; i < 6; ++i) {
printf("%.3f%s", data->gravity_torque[i], (i < 5) ? ", " : "\n");
}
// Pretty matrix printer
auto print_matrix = [](const char* name, float mat[6][6]) {
printf(CYAN "%s:\n", name);
for (int i = 0; i < 6; ++i) {
printf(CYAN " [");
for (int j = 0; j < 6; ++j) {
printf(CYAN "%7.3f%s", mat[i][j], (j < 5) ? ", " : "");
}
printf(CYAN "]\n");
}
};
print_matrix(CYAN "Jacobian Matrix", data->jacobian_matrix);
print_matrix(CYAN "Mass Matrix", data->mass_matrix);
print_matrix(CYAN "Coriolis Matrix", data->coriolis_matrix);
});
The callback returns immediately when ``data`` is null. Otherwise it prints a timestamp based on the local system clock, joint positions, joint velocities, joint torques, gravity torques, and dynamic matrices (Jacobian, Mass, Coriolis).
.. figure:: /tutorials/images/tutorials/2_minimal_rt_monitoring_sample_result.png
:alt: 2_minimal_rt_monitoring_sample_result
:width: 80%
:align: center
.. raw:: html
- **RT Session Configuration & Start**
After registering the callback, the sample configures the RT session with ``set_rt_control_output()``, waits for **Enter**, calls ``start_rt_control()``, waits for **Enter** again and calls ``disconnect_rt_control()``.
.. code-block:: cpp
string version = "v1.0";
// The output configuration drives the monitoring stream; its period is in seconds.
float period = 0.01f; // 100 Hz
int losscount = 4;
std::cout << "RT Result " << robot.set_rt_control_output(version, period, losscount) << std::endl;
std::cout << "Press Enter to continue..." ;
std::cin.get(); // Waits for user to press Enter
robot.start_rt_control();
std::cout << "Press Enter to terminate..." ;
std::cin.get(); // Waits for user to press Enter
robot.disconnect_rt_control();
return 0;
RT Output
~~~~~~~~~~~~~~~~~
Before starting the RT session, the program calls ``set_rt_control_output()``, which sets how often the controller sends RT data.
.. code-block:: cpp
string version = "v1.0";
// The output configuration drives the monitoring stream; its period is in seconds.
float period = 0.01f; // 100 Hz
int losscount = 4;
std::cout << "RT Result " << robot.set_rt_control_output(version, period, losscount) << std::endl;
- ``version = "v1.0"``: selects the RT protocol version.
- ``period = 0.01f``: passed as the ``fPeriod`` argument, the communication period in seconds (100 Hz).
- ``losscount = 4``: passed as the ``nLossCnt`` argument, the allowed consecutive loss count.
See :ref:`set_rt_control_output ` for the parameters. The return value is printed to the console. It reports only that the configuration was sent, not that the controller accepted it.
Start & Stop RT Monitoring
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The example uses simple **Enter key prompts** to start and stop RT monitoring.
.. code-block:: cpp
std::cout << "Press Enter to continue..." ;
std::cin.get(); // Waits for user to press Enter
robot.start_rt_control();
std::cout << "Press Enter to terminate..." ;
std::cin.get(); // Waits for user to press Enter
robot.disconnect_rt_control();
return 0;
- After the first ``Enter``, the sample calls ``start_rt_control()``.
- After the second ``Enter``, ``disconnect_rt_control()`` closes the realtime
monitoring channel and the program exits.