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.