Skip to content

Commit 50e2a20

Browse files
committed
Add parsing masterboard data
1 parent 40bc3c8 commit 50e2a20

7 files changed

Lines changed: 484 additions & 5 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ add_library(urcl
3838
src/primary/robot_state/kinematics_info.cpp
3939
src/primary/robot_state/robot_mode_data.cpp
4040
src/primary/robot_state/configuration_data.cpp
41+
src/primary/robot_state/masterboard_data.cpp
4142
src/rtde/control_package_pause.cpp
4243
src/rtde/control_package_setup_inputs.cpp
4344
src/rtde/control_package_setup_outputs.cpp
@@ -190,4 +191,4 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/share/${PROJECT_NAME}/hook/ros_package_pa
190191
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/share/${PROJECT_NAME}/hook/ros_package_path.dsv DESTINATION share/${PROJECT_NAME}/hook)
191192
#### End iport ####
192193

193-
install(DIRECTORY resources DESTINATION share/${PROJECT_NAME})
194+
install(DIRECTORY resources DESTINATION share/${PROJECT_NAME})

include/ur_client_library/primary/abstract_primary_consumer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "ur_client_library/primary/robot_state/kinematics_info.h"
3737
#include "ur_client_library/primary/robot_state/robot_mode_data.h"
3838
#include "ur_client_library/primary/robot_state/configuration_data.h"
39+
#include "ur_client_library/primary/robot_state/masterboard_data.h"
3940
#include "ur_client_library/primary/robot_message/safety_mode_message.h"
4041

4142
namespace urcl
@@ -80,6 +81,7 @@ class AbstractPrimaryConsumer : public comm::IConsumer<PrimaryPackage>
8081
virtual bool consume(ErrorCodeMessage& pkg) = 0;
8182
virtual bool consume(RobotModeData& pkg) = 0;
8283
virtual bool consume(ConfigurationData& pkg) = 0;
84+
virtual bool consume(MasterboardData& pkg) = 0;
8385
virtual bool consume(SafetyModeMessage& pkg) = 0;
8486

8587
private:

include/ur_client_library/primary/primary_consumer.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "ur_client_library/primary/abstract_primary_consumer.h"
3232
#include "ur_client_library/primary/robot_state/robot_mode_data.h"
33+
#include "ur_client_library/primary/robot_state/masterboard_data.h"
3334
#include "ur_client_library/ur/datatypes.h"
3435
#include "ur_client_library/ur/version_information.h"
3536

@@ -185,6 +186,20 @@ class PrimaryConsumer : public AbstractPrimaryConsumer
185186
return true;
186187
}
187188

