Skip to content

Commit 822142a

Browse files
committed
Update ScriptSender documentation with example
1 parent a3d9ceb commit 822142a

File tree

4 files changed

+85
-77
lines changed

4 files changed

+85
-77
lines changed

doc/architecture.rst

Lines changed: 4 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -13,71 +13,13 @@ The core of this library is the ``UrDriver`` class which creates a
1313
fully functioning robot interface. For details on how to use it, please see the
1414
:ref:`example-driver` section.
1515

16-
The ``UrDriver``'s modules will be explained in the following.
17-
18-
RTDEClient
19-
----------
20-
21-
The ``RTDEClient`` class serves as a standalone
22-
`RTDE <https://www.universal-robots.com/articles/ur-articles/real-time-data-exchange-rtde-guide/>`_
23-
client. To use the RTDE-Client, you'll have to initialize and start it separately:
24-
25-
.. code-block:: c++
26-
27-
rtde_interface::RTDEClient my_client(ROBOT_IP, notifier, OUTPUT_RECIPE, INPUT_RECIPE);
28-
my_client.init();
29-
my_client.start();
30-
while (true)
31-
{
32-
std::unique_ptr<rtde_interface::DataPackage> data_pkg = my_client.getDataPackage(READ_TIMEOUT);
33-
if (data_pkg)
34-
{
35-
std::cout << data_pkg->toString() << std::endl;
36-
}
37-
}
38-
39-
Upon construction, two recipe files have to be given, one for the RTDE inputs, one for the RTDE
40-
outputs. Please refer to the `RTDE
41-
guide <https://www.universal-robots.com/articles/ur-articles/real-time-data-exchange-rtde-guide/>`_
42-
on which elements are available.
43-
44-
Inside the ``RTDEclient`` data is received in a separate thread, parsed by the ``RTDEParser`` and
45-
added to a pipeline queue.
46-
47-
Right after calling ``my_client.start()``, it should be made sure to read the buffer from the
48-
``RTDEClient`` by calling ``getDataPackage()`` frequently. The Client's queue can only contain 1
49-
item at a time, so a ``Pipeline producer overflowed!`` error will be raised if the buffer isn't read
50-
before the next package arrives.
51-
52-
For writing data to the RTDE interface, use the ``RTDEWriter`` member of the ``RTDEClient``. It can be
53-
retrieved by calling ``getWriter()`` method. The ``RTDEWriter`` provides convenience methods to write
54-
all data available at the RTDE interface. Make sure that the required keys are configured inside the
55-
input recipe, as otherwise the send-methods will return ``false`` if the data field is not setup in
56-
the recipe.
16+
.. toctree::
17+
:maxdepth: 1
5718

58-
An example of a standalone RTDE-client can be found in the ``examples`` subfolder. To run it make
59-
sure to
19+
architecture/script_sender
6020

61-
* have an instance of a robot controller / URSim running at the configured IP address (or adapt the
62-
address to your needs)
63-
* run it from the package's main folder, as for simplicity reasons it doesn't use any sophisticated
64-
method to locate the required files.
65-
66-
.. note::
67-
The ``URDriver`` class creates a ``RTDEClient`` during initialization using the provided
68-
recipes and utilizing the robot model's maximum frequency. If you would like to use a different
69-
frequency, please use the ``resetRTDEClient()`` method after the ``UrDriver`` object has been
70-
created.
71-
72-
RTDEWriter
73-
^^^^^^^^^^
74-
75-
The ``RTDEWriter`` class provides an interface to write data to the RTDE interface. Data fields that
76-
should be written have to be defined inside the ``INPUT_RECIPE`` as noted above.
77-
78-
The class offers specific methods for every RTDE input possible to write.
21+
The ``UrDriver``'s modules will be explained in the following.
7922

80-
Data is sent asynchronously to the RTDE interface.
8123

