Skip to content

Commit 7ad9d20

Browse files
authored
[primary interface] More robot messages (UniversalRobots#429)
Add support for more RobotMessage types: - TextMessage - RuntimeExceptionMessage This also adds an integration test sending a program to the robot and verifying that the expected KeyMessage, TextMessage and RuntimeExceptionMessage objects are received.
1 parent b5be8bd commit 7ad9d20

9 files changed

Lines changed: 566 additions & 11 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ add_library(urcl
2828
src/primary/robot_message.cpp
2929
src/primary/robot_message/error_code_message.cpp
3030
src/primary/robot_message/key_message.cpp
31+
src/primary/robot_message/runtime_exception_message.cpp
32+
src/primary/robot_message/text_message.cpp
3133
src/primary/robot_message/version_message.cpp
3234
src/primary/robot_state.cpp
3335
src/primary/robot_state/kinematics_info.cpp

include/ur_client_library/primary/primary_parser.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "ur_client_library/comm/parser.h"
2626
#include "ur_client_library/primary/package_header.h"
2727
#include "ur_client_library/primary/robot_message/key_message.h"
28+
#include "ur_client_library/primary/robot_message/runtime_exception_message.h"
29+
#include "ur_client_library/primary/robot_message/text_message.h"
2830
#include "ur_client_library/primary/robot_state.h"
2931
#include "ur_client_library/primary/robot_message.h"
3032
#include "ur_client_library/primary/robot_state/kinematics_info.h"
@@ -178,12 +180,16 @@ class PrimaryParser : public comm::Parser<PrimaryPackage>
178180
//return new rmd;
179181
case robot_state_type::MASTERBOARD_DATA:
180182
return new MBD;*/
183+
case RobotMessagePackageType::ROBOT_MESSAGE_TEXT:
184+
return new TextMessage(timestamp, source);
181185
case RobotMessagePackageType::ROBOT_MESSAGE_VERSION:
182186
return new VersionMessage(timestamp, source);
183187
case RobotMessagePackageType::ROBOT_MESSAGE_ERROR_CODE:
184188
return new ErrorCodeMessage(timestamp, source);
185189
case RobotMessagePackageType::ROBOT_MESSAGE_KEY:
186190
return new KeyMessage(timestamp, source);
191+
case RobotMessagePackageType::ROBOT_MESSAGE_RUNTIME_EXCEPTION:
192+
return new RuntimeExceptionMessage(timestamp, source);
187193
default:
188194
return new RobotMessage(timestamp, source, type);
189195
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
2+
// -- BEGIN LICENSE BLOCK ----------------------------------------------
3+
// Copyright 2026 Universal Robots A/S
4+
//
5+
// Redistribution and use in source and binary forms, with or without
6+
// modification, are permitted provided that the following conditions are met:
7+
//
8+
// * Redistributions of source code must retain the above copyright
9+
// notice, this list of conditions and the following disclaimer.
10+
//
11+
// * Redistributions in binary form must reproduce the above copyright
12+
// notice, this list of conditions and the following disclaimer in the
13+
// documentation and/or other materials provided with the distribution.
14+
//
15+
// * Neither the name of the {copyright_holder} nor the names of its
16+
// contributors may be used to endorse or promote products derived from
17+
// this software without specific prior written permission.
18+
//
19+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29+
// POSSIBILITY OF SUCH DAMAGE.
30+
// -- END LICENSE BLOCK ------------------------------------------------
31+
32+
//----------------------------------------------------------------------
33+
/*!\file
34+
*
35+
* \author Felix Exner feex@universal-robots.com
36+
* \date 2026-02-03
37+
*
38+
*/
39+
//----------------------------------------------------------------------
40+
#ifndef UR_CLIENT_LIBRARY_PRIMARY_RUNTIME_EXCEPTION_MESSAGE_H_INCLUDED
41+
#define UR_CLIENT_LIBRARY_PRIMARY_RUNTIME_EXCEPTION_MESSAGE_H_INCLUDED
42+
43+
#include "ur_client_library/primary/robot_message.h"
44+
45+
namespace urcl
46+
{
47+
namespace primary_interface
48+
{
49+
/*!
50+
* \brief Representation of the RuntimeExceptionMessage robot message
51+
*/
52+
class RuntimeExceptionMessage : public RobotMessage
53+
{
54+
public:
55+
RuntimeExceptionMessage() = delete;
56+
/*!
57+
* \brief Creates a new RuntimeExceptionMessage object to be filled from a package.
58+
*
59+
* \param timestamp Timestamp of the package
60+
* \param source The package's source
61+
*/
62+
RuntimeExceptionMessage(uint64_t timestamp, int8_t source)
63+
: RobotMessage(timestamp, source, RobotMessagePackageType::ROBOT_MESSAGE_RUNTIME_EXCEPTION)
64+
{
65+
}
66+
67+
/*!
68+
* \brief Creates a copy of a RuntimeExceptionMessage object.
69+
*
70+
* \param pkg The RuntimeExceptionMessage object to be copied
71+
*/
72+
RuntimeExceptionMessage(const RuntimeExceptionMessage& pkg);
73+
74+
virtual ~RuntimeExceptionMessage() = default;
75+
76+
/*!
77+
* \brief Sets the attributes of the package by parsing a serialized representation of the
78+
* package.
79+
*
80+
* \param bp A parser containing a serialized text of the package
81+
*
82+
* \returns True, if the package was parsed successfully, false otherwise
83+
*/
84+
virtual bool parseWith(comm::BinParser& bp);
85+
86+
/*!
87+
* \brief Consume this package with a specific consumer.
88+
*
89+
* \param consumer Placeholder for the consumer calling this
90+
*
91+
* \returns true on success
92+
*/
93+
virtual bool consumeWith(AbstractPrimaryConsumer& consumer);
94+
95+
/*!
96+
* \brief Produces a human readable representation of the package object.
97+
*
98+
* \returns A string representing the object
99+
*/
100+
virtual std::string toString() const;
101+
102+
int32_t line_number_;
103+
int32_t column_number_;
104+
std::string text_;
105+
};
106+
} // namespace primary_interface
107+
} // namespace urcl
108+
109+
#endif // UR_CLIENT_LIBRARY_PRIMARY_RUNTIME_EXCEPTION_MESSAGE_H_INCLUDED
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// -- BEGIN LICENSE BLOCK ----------------------------------------------
2+
// Copyright 2026 Universal Robots A/S
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
//
7+
// * Redistributions of source code must retain the above copyright
8+
// notice, this list of conditions and the following disclaimer.
9+
//
10+
// * Redistributions in binary form must reproduce the above copyright
11+
// notice, this list of conditions and the following disclaimer in the
12+
// documentation and/or other materials provided with the distribution.
13+
//
14+
// * Neither the name of the {copyright_holder} nor the names of its
15+
// contributors may be used to endorse or promote products derived from
16+
// this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
// POSSIBILITY OF SUCH DAMAGE.
29+
// -- END LICENSE BLOCK ------------------------------------------------
30+
31+
//----------------------------------------------------------------------
32+
/*!\file
33+
*
34+
* \author Felix Exner feex@universal-robots.com
35+
* \date 2026-02-03
36+
*
37+
*/
38+
//----------------------------------------------------------------------
39+
40+
#ifndef UR_CLIENT_LIBRARY_PRIMARY_TEXT_MESSAGE_H_INCLUDED
41+
#define UR_CLIENT_LIBRARY_PRIMARY_TEXT_MESSAGE_H_INCLUDED
42+
43+
#include "ur_client_library/primary/robot_message.h"
44+
45+
namespace urcl
46+
{
47+
namespace primary_interface
48+
{
49+
/*!
50+
* \brief The TextMessage class handles the text messages sent via the primary UR interface.
51+
*/
52+
class TextMessage : public RobotMessage
53+
{
54+
public:
55+
TextMessage() = delete;
56+
/*!
57+
* \brief Creates a new TextMessage object to be filled from a package.
58+
*
59+
* \param timestamp Timestamp of the package
60+
* \param source The package's source
61+
*/
62+
TextMessage(uint64_t timestamp, int8_t source)
63+
: RobotMessage(timestamp, source, RobotMessagePackageType::ROBOT_MESSAGE_TEXT)
64+
{
65+
}
66+
67+
/*!
68+
* \brief Creates a copy of a TextMessage object.
69+
*
70+
* \param pkg The TextMessage object to be copied
71+
*/
72+
TextMessage(const TextMessage& pkg)
73+
: RobotMessage(pkg.timestamp_, pkg.source_, RobotMessagePackageType::ROBOT_MESSAGE_TEXT)
74+
{
75+
text_ = pkg.text_;
76+
}
77+
virtual ~TextMessage() = default;
78+
79+
/*!
80+
* \brief Sets the attributes of the package by parsing a serialized representation of the
81+
* package.
82+
*
83+
* \param bp A parser containing a serialized text of the package
84+
*
85+
* \returns True, if the package was parsed successfully, false otherwise
86+
*/
87+
virtual bool parseWith(comm::BinParser& bp);
88+
89+
/*!
90+
* \brief Consume this package with a specific consumer.
91+
*
92+
* \param consumer Placeholder for the consumer calling this
93+
*
94+
* \returns true on success
95+
*/
96+
virtual bool consumeWith(AbstractPrimaryConsumer& consumer);
97+
98+
/*!
99+
* \brief Produces a human readable representation of the package object.
100+
*
101+
* \returns A string representing the object
102+
*/
103+
virtual std::string toString() const;
104+
105+
std::string text_;
106+
};
107+
} // namespace primary_interface
108+
} // namespace urcl
109+
110+
#endif // ifndef UR_CLIENT_LIBRARY_PRIMARY_TEXT_MESSAGE_H_INCLUDED
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// -- BEGIN LICENSE BLOCK ----------------------------------------------
2+
// Copyright 2026 Universal Robots A/S
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
//
7+
// * Redistributions of source code must retain the above copyright
8+
// notice, this list of conditions and the following disclaimer.
9+
//
10+
// * Redistributions in binary form must reproduce the above copyright
11+
// notice, this list of conditions and the following disclaimer in the
12+
// documentation and/or other materials provided with the distribution.
13+
//
14+
// * Neither the name of the {copyright_holder} nor the names of its
15+
// contributors may be used to endorse or promote products derived from
16+
// this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
// POSSIBILITY OF SUCH DAMAGE.
29+
// -- END LICENSE BLOCK ------------------------------------------------
30+
31+
//----------------------------------------------------------------------
32+
/*!\file
33+
*
34+
* \author Felix Exner feex@universal-robots.com
35+
* \date 2026-02-03
36+
*
37+
*/
38+
//----------------------------------------------------------------------
39+
#include "ur_client_library/primary/robot_message/runtime_exception_message.h"
40+
#include "ur_client_library/primary/abstract_primary_consumer.h"
41+
42+
namespace urcl
43+
{
44+
namespace primary_interface
45+
{
46+
RuntimeExceptionMessage::RuntimeExceptionMessage(const RuntimeExceptionMessage& pkg)
47+
: RobotMessage(pkg.timestamp_, pkg.source_, RobotMessagePackageType::ROBOT_MESSAGE_RUNTIME_EXCEPTION)
48+
{
49+
line_number_ = pkg.line_number_;
50+
column_number_ = pkg.column_number_;
51+
text_ = pkg.text_;
52+
}
53+
54+
bool RuntimeExceptionMessage::parseWith(comm::BinParser& bp)
55+
{
56+
bp.parse(line_number_);
57+
bp.parse(column_number_);
58+
bp.parseRemainder(text_);
59+
60+
return true; // not really possible to check dynamic size packets
61+
}
62+
63+
bool RuntimeExceptionMessage::consumeWith(AbstractPrimaryConsumer& consumer)
64+
{
65+
return consumer.consume(*this);
66+
}
67+
68+
std::string RuntimeExceptionMessage::toString() const
69+
{
70+
std::stringstream ss;
71+
ss << "RuntimeException:" << std::endl;
72+
ss << "Runtime error in line " << line_number_;
73+
ss << ", column " << column_number_ << std::endl;
74+
ss << "Error: " << text_;
75+
return ss.str();
76+
}
77+
} // namespace primary_interface
78+
} // namespace urcl
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// -- BEGIN LICENSE BLOCK ----------------------------------------------
2+
// Copyright 2026 Universal Robots A/S
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
//
7+
// * Redistributions of source code must retain the above copyright
8+
// notice, this list of conditions and the following disclaimer.
9+
//
10+
// * Redistributions in binary form must reproduce the above copyright
11+
// notice, this list of conditions and the following disclaimer in the
12+
// documentation and/or other materials provided with the distribution.
13+
//
14+
// * Neither the name of the {copyright_holder} nor the names of its
15+
// contributors may be used to endorse or promote products derived from
16+
// this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
// POSSIBILITY OF SUCH DAMAGE.
29+
// -- END LICENSE BLOCK ------------------------------------------------
30+
31+
//----------------------------------------------------------------------
32+
/*!\file
33+
*
34+
* \author Felix Exner feex@universal-robots.com
35+
* \date 2026-02-03
36+
*
37+
*/
38+
//----------------------------------------------------------------------
39+
#include "ur_client_library/primary/robot_message/text_message.h"
40+
#include "ur_client_library/primary/abstract_primary_consumer.h"
41+
42+
namespace urcl
43+
{
44+
namespace primary_interface
45+
{
46+
bool TextMessage::parseWith(comm::BinParser& bp)
47+
{
48+
bp.parseRemainder(text_);
49+
50+
return true;
51+
}
52+
53+
bool TextMessage::consumeWith(AbstractPrimaryConsumer& consumer)
54+
{
55+
return consumer.consume(*this);
56+
}
57+
58+
std::string TextMessage::toString() const
59+
{
60+
return "TextMessage: " + text_;
61+
}
62+
} // namespace primary_interface
63+
} // namespace urcl

0 commit comments

Comments
 (0)