Skip to content

Commit ba7bab1

Browse files
Addressed PR comments
1 parent 56d5bee commit ba7bab1

File tree

13 files changed

+350
-91
lines changed

13 files changed

+350
-91
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ add_library(urcl SHARED
1616
src/control/trajectory_point_interface.cpp
1717
src/control/script_command_interface.cpp
1818
src/primary/primary_package.cpp
19+
src/primary/primary_client.cpp
1920
src/primary/robot_message.cpp
2021
src/primary/robot_state.cpp
2122
src/primary/robot_message/version_message.cpp
@@ -34,7 +35,6 @@ add_library(urcl SHARED
3435
src/ur/ur_driver.cpp
3536
src/ur/calibration_checker.cpp
3637
src/ur/error_code_reader.cpp
37-
src/ur/error_code_client.cpp
3838
src/ur/dashboard_client.cpp
3939
src/ur/tool_communication.cpp
4040
src/ur/robot_receive_timeout.cpp

include/ur_client_library/comm/pipeline.h

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include <thread>
3030
#include <vector>
3131
#include <fstream>
32+
#include <mutex>
33+
#include <algorithm>
3234

3335
namespace urcl
3436
{
@@ -83,26 +85,54 @@ class IConsumer
8385

8486
/*!
8587
* \brief Consumer, that allows one product to be consumed by multiple arbitrary
86-
* conusmers.
88+
* consumers.
8789
*
8890
* @tparam T Type of the consumed products
8991
*/
9092
template <typename T>
9193
class MultiConsumer : public IConsumer<T>
9294
{
9395
private:
94-
std::vector<IConsumer<T>*> consumers_;
96+
std::vector<std::shared_ptr<IConsumer<T>>> consumers_;
9597

9698
public:
9799
/*!
98100
* \brief Creates a new MultiConsumer object.
99101
*
100102
* \param consumers The list of consumers that should all consume given products
101103
*/
102-
MultiConsumer(std::vector<IConsumer<T>*> consumers) : consumers_(consumers)
104+
MultiConsumer(std::vector<std::shared_ptr<IConsumer<T>>> consumers) : consumers_(consumers)
103105
{
104106
}
105107

108+
/*!
109+
* \brief Adds a new consumer to the list of consumers
110+
*
111+
* \param consumer Consumer that should be added to the list
112+
*/
113+
void addConsumer(std::shared_ptr<IConsumer<T>> consumer)
114+
{
115+
std::lock_guard<std::mutex> lk(consumer_list);
116+
consumers_.push_back(consumer);
117+
}
118+
119+
/*!
120+
* \brief Remove a consumer from the list of consumers
121+
*
122+
* \param consumer Consumer that should be removed from the list
123+
*/
124+
void removeConsumer(std::shared_ptr<IConsumer<T>> consumer)
125+
{
126+
std::lock_guard<std::mutex> lk(consumer_list);
127+
auto it = std::find(consumers_.begin(), consumers_.end(), consumer);
128+
if (it == consumers_.end())
129+
{
130+
URCL_LOG_ERROR("Unable to remove consumer as it is not part of the consumer list");
131+
return;
132+
}
133+
consumers_.erase(it);
134+
}
135+
106136
/*!
107137
* \brief Sets up all registered consumers.
108138
*/
@@ -153,6 +183,7 @@ class MultiConsumer : public IConsumer<T>
153183
*/
154184
bool consume(std::shared_ptr<T> product)
155185
{
186+
std::lock_guard<std::mutex> lk(consumer_list);
156187
bool res = true;
157188
for (auto& con : consumers_)
158189
{
@@ -161,6 +192,9 @@ class MultiConsumer : public IConsumer<T>
161192
}
162193
return res;
163194
}
195+
196+
private:
197+
std::mutex consumer_list;
164198
};
165199

166200
/*!
@@ -234,7 +268,7 @@ class INotifier
234268
};
235269

236270
/*!
237-
* \brief The Pipepline manages the production and optionally consumption of packages. Cyclically
271+
* \brief The Pipeline manages the production and optionally consumption of packages. Cyclically
238272
* the producer is called and returned packages are saved in a queue. This queue is then either also
239273
* cyclically utilized by the registered consumer or can be externally used.
240274
*

include/ur_client_library/primary/abstract_primary_consumer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "ur_client_library/log.h"
3333
#include "ur_client_library/comm/pipeline.h"
3434
#include "ur_client_library/primary/robot_message/version_message.h"
35+
#include "ur_client_library/primary/robot_message/error_code_message.h"
3536
#include "ur_client_library/primary/robot_state/kinematics_info.h"
3637

3738
namespace urcl
@@ -51,7 +52,7 @@ class AbstractPrimaryConsumer : public comm::IConsumer<PrimaryPackage>
5152
virtual ~AbstractPrimaryConsumer() = default;
5253

5354
/*!
54-
* \brief This consume method is usally being called by the Pipeline structure. We don't
55+
* \brief This consume method is usually being called by the Pipeline structure. We don't
5556
* necessarily need to know the specific package type here, as the packages themselves will take
5657
* care to be consumed with the correct function (visitor pattern).
5758
*
@@ -73,6 +74,7 @@ class AbstractPrimaryConsumer : public comm::IConsumer<PrimaryPackage>
7374
virtual bool consume(RobotState& pkg) = 0;
7475
virtual bool consume(VersionMessage& pkg) = 0;
7576
virtual bool consume(KinematicsInfo& pkg) = 0;
77+
virtual bool consume(ErrorCodeMessage& pkg) = 0;
7678

7779
private:
7880
/* data */
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include <memory>
2+
3+
#include <ur_client_library/comm/stream.h>
4+
#include <ur_client_library/comm/pipeline.h>
5+
#include <ur_client_library/comm/producer.h>
6+
#include <ur_client_library/primary/abstract_primary_consumer.h>
7+
#include <ur_client_library/primary/primary_consumer.h>
8+
#include <ur_client_library/primary/primary_package.h>
9+
#include <ur_client_library/primary/primary_parser.h>
10+
#include <ur_client_library/ur/error_code_reader.h>
11+
namespace urcl
12+
{
13+
namespace primary_interface
14+
{
15+
class PrimaryClient
16+
{
17+
public:
18+
PrimaryClient() = delete;
19+
PrimaryClient(comm::URStream<PrimaryPackage>& stream);
20+
~PrimaryClient();
21+
22+
/*!
23+
* \brief Adds a primary consumer to the list of consumers
24+
*
25+
* \param primary_consumer Primary consumer that should be added to the list
26+
*/
27+
void addPrimaryConsumer (std::shared_ptr<AbstractPrimaryConsumer> primary_consumer);
28+
29+
/*!
30+
* \brief Remove a primary consumer from the list of consumers
31+
*
32+
* \param primary_consumer Primary consumer that should be removed from the list
33+
*/
34+
void removePrimaryConsumer(std::shared_ptr<AbstractPrimaryConsumer> primary_consumer);
35+
void start();
36+
37+
std::deque<ErrorCode> getErrorCodes();
38+
39+
private:
40+
41+
// The function is called whenever an error code message is received
42+
void errorMessageCallback(ErrorCode& code);
43+
44+
PrimaryParser parser_;
45+
std::shared_ptr<PrimaryConsumer> consumer_;
46+
std::unique_ptr<comm::MultiConsumer<PrimaryPackage>> multi_consumer_;
47+
48+
comm::INotifier notifier_;
49+
50+
comm::URStream<PrimaryPackage>& stream_;
51+
std::unique_ptr<comm::URProducer<PrimaryPackage>> prod_;
52+
std::unique_ptr<comm::Pipeline<PrimaryPackage>> pipeline_;
53+
54+
std::mutex error_code_queue_mutex_;
55+
std::deque<ErrorCode> error_code_queue_;
56+
};
57+
58+
} // namespace primary_interface
59+
} // namespace urcl
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2+
//
3+
// -- BEGIN LICENSE BLOCK ----------------------------------------------
4+
// Copyright 2020 FZI Forschungszentrum Informatik
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
// -- END LICENSE BLOCK ------------------------------------------------
18+
19+
//----------------------------------------------------------------------
20+
/*!\file
21+
*
22+
* \author Felix Exner [email protected]
23+
* \date 2020-04-30
24+
*
25+
*/
26+
//----------------------------------------------------------------------
27+
28+
#ifndef UR_CLIENT_LIBRARY_PRIMARY_CONSUMER_H_INCLUDED
29+
#define UR_CLIENT_LIBRARY_PRIMARY_CONSUMER_H_INCLUDED
30+
31+
#include "ur_client_library/primary/abstract_primary_consumer.h"
32+
33+
#include <functional>
34+
#include <mutex>
35+
#include <condition_variable>
36+
37+
namespace urcl
38+
{
39+
namespace primary_interface
40+
{
41+
/*!
42+
* \brief Primary consumer implementation
43+
*
44+
* This class implements an AbstractPrimaryConsumer such that it can consume all incoming primary
45+
* messages. The actual work for each package will be done in this class.
46+
*/
47+
class PrimaryConsumer : public AbstractPrimaryConsumer
48+
{
49+
public:
50+
PrimaryConsumer() {}
51+
virtual ~PrimaryConsumer() = default;
52+
53+
/*!
54+
* \brief Consume a RobotMessage
55+
*
56+
* \param msg Robot message
57+
*
58+
* \returns True
59+
*/
60+
virtual bool consume(RobotMessage& msg) override
61+
{
62+
return true;
63+
}
64+
65+
/*!
66+
* \brief Consume a RobotState
67+
*
68+
* \param msg Robot state
69+
*
70+
* \returns True
71+
*/
72+
virtual bool consume(RobotState& msg) override
73+
{
74+
return true;
75+
}
76+
77+
/*!
78+
* \brief Handle a VersionMessage
79+
*
80+
* \param pkg VersionMessage
81+
*
82+
* \returns True
83+
*/
84+
virtual bool consume(VersionMessage& pkg) override
85+
{
86+
return true;
87+
}
88+
89+
/*!
90+
* \brief Handle a KinematicsInfo
91+
*
92+
* \param pkg KinematicsInfo
93+
*
94+
* \returns True
95+
*/
96+
virtual bool consume(KinematicsInfo& pkg) override
97+
{
98+
return true;
99+
}
100+
101+
/*!
102+
* \brief Handle an ErrorCodeMessage
103+
*
104+
* \param pkg ErrorCodeMessage
105+
*
106+
* \returns True
107+
*/
108+
virtual bool consume(ErrorCodeMessage& pkg) override
109+
{
110+
urcl::primary_interface::ErrorCode code;
111+
code.message_code = pkg.message_code_;
112+
code.message_argument = pkg.message_argument_;
113+
code.report_level = pkg.report_level_;
114+
code.data_type = pkg.data_type_;
115+
code.data = pkg.data_;
116+
code.text = pkg.text_;
117+
code.timestamp = pkg.timestamp_;
118+
code.to_string = pkg.toString();
119+
120+
const auto logContents =
121+
"Logging an ErrorCodeMessage from the UR Controller Box: " + pkg.toString();
122+
123+
switch (code.report_level)
124+
{
125+
case urcl::primary_interface::ReportLevel::DEBUG:
126+
case urcl::primary_interface::ReportLevel::DEVL_DEBUG:
127+
case urcl::primary_interface::ReportLevel::DEVL_INFO:
128+
case urcl::primary_interface::ReportLevel::DEVL_WARNING:
129+
case urcl::primary_interface::ReportLevel::DEVL_VIOLATION:
130+
case urcl::primary_interface::ReportLevel::DEVL_FAULT:
131+
URCL_LOG_DEBUG(logContents.c_str());
132+
break;
133+
case urcl::primary_interface::ReportLevel::INFO:
134+
URCL_LOG_INFO(logContents.c_str());
135+
break;
136+
case urcl::primary_interface::ReportLevel::WARNING:
137+
URCL_LOG_WARN(logContents.c_str());
138+
break;
139+
default:
140+
// urcl::primary_interface::ReportLevel::VIOLATION:
141+
// urcl::primary_interface::ReportLevel::FAULT:
142+
URCL_LOG_ERROR(logContents.c_str());
143+
break;
144+
}
145+
146+
if (error_code_message_callback_ != nullptr)
147+
{
148+
error_code_message_callback_(code);
149+
}
150+
return true;
151+
}
152+
153+
/*!
154+
* \brief Set callback function which will be triggered whenever error code messages are received
155+
*
156+
* \param callback_function Function handling the event information. The error code message received is passed to the
157+
* function.
158+
*/
159+
void setErrorCodeMessageCallback(std::function<void(ErrorCode&)> callback_function)
160+
{
161+
error_code_message_callback_ = callback_function;
162+
}
163+
164+
private:
165+
std::function<void(ErrorCode&)> error_code_message_callback_;
166+
167+
};
168+
169+
} // namespace primary_interface
170+
} // namespace urcl
171+
172+
#endif // ifndef UR_CLIENT_LIBRARY_PRIMARY_CONSUMER_H_INCLUDED

include/ur_client_library/primary/robot_message/error_code_message.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
// Below code is copied from a branch on the Universal_Robot_Client_Library
2-
// with some modification. Link to branch:
3-
// https://github.com/UniversalRobots/Universal_Robots_Client_Library/tree/improve_primary_interface
4-
//
51
// this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
62

73
// -- BEGIN LICENSE BLOCK ----------------------------------------------

0 commit comments

Comments
 (0)