ros2_control - rolling
handle.hpp
1 // Copyright 2020 PAL Robotics S.L.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef HARDWARE_INTERFACE__HANDLE_HPP_
16 #define HARDWARE_INTERFACE__HANDLE_HPP_
17 
18 #include <limits>
19 #include <memory>
20 #include <mutex>
21 #include <shared_mutex>
22 #include <string>
23 #include <utility>
24 #include <variant>
25 
26 #include "hardware_interface/hardware_info.hpp"
27 #include "hardware_interface/macros.hpp"
28 
29 namespace hardware_interface
30 {
31 
32 using HANDLE_DATATYPE = std::variant<double>;
33 
35 class Handle
36 {
37 public:
38  [[deprecated("Use InterfaceDescription for initializing the Interface")]]
39 
40  Handle(
41  const std::string & prefix_name, const std::string & interface_name,
42  double * value_ptr = nullptr)
43  : prefix_name_(prefix_name),
44  interface_name_(interface_name),
45  handle_name_(prefix_name_ + "/" + interface_name_),
46  value_ptr_(value_ptr)
47  {
48  }
49 
50  explicit Handle(const InterfaceDescription & interface_description)
51  : prefix_name_(interface_description.get_prefix_name()),
52  interface_name_(interface_description.get_interface_name()),
53  handle_name_(interface_description.get_name())
54  {
55  // As soon as multiple datatypes are used in HANDLE_DATATYPE
56  // we need to initialize according the type passed in interface description
57  value_ = std::numeric_limits<double>::quiet_NaN();
58  value_ptr_ = std::get_if<double>(&value_);
59  }
60 
61  [[deprecated("Use InterfaceDescription for initializing the Interface")]]
62 
63  explicit Handle(const std::string & interface_name)
64  : interface_name_(interface_name), handle_name_("/" + interface_name_), value_ptr_(nullptr)
65  {
66  }
67 
68  [[deprecated("Use InterfaceDescription for initializing the Interface")]]
69 
70  explicit Handle(const char * interface_name)
71  : interface_name_(interface_name), handle_name_("/" + interface_name_), value_ptr_(nullptr)
72  {
73  }
74 
75  Handle(const Handle & other) noexcept
76  {
77  std::unique_lock<std::shared_mutex> lock(other.handle_mutex_);
78  std::unique_lock<std::shared_mutex> lock_this(handle_mutex_);
79  prefix_name_ = other.prefix_name_;
80  interface_name_ = other.interface_name_;
81  handle_name_ = other.handle_name_;
82  value_ = other.value_;
83  value_ptr_ = other.value_ptr_;
84  }
85 
86  Handle(Handle && other) noexcept
87  {
88  std::unique_lock<std::shared_mutex> lock(other.handle_mutex_);
89  std::unique_lock<std::shared_mutex> lock_this(handle_mutex_);
90  prefix_name_ = std::move(other.prefix_name_);
91  interface_name_ = std::move(other.interface_name_);
92  handle_name_ = std::move(other.handle_name_);
93  value_ = std::move(other.value_);
94  value_ptr_ = std::move(other.value_ptr_);
95  }
96 
97  Handle & operator=(const Handle & other)
98  {
99  if (this != &other)
100  {
101  std::unique_lock<std::shared_mutex> lock(other.handle_mutex_);
102  std::unique_lock<std::shared_mutex> lock_this(handle_mutex_);
103  prefix_name_ = other.prefix_name_;
104  interface_name_ = other.interface_name_;
105  handle_name_ = other.handle_name_;
106  value_ = other.value_;
107  value_ptr_ = other.value_ptr_;
108  }
109  return *this;
110  }
111 
112  Handle & operator=(Handle && other)
113  {
114  if (this != &other)
115  {
116  std::unique_lock<std::shared_mutex> lock(other.handle_mutex_);
117  std::unique_lock<std::shared_mutex> lock_this(handle_mutex_);
118  prefix_name_ = std::move(other.prefix_name_);
119  interface_name_ = std::move(other.interface_name_);
120  handle_name_ = std::move(other.handle_name_);
121  value_ = std::move(other.value_);
122  value_ptr_ = std::move(other.value_ptr_);
123  }
124  return *this;
125  }
126 
127  virtual ~Handle() = default;
128 
130  inline operator bool() const { return value_ptr_ != nullptr; }
131 
132  const std::string & get_name() const { return handle_name_; }
133 
134  const std::string & get_interface_name() const { return interface_name_; }
135 
136  [[deprecated(
137  "Replaced by get_name method, which is semantically more correct")]] const std::string &
138  get_full_name() const
139  {
140  return get_name();
141  }
142 
143  const std::string & get_prefix_name() const { return prefix_name_; }
144 
145  [[deprecated("Use bool get_value(double & value) instead to retrieve the value.")]]
146  double get_value() const
147  {
148  std::shared_lock<std::shared_mutex> lock(handle_mutex_, std::try_to_lock);
149  if (!lock.owns_lock())
150  {
151  return std::numeric_limits<double>::quiet_NaN();
152  }
153  // BEGIN (Handle export change): for backward compatibility
154  // TODO(Manuel) return value_ if old functionality is removed
155  THROW_ON_NULLPTR(value_ptr_);
156  return *value_ptr_;
157  // END
158  }
159 
160  [[nodiscard]] bool get_value(double & value) const
161  {
162  std::shared_lock<std::shared_mutex> lock(handle_mutex_, std::try_to_lock);
163  if (!lock.owns_lock())
164  {
165  return false;
166  }
167  // BEGIN (Handle export change): for backward compatibility
168  // TODO(Manuel) set value directly if old functionality is removed
169  THROW_ON_NULLPTR(value_ptr_);
170  value = *value_ptr_;
171  return true;
172  // END
173  }
174 
175  [[nodiscard]] bool set_value(double value)
176  {
177  std::unique_lock<std::shared_mutex> lock(handle_mutex_, std::try_to_lock);
178  if (!lock.owns_lock())
179  {
180  return false;
181  }
182  // BEGIN (Handle export change): for backward compatibility
183  // TODO(Manuel) set value_ directly if old functionality is removed
184  THROW_ON_NULLPTR(this->value_ptr_);
185  *this->value_ptr_ = value;
186  return true;
187  // END
188  }
189 
190 protected:
191  std::string prefix_name_;
192  std::string interface_name_;
193  std::string handle_name_;
194  HANDLE_DATATYPE value_;
195  // BEGIN (Handle export change): for backward compatibility
196  // TODO(Manuel) redeclare as HANDLE_DATATYPE * value_ptr_ if old functionality is removed
197  double * value_ptr_;
198  // END
199  mutable std::shared_mutex handle_mutex_;
200 };
201 
202 class StateInterface : public Handle
203 {
204 public:
205  explicit StateInterface(const InterfaceDescription & interface_description)
206  : Handle(interface_description)
207  {
208  }
209 
210  StateInterface(const StateInterface & other) = default;
211 
212  StateInterface(StateInterface && other) = default;
213 
214  using Handle::Handle;
215 
216  using SharedPtr = std::shared_ptr<StateInterface>;
217  using ConstSharedPtr = std::shared_ptr<const StateInterface>;
218 };
219 
220 class CommandInterface : public Handle
221 {
222 public:
223  explicit CommandInterface(const InterfaceDescription & interface_description)
224  : Handle(interface_description)
225  {
226  }
228 
233  CommandInterface(const CommandInterface & other) = delete;
234 
235  CommandInterface(CommandInterface && other) = default;
236 
237  using Handle::Handle;
238 
239  using SharedPtr = std::shared_ptr<CommandInterface>;
240 };
241 
242 } // namespace hardware_interface
243 
244 #endif // HARDWARE_INTERFACE__HANDLE_HPP_
Definition: handle.hpp:221
CommandInterface(const CommandInterface &other)=delete
CommandInterface copy constructor is actively deleted.
A handle used to get and set a value on a given interface.
Definition: handle.hpp:36
Definition: handle.hpp:203
Definition: actuator.hpp:34
Definition: hardware_info.hpp:138