Skip to content

Commit 4127006

Browse files
committed
Update tests and documentation regarding empty input recipes
1 parent 0ef331d commit 4127006

File tree

2 files changed

+91
-4
lines changed

2 files changed

+91
-4
lines changed

doc/architecture/rtde_client.rst

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ client. To use the RTDE-Client, you'll have to initialize and start it separatel
1111

1212
.. code-block:: c++
1313

14-
rtde_interface::RTDEClient my_client(ROBOT_IP, notifier, OUTPUT_RECIPE, INPUT_RECIPE);
14+
rtde_interface::RTDEClient my_client(ROBOT_IP, notifier, OUTPUT_RECIPE_FILE, INPUT_RECIPE_FILE);
1515
my_client.init();
1616
my_client.start();
1717
while (true)
@@ -28,6 +28,20 @@ outputs. Please refer to the `RTDE
2828
guide <https://www.universal-robots.com/articles/ur-articles/real-time-data-exchange-rtde-guide/>`_
2929
on which elements are available.
3030

31+
.. note::
32+
33+
The recipes can be either passed as a filename or as a list of strings directly. E.g. the
34+
following will work
35+
36+
.. code-block:: c++
37+
38+
rtde_interface::RTDEClient my_client(
39+
ROBOT_IP,
40+
notifier,
41+
{"timestamp", "actual_q"},
42+
{"speed_slider_mask", "speed_slider_fraction"}
43+
);
44+
3145
Inside the ``RTDEclient`` data is received in a separate thread, parsed by the ``RTDEParser`` and
3246
added to a pipeline queue.
3347

@@ -56,6 +70,29 @@ sure to
5670
frequency, please use the ``resetRTDEClient()`` method after the ``UrDriver`` object has been
5771
created.
5872

73+
Read-Only RTDEClient
74+
--------------------
75+
76+
While RTDE allows multiple clients to connect to the same robot, only one client is allowed to
77+
write data to the robot. To create a read-only RTDE client, the ``RTDEClient`` can be created with
78+
an empty input recipe, like this:
79+
80+
.. code-block:: c++
81+
82+
rtde_interface::RTDEClient my_client(ROBOT_IP, notifier, OUTPUT_RECIPE, {});
83+
// Alternatively, pass an empty filename when using recipe files
84+
// rtde_interface::RTDEClient my_client(ROBOT_IP, notifier, OUTPUT_RECIPE_FILE, "");
85+
my_client.init();
86+
my_client.start();
87+
while (true)
88+
{
89+
std::unique_ptr<rtde_interface::DataPackage> data_pkg = my_client.getDataPackage(READ_TIMEOUT);
90+
if (data_pkg)
91+
{
92+
std::cout << data_pkg->toString() << std::endl;
93+
}
94+
}
95+
5996
RTDEWriter
6097
----------
6198

@@ -66,3 +103,8 @@ The class offers specific methods for every RTDE input possible to write.
66103

67104
Data is sent asynchronously to the RTDE interface.
68105

106+
.. note::
107+
108+
The ``RTDEWriter`` will return ``false`` on any writing attempts for fields that have not been
109+
setup in the ``INPUT_RECIPE``. When no input recipe was provided, all write operations will
110+
return ``false``.

tests/test_rtde_client.cpp

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,12 @@ TEST_F(RTDEClientTest, no_recipe)
120120
UrException);
121121

122122
// Only input recipe is unconfigured
123-
EXPECT_THROW(
124-
client_.reset(new rtde_interface::RTDEClient(g_ROBOT_IP, notifier_, output_recipe_file_, input_recipe_file)),
125-
UrException);
123+
EXPECT_NO_THROW(
124+
client_.reset(new rtde_interface::RTDEClient(g_ROBOT_IP, notifier_, output_recipe_file_, input_recipe_file)));
125+
126+
EXPECT_THROW(client_.reset(new rtde_interface::RTDEClient(g_ROBOT_IP, notifier_, output_recipe_file_,
127+
"/i/do/not/exist/urclrtdetest.txt")),
128+
UrException);
126129
}
127130

128131
TEST_F(RTDEClientTest, empty_recipe_file)
@@ -413,6 +416,48 @@ TEST_F(RTDEClientTest, check_unknown_rtde_output_variable)
413416
EXPECT_THROW(client_->init(), UrException);
414417
}
415418

419+
TEST_F(RTDEClientTest, empty_input_recipe)
420+
{
421+
std::vector<std::string> empty_input_recipe = {};
422+
client_.reset(new rtde_interface::RTDEClient(g_ROBOT_IP, notifier_, resources_output_recipe_, empty_input_recipe));
423+
client_->init();
424+
client_->start();
425+
426+
// Test that we can receive and parse the timestamp from the received package to prove the setup was successful
427+
const std::chrono::milliseconds read_timeout{ 100 };
428+
std::unique_ptr<rtde_interface::DataPackage> data_pkg = client_->getDataPackage(read_timeout);
429+
430+
if (data_pkg == nullptr)
431+
{
432+
std::cout << "Failed to get data package from robot" << std::endl;
433+
GTEST_FAIL();
434+
}
435+
436+
double timestamp;
437+
EXPECT_TRUE(data_pkg->getData("timestamp", timestamp));
438+
439+
EXPECT_FALSE(client_->getWriter().sendStandardDigitalOutput(1, false));
440+
441+
client_->pause();
442+
443+
client_.reset(new rtde_interface::RTDEClient(g_ROBOT_IP, notifier_, output_recipe_file_, ""));
444+
client_->init();
445+
client_->start();
446+
447+
data_pkg = client_->getDataPackage(read_timeout);
448+
449+
if (data_pkg == nullptr)
450+
{
451+
std::cout << "Failed to get data package from robot" << std::endl;
452+
GTEST_FAIL();
453+
}
454+
EXPECT_TRUE(data_pkg->getData("timestamp", timestamp));
455+
456+
EXPECT_FALSE(client_->getWriter().sendStandardDigitalOutput(1, false));
457+
458+
client_->pause();
459+
}
460+
416461
int main(int argc, char* argv[])
417462
{
418463
::testing::InitGoogleTest(&argc, argv);

0 commit comments

Comments
 (0)