8224
ReverseInterface
8325
----------------
@@ -97,21 +39,6 @@ script <../resources/external_control.urscript>`_ for reference.
9739
Also see the :ref:`ScriptSender` for a way to define the corresponding URScript on the
9840
control PC and sending it to the robot upon request.
9941

100-
.. _ScriptSender:
101-
102-
ScriptSender
103-
------------
104-
105-
The ``ScriptSender`` class opens a tcp socket on the remote PC whose single purpose it is to answer
106-
with a URScript code snippet on a "*request_program*" request. The script code itself has to be
107-
given to the class constructor.
108-
109-
Use this class in conjunction with the `External Control URCap
110-
<https://github.com/UniversalRobots/Universal_Robots_ExternalControl_URCap>`_ which will make the
111-
corresponding request when starting a program on the robot that contains the **External Control**
112-
program node. In order to work properly, make sure that the IP address and script sender port are
113-
configured correctly on the robot.
114-
11542
Other public interface functions
11643
--------------------------------
11744

doc/architecture/script_sender.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.. _ScriptSender:
2+
3+
ScriptSender
4+
============
5+
6+
The ``ScriptSender`` class opens a tcp socket listens for "*request_program*" request. Upon such a
7+
request, a predefined URScript code is sent to the caller. The script code itself has to be passed
8+
to the ``ScriptSender``'s constructor.
9+
10+
Use this class in conjunction with the `External Control URCap
11+
<https://github.com/UniversalRobots/Universal_Robots_ExternalControl_URCap>`_ which will make the
12+
corresponding request when starting a program on the robot that contains the **External Control**
13+
program node. In order to work properly, make sure that the IP address and script sender port are
14+
configured correctly on the robot.
15+
16+
The following example creates a ``ScriptSender`` listening on port ``12345`` and sends the script
17+
``textmsg("Hello, World!")`` when requested. A fully compilable example can be found in `script_sender.cpp <https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/examples/script_sender.cpp>`_
18+
19+
.. literalinclude:: ../../examples/script_sender.cpp
20+
:language: c++
21+
:caption: examples/script_sender.cpp
22+
:linenos:
23+
:lineno-match:
24+
:start-at: constexpr uint32_t PORT

examples/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,8 @@ add_executable(force_mode_example
5454
force_mode_example.cpp)
5555
target_compile_options(force_mode_example PUBLIC ${CXX17_FLAG})
5656
target_link_libraries(force_mode_example ur_client_library::urcl)
57+
58+
add_executable(script_sender_example
59+
script_sender.cpp)
60+
target_compile_options(script_sender_example PUBLIC ${CXX17_FLAG})
61+
target_link_libraries(script_sender_example ur_client_library::urcl)

examples/script_sender.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// -- BEGIN LICENSE BLOCK ----------------------------------------------
2+
// Copyright 2024 Universal Robots A/S
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// -- END LICENSE BLOCK ------------------------------------------------
16+
17+
//----------------------------------------------------------------------
18+
/*!\file
19+
*
20+
* \author Felix Exner [email protected]
21+
* \date 2024-12-04
22+
*
23+
*/
24+
//----------------------------------------------------------------------
25+
26+
#include <iostream>
27+
#include <thread>
28+
29+
#include <ur_client_library/control/script_sender.h>
30+
31+
constexpr uint32_t PORT = 12345;
32+
33+
int main(int argc, char* argv[])
34+
{
35+
// Parse how may seconds to run
36+
int second_to_run = -1;
37+
if (argc > 2)
38+
{
39+
second_to_run = std::stoi(argv[2]);
40+
}
41+
urcl::control::ScriptSender sender(PORT, "textmsg(\"Hello, World!\")");
42+
43+
std::cout << "Waiting for incoming requests on port " << PORT << "..." << std::endl;
44+
45+
unsigned long startTime = clock();
46+
while (second_to_run < 0 || ((clock() - startTime) / CLOCKS_PER_SEC) < static_cast<unsigned int>(second_to_run))
47+
{
48+
std::this_thread::sleep_for(std::chrono::seconds(1));
49+
}
50+
51+
return 0;
52+
}

0 commit comments

Comments
 (0)