189+
/*!
190+
* \brief Handle a MasterboardData package
191+
*
192+
* \param pkg MasterboardData
193+
*
194+
* \returns True
195+
*/
196+
virtual bool consume(MasterboardData& pkg) override
197+
{
198+
std::scoped_lock lock(masterboard_data_mutex_);
199+
masterboard_data_ = std::make_shared<MasterboardData>(pkg);
200+
return true;
201+
}
202+
188203
/*!
189204
* \brief Set callback function which will be triggered whenever error code messages are received
190205
*
@@ -267,6 +282,8 @@ class PrimaryConsumer : public AbstractPrimaryConsumer
267282
std::mutex configuration_data_mutex_;
268283
std::mutex safety_mode_mutex_;
269284
std::shared_ptr<SafetyModeMessage> safety_mode_;
285+
std::mutex masterboard_data_mutex_;
286+
std::shared_ptr<MasterboardData> masterboard_data_;
270287
};
271288

272289
} // namespace primary_interface

include/ur_client_library/primary/primary_parser.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "ur_client_library/primary/robot_message/error_code_message.h"
3535
#include "ur_client_library/primary/robot_state/robot_mode_data.h"
3636
#include "ur_client_library/primary/robot_state/configuration_data.h"
37+
#include "ur_client_library/primary/robot_state/masterboard_data.h"
3738
#include "ur_client_library/primary/robot_message/safety_mode_message.h"
3839

3940
namespace urcl
@@ -209,10 +210,8 @@ class PrimaryParser : public comm::Parser<PrimaryPackage>
209210
{
210211
case RobotStateType::ROBOT_MODE_DATA:
211212
return new RobotModeData(type);
212-
213-
// return new rmd;
214-
// case robot_state_type::MASTERBOARD_DATA:
215-
// return new MBD;*/
213+
case RobotStateType::MASTERBOARD_DATA:
214+
return new MasterboardData(type);
216215
case RobotStateType::KINEMATICS_INFO:
217216
return new KinematicsInfo(type);
218217
case RobotStateType::CONFIGURATION_DATA:
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
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+
#ifndef UR_CLIENT_LIBRARY_MASTERBOARD_DATA_H_INCLUDED
32+
#define UR_CLIENT_LIBRARY_MASTERBOARD_DATA_H_INCLUDED
33+
34+
#include <bitset>
35+
36+
#include "ur_client_library/types.h"
37+
#include "ur_client_library/primary/robot_state.h"
38+
39+
namespace urcl
40+
{
41+
namespace primary_interface
42+
{
43+
/*!
44+
* \brief The MasterboardData class handles the masterboard data sub-package sent as part of the
45+
* Robot State message on the primary UR interface.
46+
*
47+
* This package contains information about the control box IOs, analog inputs/outputs, voltages,
48+
* currents, temperatures, the safety mode, as well as information about the optional IMMI
49+
* interface. See the Universal Robots primary/secondary guide for details:
50+
* https://docs.universal-robots.com/tutorials/communication-protocol-tutorials/primary-secondary-guide.html
51+
*/
52+
class MasterboardData : public RobotState
53+
{
54+
public:
55+
MasterboardData() = delete;
56+
57+
/*!
58+
* \brief Creates a new MasterboardData object.
59+
*
60+
* \param type The type of RobotState message received
61+
*/
62+
MasterboardData(const RobotStateType type) : RobotState(type)
63+
{
64+
}
65+
66+
/*!
67+
* \brief Creates a copy of a MasterboardData object.
68+
*
69+
* \param pkg The MasterboardData object to be copied
70+
*/
71+
MasterboardData(const MasterboardData& pkg);
72+
73+
virtual ~MasterboardData() = default;
74+
75+
/*!
76+
* \brief Sets the attributes of the package by parsing a serialized representation of the
77+
* package.
78+
*
79+
* \param bp A parser containing a serialized version of the package
80+
*
81+
* \returns True, if the package was parsed successfully, false otherwise
82+
*/
83+
virtual bool parseWith(comm::BinParser& bp);
84+
85+
/*!
86+
* \brief Consume this specific package with a specific consumer.
87+
*
88+
* \param consumer Placeholder for the consumer calling this
89+
*
90+
* \returns true on success
91+
*/
92+
virtual bool consumeWith(AbstractPrimaryConsumer& consumer);
93+
94+
/*!
95+
* \brief Produces a human readable representation of the package object.
96+
*
97+
* \returns A string representing the object
98+
*/
99+
virtual std::string toString() const;
100+
101+
std::bitset<32> digital_input_bits_;
102+
std::bitset<32> digital_output_bits_;
103+
uint8_t analog_input_range_0_;
104+
uint8_t analog_input_range_1_;
105+
double analog_input_0_;
106+
double analog_input_1_;
107+
char analog_output_domain_0_;
108+
char analog_output_domain_1_;
109+
double analog_output_0_;
110+
double analog_output_1_;
111+
float master_board_temperature_;
112+
float robot_voltage_48v_;
113+
float robot_current_;
114+
float master_io_current_;
115+
uint8_t safety_mode_;
116+
bool in_reduced_mode_;
117+
bool immi_interface_installed_{ false };
118+
119+
// The following four fields are only valid if immi_interface_installed_ is true.
120+
std::bitset<32> immi_input_bits_;
121+
std::bitset<32> immi_output_bits_;
122+
float immi_voltage_24v_{ 0.0f };
123+
float immi_current_{ 0.0f };
124+
125+
uint32_t reserved_1_{ 0 };
126+
uint8_t operational_mode_selector_input_{ 0 };
127+
bool three_position_enabling_device_input_{ false };
128+
uint8_t reserved_2_{ 0 };
129+
};
130+
131+
} // namespace primary_interface
132+
} // namespace urcl
133+
134+
#endif // ifndef UR_CLIENT_LIBRARY_MASTERBOARD_DATA_H_INCLUDED
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
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+
#include "ur_client_library/primary/robot_state/masterboard_data.h"
32+
#include "ur_client_library/primary/abstract_primary_consumer.h"
33+
34+
#include <iomanip>
35+
#include <sstream>
36+
37+
namespace urcl
38+
{
39+
namespace primary_interface
40+
{
41+
MasterboardData::MasterboardData(const MasterboardData& pkg) : RobotState(RobotStateType::MASTERBOARD_DATA)
42+
{
43+
digital_input_bits_ = pkg.digital_input_bits_;
44+
digital_output_bits_ = pkg.digital_output_bits_;
45+
analog_input_range_0_ = pkg.analog_input_range_0_;
46+
analog_input_range_1_ = pkg.analog_input_range_1_;
47+
analog_input_0_ = pkg.analog_input_0_;
48+
analog_input_1_ = pkg.analog_input_1_;
49+
analog_output_domain_0_ = pkg.analog_output_domain_0_;
50+
analog_output_domain_1_ = pkg.analog_output_domain_1_;
51+
analog_output_0_ = pkg.analog_output_0_;
52+
analog_output_1_ = pkg.analog_output_1_;
53+
master_board_temperature_ = pkg.master_board_temperature_;
54+
robot_voltage_48v_ = pkg.robot_voltage_48v_;
55+
robot_current_ = pkg.robot_current_;
56+
master_io_current_ = pkg.master_io_current_;
57+
safety_mode_ = pkg.safety_mode_;
58+
in_reduced_mode_ = pkg.in_reduced_mode_;
59+
immi_interface_installed_ = pkg.immi_interface_installed_;
60+
immi_input_bits_ = pkg.immi_input_bits_;
61+
immi_output_bits_ = pkg.immi_output_bits_;
62+
immi_voltage_24v_ = pkg.immi_voltage_24v_;
63+
immi_current_ = pkg.immi_current_;
64+
reserved_1_ = pkg.reserved_1_;
65+
operational_mode_selector_input_ = pkg.operational_mode_selector_input_;
66+
three_position_enabling_device_input_ = pkg.three_position_enabling_device_input_;
67+
reserved_2_ = pkg.reserved_2_;
68+
}
69+
70+
bool MasterboardData::parseWith(comm::BinParser& bp)
71+
{
72+
bp.parse<uint32_t>(digital_input_bits_);
73+
bp.parse<uint32_t>(digital_output_bits_);
74+
bp.parse(analog_input_range_0_);
75+
bp.parse(analog_input_range_1_);
76+
bp.parse(analog_input_0_);
77+
bp.parse(analog_input_1_);
78+
bp.parse(analog_output_domain_0_);
79+
bp.parse(analog_output_domain_1_);
80+
bp.parse(analog_output_0_);
81+
bp.parse(analog_output_1_);
82+
bp.parse(master_board_temperature_);
83+
bp.parse(robot_voltage_48v_);
84+
bp.parse(robot_current_);
85+
bp.parse(master_io_current_);
86+
bp.parse(safety_mode_);
87+
bp.parse(in_reduced_mode_);
88+
bp.parse(immi_interface_installed_);
89+
90+
if (immi_interface_installed_)
91+
{
92+
bp.parse<uint32_t>(immi_input_bits_);
93+
bp.parse<uint32_t>(immi_output_bits_);
94+
bp.parse(immi_voltage_24v_);
95+
bp.parse(immi_current_);
96+
}
97+
98+
bp.parse(reserved_1_);
99+
bp.parse(operational_mode_selector_input_);
100+
bp.parse(three_position_enabling_device_input_);
101+
bp.parse(reserved_2_);
102+
103+
return true;
104+
}
105+
106+
bool MasterboardData::consumeWith(AbstractPrimaryConsumer& consumer)
107+
{
108+
return consumer.consume(*this);
109+
}
110+
111+
std::string MasterboardData::toString() const
112+
{
113+
std::stringstream os;
114+
os << "MasterboardData:" << std::endl;
115+
os << "Digital input bits: 0b" << digital_input_bits_ << std::endl;
116+
os << "Digital output bits: 0b" << digital_output_bits_ << std::endl;
117+
os << "Analog input range 0: " << unsigned(analog_input_range_0_) << std::endl;
118+
os << "Analog input range 1: " << unsigned(analog_input_range_1_) << std::endl;
119+
os << "Analog input 0: " << analog_input_0_ << std::endl;
120+
os << "Analog input 1: " << analog_input_1_ << std::endl;
121+
os << "Analog output domain 0: " << static_cast<int>(analog_output_domain_0_) << std::endl;
122+
os << "Analog output domain 1: " << static_cast<int>(analog_output_domain_1_) << std::endl;
123+
os << "Analog output 0: " << analog_output_0_ << std::endl;
124+
os << "Analog output 1: " << analog_output_1_ << std::endl;
125+
os << "Masterboard temperature: " << master_board_temperature_ << std::endl;
126+
os << "Robot voltage 48V: " << robot_voltage_48v_ << std::endl;
127+
os << "Robot current: " << robot_current_ << std::endl;
128+
os << "Master I/O current: " << master_io_current_ << std::endl;
129+
os << "Safety mode: " << unsigned(safety_mode_) << std::endl;
130+
os << "In reduced mode: " << in_reduced_mode_ << std::endl;
131+
os << "IMMI interface installed: " << immi_interface_installed_ << std::endl;
132+
if (immi_interface_installed_)
133+
{
134+
os << "IMMI input bits: 0b" << immi_input_bits_ << std::endl;
135+
os << "IMMI output bits: 0b" << immi_output_bits_ << std::endl;
136+
os << "IMMI voltage 24V: " << immi_voltage_24v_ << std::endl;
137+
os << "IMMI current: " << immi_current_ << std::endl;
138+
}
139+
os << "Operational mode selector input: " << unsigned(operational_mode_selector_input_) << std::endl;
140+
os << "Three position enabling device input: " << three_position_enabling_device_input_ << std::endl;
141+
142+
return os.str();
143+
}
144+
145+
} // namespace primary_interface
146+
} // namespace urcl

0 commit comments

Comments
 (0)