ros2_control - jazzy
Loading...
Searching...
No Matches
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 <fmt/compile.h>
19
20#include <algorithm>
21#include <cstdint>
22#include <cstdlib>
23#include <functional>
24#include <limits>
25#include <memory>
26#include <mutex>
27#include <optional>
28#include <shared_mutex>
29#include <string>
30#include <type_traits>
31#include <typeinfo>
32#include <utility>
33#include <variant>
34
35#ifndef _WIN32
36#include <cxxabi.h>
37#endif
38
39#include "hardware_interface/hardware_info.hpp"
40#include "hardware_interface/introspection.hpp"
41#include "hardware_interface/lexical_casts.hpp"
42#include "hardware_interface/macros.hpp"
43
44namespace
45{
46#ifndef _WIN32
47template <typename T>
48std::string get_type_name()
49{
50 int status = 0;
51 std::unique_ptr<char[], void (*)(void *)> res{
52 abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status), std::free};
53 return (status == 0) ? res.get() : typeid(T).name();
54}
55#else
56// not supported on Windows, use typeid directly
57template <typename T>
58std::string get_type_name()
59{
60 return typeid(T).name();
61}
62#endif
63} // namespace
64
65namespace hardware_interface
66{
67
69class Handle
70{
71public:
72 [[deprecated("Use InterfaceDescription for initializing the Interface")]]
73 Handle(const std::string & prefix_name, const std::string & interface_name, double * value_ptr)
74 : prefix_name_(prefix_name),
75 interface_name_(interface_name),
76 handle_name_(prefix_name_ + "/" + interface_name_),
77 value_ptr_(value_ptr)
78 {
79 }
80
81 explicit Handle(
82 const std::string & prefix_name, const std::string & interface_name,
83 const std::string & data_type = "double", const std::string & initial_value = "")
84 : prefix_name_(prefix_name),
85 interface_name_(interface_name),
86 handle_name_(prefix_name_ + "/" + interface_name_),
87 data_type_(data_type)
88 {
89 // we need to initialize according the type passed in interface description
90 if (data_type_ == hardware_interface::HandleDataType::DOUBLE)
91 {
92 try
93 {
94 value_ = initial_value.empty() ? std::numeric_limits<double>::quiet_NaN()
95 : hardware_interface::stod(initial_value);
96 value_ptr_ = std::get_if<double>(&value_);
97 }
98 catch (const std::invalid_argument & err)
99 {
100 throw std::invalid_argument(
101 fmt::format(
102 FMT_COMPILE(
103 "Invalid initial value : '{}' parsed for interface : '{}' with type : '{}'"),
104 initial_value, handle_name_, data_type_.to_string()));
105 }
106 }
107 else if (data_type_ == hardware_interface::HandleDataType::FLOAT32)
108 {
109 try
110 {
111 value_ptr_ = nullptr;
112 value_ = initial_value.empty()
113 ? std::numeric_limits<float>::quiet_NaN()
114 : static_cast<float>(hardware_interface::stof(initial_value));
115 }
116 catch (const std::invalid_argument & err)
117 {
118 throw std::invalid_argument(
119 fmt::format(
120 FMT_COMPILE("Invalid initial value: '{}' parsed for interface: '{}' with type: '{}'"),
121 initial_value, handle_name_, data_type_.to_string()));
122 }
123 }
124 else if (data_type_ == hardware_interface::HandleDataType::BOOL)
125 {
126 try
127 {
128 value_ptr_ = nullptr;
129 value_ = initial_value.empty() ? false : hardware_interface::parse_bool(initial_value);
130 }
131 catch (const std::invalid_argument & err)
132 {
133 throw std::invalid_argument(
134 fmt::format(
135 FMT_COMPILE("Invalid initial value: '{}' parsed for interface: '{}' with type: '{}'"),
136 initial_value, handle_name_, data_type_.to_string()));
137 }
138 }
139 else if (data_type_ == hardware_interface::HandleDataType::UINT8)
140 {
141 try
142 {
143 value_ptr_ = nullptr;
144 value_ = initial_value.empty()
145 ? static_cast<uint8_t>(std::numeric_limits<uint8_t>::max())
146 : static_cast<uint8_t>(hardware_interface::stoui8(initial_value));
147 }
148 catch (const std::invalid_argument & err)
149 {
150 throw std::invalid_argument(
151 fmt::format(
152 FMT_COMPILE("Invalid initial value: '{}' parsed for interface: '{}' with type: '{}'"),
153 initial_value, handle_name_, data_type_.to_string()));
154 }
155 }
156 else if (data_type_ == hardware_interface::HandleDataType::INT8)
157 {
158 try
159 {
160 value_ptr_ = nullptr;
161 value_ = initial_value.empty()
162 ? static_cast<int8_t>(std::numeric_limits<int8_t>::max())
163 : static_cast<int8_t>(hardware_interface::stoi8(initial_value));
164 }
165 catch (const std::invalid_argument & err)
166 {
167 throw std::invalid_argument(
168 fmt::format(
169 FMT_COMPILE("Invalid initial value: '{}' parsed for interface: '{}' with type: '{}'"),
170 initial_value, handle_name_, data_type_.to_string()));
171 }
172 }
173 else if (data_type_ == hardware_interface::HandleDataType::UINT16)
174 {
175 try
176 {
177 value_ptr_ = nullptr;
178 value_ = initial_value.empty()
179 ? static_cast<uint16_t>(std::numeric_limits<uint16_t>::max())
180 : static_cast<uint16_t>(hardware_interface::stoui16(initial_value));
181 }
182 catch (const std::invalid_argument & err)
183 {
184 throw std::invalid_argument(
185 fmt::format(
186 FMT_COMPILE("Invalid initial value: '{}' parsed for interface: '{}' with type: '{}'"),
187 initial_value, handle_name_, data_type_.to_string()));
188 }
189 }
190 else if (data_type_ == hardware_interface::HandleDataType::INT16)
191 {
192 try
193 {
194 value_ptr_ = nullptr;
195 value_ = initial_value.empty()
196 ? static_cast<int16_t>(std::numeric_limits<int16_t>::max())
197 : static_cast<int16_t>(hardware_interface::stoi16(initial_value));
198 }
199 catch (const std::invalid_argument & err)
200 {
201 throw std::invalid_argument(
202 fmt::format(
203 FMT_COMPILE("Invalid initial value: '{}' parsed for interface: '{}' with type: '{}'"),
204 initial_value, handle_name_, data_type_.to_string()));
205 }
206 }
207 else if (data_type_ == hardware_interface::HandleDataType::UINT32)
208 {
209 try
210 {
211 value_ptr_ = nullptr;
212 value_ = initial_value.empty()
213 ? static_cast<uint32_t>(std::numeric_limits<uint32_t>::max())
214 : static_cast<uint32_t>(hardware_interface::stoui32(initial_value));
215 }
216 catch (const std::invalid_argument & err)
217 {
218 throw std::invalid_argument(
219 fmt::format(
220 FMT_COMPILE("Invalid initial value: '{}' parsed for interface: '{}' with type: '{}'"),
221 initial_value, handle_name_, data_type_.to_string()));
222 }
223 }
224 else if (data_type_ == hardware_interface::HandleDataType::INT32)
225 {
226 try
227 {
228 value_ptr_ = nullptr;
229 value_ = initial_value.empty()
230 ? static_cast<int32_t>(std::numeric_limits<int32_t>::max())
231 : static_cast<int32_t>(hardware_interface::stoi32(initial_value));
232 }
233 catch (const std::invalid_argument & err)
234 {
235 throw std::invalid_argument(
236 fmt::format(
237 FMT_COMPILE("Invalid initial value: '{}' parsed for interface: '{}' with type: '{}'"),
238 initial_value, handle_name_, data_type_.to_string()));
239 }
240 }
241 else
242 {
243 throw std::runtime_error(
244 fmt::format(
245 FMT_COMPILE("Invalid data type: '{}' for interface: {}. Check supported types."),
246 data_type, handle_name_));
247 }
248 }
249
250 explicit Handle(const InterfaceDescription & interface_description)
251 : Handle(
252 interface_description.get_prefix_name(), interface_description.get_interface_name(),
253 interface_description.get_data_type_string(),
254 interface_description.interface_info.initial_value)
255 {
256 }
257
258 [[deprecated("Use InterfaceDescription for initializing the Interface")]]
259
260 explicit Handle(const std::string & interface_name)
261 : interface_name_(interface_name), handle_name_("/" + interface_name_), value_ptr_(nullptr)
262 {
263 }
264
265 [[deprecated("Use InterfaceDescription for initializing the Interface")]]
266
267 explicit Handle(const char * interface_name)
268 : interface_name_(interface_name), handle_name_("/" + interface_name_), value_ptr_(nullptr)
269 {
270 }
271
272 Handle(const Handle & other) noexcept { copy(other); }
273
274 Handle & operator=(const Handle & other)
275 {
276 if (this != &other)
277 {
278 copy(other);
279 }
280 return *this;
281 }
282
283 Handle(Handle && other) noexcept { swap(*this, other); }
284
285 Handle & operator=(Handle && other)
286 {
287 swap(*this, other);
288 return *this;
289 }
290
291 virtual ~Handle() = default;
292
294 inline operator bool() const { return value_ptr_ != nullptr; }
295
296 const std::string & get_name() const { return handle_name_; }
297
298 const std::string & get_interface_name() const { return interface_name_; }
299
300 [[deprecated(
301 "Replaced by get_name method, which is semantically more correct")]] const std::string &
302 get_full_name() const
303 {
304 return get_name();
305 }
306
307 const std::string & get_prefix_name() const { return prefix_name_; }
308
309 [[deprecated(
310 "Use std::optional<T> get_optional() instead to retrieve the value. This method will be "
311 "removed by the ROS 2 Kilted Kaiju release.")]]
312 double get_value() const
313 {
314 std::shared_lock<std::shared_mutex> lock(handle_mutex_, std::try_to_lock);
315 if (!lock.owns_lock())
316 {
317 return std::numeric_limits<double>::quiet_NaN();
318 }
319 // BEGIN (Handle export change): for backward compatibility
320 // TODO(Manuel) return value_ if old functionality is removed
321 THROW_ON_NULLPTR(value_ptr_);
322 return *value_ptr_;
323 // END
324 }
325
336 template <typename T = double>
337 [[nodiscard]] std::optional<T> get_optional() const
338 {
339 std::shared_lock<std::shared_mutex> lock(handle_mutex_, std::try_to_lock);
340 return get_optional<T>(lock);
341 }
353 template <typename T = double>
354 [[nodiscard]] std::optional<T> get_optional(std::shared_lock<std::shared_mutex> & lock) const
355 {
356 if (!lock.owns_lock())
357 {
358 return std::nullopt;
359 }
360 // BEGIN (Handle export change): for backward compatibility
361 // TODO(saikishor) return value_ if old functionality is removed
362 if constexpr (std::is_same_v<T, double>)
363 {
364 switch (data_type_)
365 {
366 case HandleDataType::DOUBLE:
367 THROW_ON_NULLPTR(value_ptr_);
368 return *value_ptr_;
369 case HandleDataType::BOOL: // fallthrough
370 case HandleDataType::FLOAT32: // fallthrough
371 case HandleDataType::UINT8: // fallthrough
372 case HandleDataType::INT8: // fallthrough
373 case HandleDataType::UINT16: // fallthrough
374 case HandleDataType::INT16: // fallthrough
375 case HandleDataType::UINT32: // fallthrough
376 case HandleDataType::INT32: // fallthrough
377 throw std::runtime_error(
378 fmt::format(
379 FMT_COMPILE(
380 "Data type: '{}' will not be casted to double for interface: {}. Use "
381 "get_optional<{}>() instead."),
382 data_type_.to_string(), get_name(), data_type_.to_string()));
383 default:
384 throw std::runtime_error(
385 fmt::format(
386 FMT_COMPILE("Data type: '{}' cannot be casted to double for interface: {}"),
387 data_type_.to_string(), get_name()));
388 }
389 }
390 try
391 {
392 return std::get<T>(value_);
393 }
394 catch (const std::bad_variant_access & err)
395 {
396 throw std::runtime_error(
397 fmt::format(
398 FMT_COMPILE("Invalid data type : '{}' access for interface : {} expected : '{}'"),
399 get_type_name<T>(), get_name(), data_type_.to_string()));
400 }
401 // END
402 }
403
415 template <typename T>
416 [[deprecated(
417 "Use std::optional<T> get_optional() instead to retrieve the value. This method will be "
418 "removed by the ROS 2 Kilted Kaiju release.")]] [[nodiscard]] bool
419 get_value(T & value) const
420 {
421 std::shared_lock<std::shared_mutex> lock(handle_mutex_, std::try_to_lock);
422 if (!lock.owns_lock())
423 {
424 return false;
425 }
426 // BEGIN (Handle export change): for backward compatibility
427 // TODO(Manuel) return value_ if old functionality is removed
428 if constexpr (std::is_same_v<T, double>)
429 {
430 // If the template is of type double, check if the value_ptr_ is not nullptr
431 THROW_ON_NULLPTR(value_ptr_);
432 value = *value_ptr_;
433 }
434 else
435 {
436 try
437 {
438 value = std::get<T>(value_);
439 }
440 catch (const std::bad_variant_access & err)
441 {
442 throw std::runtime_error(
443 fmt::format(
444 FMT_COMPILE("Invalid data type : '{}' access for interface : {} expected : '{}'"),
445 get_type_name<T>(), get_name(), data_type_.to_string()));
446 }
447 }
448 return true;
449 // END
450 }
451
464 template <
465 typename T, typename = std::enable_if_t<
466 !std::is_same_v<std::decay_t<T>, std::shared_lock<std::shared_mutex>>>>
467 [[nodiscard]] bool get_value(T & value, bool wait_for_lock) const
468 {
469 if (wait_for_lock)
470 {
471 std::shared_lock<std::shared_mutex> lock(handle_mutex_);
472 return get_value(lock, value);
473 }
474 else
475 {
476 std::shared_lock<std::shared_mutex> lock(handle_mutex_, std::try_to_lock);
477 return get_value(lock, value);
478 }
479 }
480
492 template <typename T>
493 [[nodiscard]] bool set_value(const T & value, bool wait_for_lock)
494 {
495 if (wait_for_lock)
496 {
497 std::unique_lock<std::shared_mutex> lock(handle_mutex_);
498 return set_value(lock, value);
499 }
500 else
501 {
502 std::unique_lock<std::shared_mutex> lock(handle_mutex_, std::try_to_lock);
503 return set_value(lock, value);
504 }
505 }
506
518 template <typename T>
519 [[nodiscard]] bool set_value(const T & value)
520 {
521 std::unique_lock<std::shared_mutex> lock(handle_mutex_, std::try_to_lock);
522 return set_value(lock, value);
523 }
524
537 template <typename T>
538 [[nodiscard]] bool set_value(std::unique_lock<std::shared_mutex> & lock, const T & value)
539 {
540 if (!lock.owns_lock())
541 {
542 return false;
543 }
544 // BEGIN (Handle export change): for backward compatibility
545 // TODO(Manuel) set value_ directly if old functionality is removed
546 if constexpr (std::is_same_v<T, double>)
547 {
548 // If the template is of type double, check if the value_ptr_ is not nullptr
549 THROW_ON_NULLPTR(value_ptr_);
550 *value_ptr_ = value;
551 }
552 else
553 {
554 if (!std::holds_alternative<T>(value_))
555 {
556 throw std::runtime_error(
557 fmt::format(
558 FMT_COMPILE("Invalid data type : '{}' access for interface : {} expected : '{}'"),
559 get_type_name<T>(), get_name(), data_type_.to_string()));
560 }
561 value_ = value;
562 }
563 return true;
564 // END
565 }
566
567 std::shared_mutex & get_mutex() const { return handle_mutex_; }
568
569 HandleDataType get_data_type() const { return data_type_; }
570
572 bool is_castable_to_double() const { return data_type_.is_castable_to_double(); }
573
574 bool is_valid() const
575 {
576 return (value_ptr_ != nullptr) || !std::holds_alternative<std::monostate>(value_);
577 }
578
579protected:
589 template <typename T>
590 [[nodiscard]] bool get_value(std::shared_lock<std::shared_mutex> & lock, T & value) const
591 {
592 if (!lock.owns_lock())
593 {
594 return false;
595 }
596 // BEGIN (Handle export change): for backward compatibility
597 // TODO(saikishor) get value_ if old functionality is removed
598 if constexpr (std::is_same_v<T, double>)
599 {
600 switch (data_type_)
601 {
602 case HandleDataType::DOUBLE:
603 THROW_ON_NULLPTR(value_ptr_);
604 value = *value_ptr_;
605 return true;
606 case HandleDataType::BOOL: // fallthrough
607 case HandleDataType::FLOAT32: // fallthrough
608 case HandleDataType::UINT8: // fallthrough
609 case HandleDataType::INT8: // fallthrough
610 case HandleDataType::UINT16: // fallthrough
611 case HandleDataType::INT16: // fallthrough
612 case HandleDataType::UINT32: // fallthrough
613 case HandleDataType::INT32: // fallthrough
614 throw std::runtime_error(
615 fmt::format(
616 FMT_COMPILE(
617 "Data type: '{}' will not be casted to double for interface: {}. Use "
618 "get_optional<{}>() instead."),
619 data_type_.to_string(), get_name(), data_type_.to_string()));
620 default:
621 throw std::runtime_error(
622 fmt::format(
623 FMT_COMPILE("Data type: '{}' cannot be casted to double for interface: {}"),
624 data_type_.to_string(), get_name()));
625 }
626 }
627 try
628 {
629 value = std::get<T>(value_);
630 return true;
631 }
632 catch (const std::bad_variant_access & err)
633 {
634 throw std::runtime_error(
635 fmt::format(
636 FMT_COMPILE("Invalid data type: '{}' access for interface: {} expected: '{}'"),
637 get_type_name<T>(), get_name(), data_type_.to_string()));
638 }
639 }
640
641private:
642 void copy(const Handle & other) noexcept
643 {
644 std::scoped_lock lock(other.handle_mutex_, handle_mutex_);
646 interface_name_ = other.interface_name_;
647 handle_name_ = other.handle_name_;
648 value_ = other.value_;
649 data_type_ = other.data_type_;
650 if (std::holds_alternative<std::monostate>(value_))
651 {
652 value_ptr_ = other.value_ptr_;
653 }
654 else
655 {
656 value_ptr_ = std::get_if<double>(&value_);
657 }
658 }
659
660 void swap(Handle & first, Handle & second) noexcept
661 {
662 std::scoped_lock lock(first.handle_mutex_, second.handle_mutex_);
663 std::swap(first.prefix_name_, second.prefix_name_);
664 std::swap(first.interface_name_, second.interface_name_);
665 std::swap(first.handle_name_, second.handle_name_);
666 std::swap(first.value_, second.value_);
667 std::swap(first.data_type_, second.data_type_);
668 std::swap(first.value_ptr_, second.value_ptr_);
669 }
670
671protected:
673 std::string prefix_name_;
674 std::string interface_name_;
675 std::string handle_name_;
676 HANDLE_DATATYPE value_ = std::monostate{};
677 HandleDataType data_type_ = HandleDataType::DOUBLE;
678 // BEGIN (Handle export change): for backward compatibility
679 // TODO(Manuel) redeclare as HANDLE_DATATYPE * value_ptr_ if old functionality is removed
680 double * value_ptr_ = nullptr;
681 // END
682 mutable std::shared_mutex handle_mutex_;
683};
684
685class StateInterface : public Handle
686{
687public:
688 explicit StateInterface(const InterfaceDescription & interface_description)
689 : Handle(interface_description)
690 {
691 }
692
693 void registerIntrospection() const
694 {
695 if (!is_valid())
696 {
697 RCLCPP_WARN(
698 rclcpp::get_logger(get_name()),
699 "Cannot register state introspection for state interface: %s without a valid value "
700 "pointer or initialized value.",
701 get_name().c_str());
702 return;
703 }
704 if (value_ptr_ || data_type_.is_castable_to_double())
705 {
706 std::function<double()> f = [this]()
707 {
708 if (value_ptr_)
709 {
710 return *value_ptr_;
711 }
712 else
713 {
714 return data_type_.cast_to_double(value_);
715 }
716 };
717 DEFAULT_REGISTER_ROS2_CONTROL_INTROSPECTION("state_interface." + get_name(), f);
718 }
719 }
720
721 void unregisterIntrospection() const
722 {
723 if (is_valid() && (value_ptr_ || data_type_.is_castable_to_double()))
724 {
725 DEFAULT_UNREGISTER_ROS2_CONTROL_INTROSPECTION("state_interface." + get_name());
726 }
727 }
728
729 StateInterface(const StateInterface & other) = default;
730
731 StateInterface(StateInterface && other) = default;
732
733// Disable deprecated warnings
734#pragma GCC diagnostic push
735#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
736 using Handle::Handle;
737#pragma GCC diagnostic pop
738
739 using SharedPtr = std::shared_ptr<StateInterface>;
740 using ConstSharedPtr = std::shared_ptr<const StateInterface>;
741};
742
744{
745public:
746 explicit CommandInterface(const InterfaceDescription & interface_description)
747 : Handle(interface_description)
748 {
749 }
751
756 CommandInterface(const CommandInterface & other) = delete;
757
758 CommandInterface(CommandInterface && other) = default;
759
760 void set_on_set_command_limiter(std::function<double(double, bool &)> on_set_command_limiter)
761 {
762 on_set_command_limiter_ = on_set_command_limiter;
763 }
764
766
770 template <typename T>
771 [[nodiscard]] bool set_limited_value(const T & value)
772 {
773 if constexpr (std::is_same_v<T, double>)
774 {
775 return set_value(on_set_command_limiter_(value, is_command_limited_));
776 }
777 else
778 {
779 return set_value(value);
780 }
781 }
782
783 const bool & is_limited() const { return is_command_limited_; }
784
785 void registerIntrospection() const
786 {
787 if (!is_valid())
788 {
789 RCLCPP_WARN(
790 rclcpp::get_logger(get_name()),
791 "Cannot register command introspection for command interface: %s without a valid value "
792 "pointer or initialized value.",
793 get_name().c_str());
794 return;
795 }
796 if (value_ptr_ || data_type_.is_castable_to_double())
797 {
798 std::function<double()> f = [this]()
799 {
800 if (value_ptr_)
801 {
802 return *value_ptr_;
803 }
804 else
805 {
806 return data_type_.cast_to_double(value_);
807 }
808 };
809 DEFAULT_REGISTER_ROS2_CONTROL_INTROSPECTION("command_interface." + get_name(), f);
810 DEFAULT_REGISTER_ROS2_CONTROL_INTROSPECTION(
811 "command_interface." + get_name() + ".is_limited", &is_command_limited_);
812 }
813 }
814
815 void unregisterIntrospection() const
816 {
817 if (is_valid() && (value_ptr_ || data_type_.is_castable_to_double()))
818 {
819 DEFAULT_UNREGISTER_ROS2_CONTROL_INTROSPECTION("command_interface." + get_name());
820 DEFAULT_UNREGISTER_ROS2_CONTROL_INTROSPECTION(
821 "command_interface." + get_name() + ".is_limited");
822 }
823 }
824
825// Disable deprecated warnings
826#pragma GCC diagnostic push
827#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
828 using Handle::Handle;
829#pragma GCC diagnostic pop
830
831 using SharedPtr = std::shared_ptr<CommandInterface>;
832
833private:
834 bool is_command_limited_ = false;
835 std::function<double(double, bool &)> on_set_command_limiter_ =
836 [](double value, bool & is_limited)
837 {
838 is_limited = false;
839 return value;
840 };
841};
842
843} // namespace hardware_interface
844
845#endif // HARDWARE_INTERFACE__HANDLE_HPP_
Definition handle.hpp:744
bool set_limited_value(const T &value)
A setter for the value of the command interface that triggers the limiter.
Definition handle.hpp:771
CommandInterface(const CommandInterface &other)=delete
CommandInterface copy constructor is actively deleted.
Definition hardware_info.hpp:158
bool is_castable_to_double() const
Check if the HandleDataType can be casted to double.
Definition hardware_info.hpp:262
double cast_to_double(const HANDLE_DATATYPE &value) const
Cast the given value to double.
Definition hardware_info.hpp:288
A handle used to get and set a value on a given interface.
Definition handle.hpp:70
bool set_value(const T &value)
Set the value of the handle.
Definition handle.hpp:519
bool get_value(T &value) const
Get the value of the handle.
Definition handle.hpp:419
bool get_value(std::shared_lock< std::shared_mutex > &lock, T &value) const
Get the value of the handle.
Definition handle.hpp:590
std::optional< T > get_optional(std::shared_lock< std::shared_mutex > &lock) const
Get the value of the handle.
Definition handle.hpp:354
bool get_value(T &value, bool wait_for_lock) const
Get the value of the handle.
Definition handle.hpp:467
bool is_castable_to_double() const
Returns true if the handle data type can be casted to double.
Definition handle.hpp:572
std::string prefix_name_
Definition handle.hpp:673
bool set_value(std::unique_lock< std::shared_mutex > &lock, const T &value)
Set the value of the handle.
Definition handle.hpp:538
bool set_value(const T &value, bool wait_for_lock)
Set the value of the handle.
Definition handle.hpp:493
std::optional< T > get_optional() const
Get the value of the handle.
Definition handle.hpp:337
Definition handle.hpp:686
Definition mujoco_system_interface.hpp:57
std::variant< std::monostate, double, float, bool, uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t > HANDLE_DATATYPE
Definition hardware_info.hpp:156
float stof(const std::string &s)
Helper function to convert a std::string to float in a locale-independent way.
Definition lexical_casts.cpp:116
double stod(const std::string &s)
Helper function to convert a std::string to double in a locale-independent way.
Definition lexical_casts.cpp:107
bool parse_bool(const std::string &bool_string)
Parse a boolean value from a string.
Definition lexical_casts.cpp:134
Definition hardware_info.hpp:327
InterfaceInfo interface_info
Definition hardware_info.hpp:343
std::string initial_value
(Optional) Initial value of the interface.
Definition hardware_info.hpp:55