ros2_canopen master
C++ ROS CANopen Library
Loading...
Searching...
No Matches
lely_driver_bridge.hpp
Go to the documentation of this file.
1// Copyright 2022 Christoph Hellmann Santos
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 CANOPEN_BASE_DRIVER__LELY_BRIDGE_HPP_
16#define CANOPEN_BASE_DRIVER__LELY_BRIDGE_HPP_
17
18#include <sys/stat.h>
19
20#include <lely/co/dcf.hpp>
21#include <lely/co/dev.hpp>
22#include <lely/co/obj.hpp>
23#include <lely/coapp/fiber_driver.hpp>
24#include <lely/coapp/master.hpp>
25#include <lely/coapp/sdo_error.hpp>
26#include <lely/ev/co_task.hpp>
27#include <lely/ev/future.hpp>
28
29#include <atomic>
30#include <condition_variable>
31#include <future>
32#include <memory>
33#include <mutex>
34#include <rclcpp/rclcpp.hpp>
35#include <string>
36#include <system_error>
37#include <thread>
38#include <vector>
39
40#include <boost/lockfree/queue.hpp>
41#include <boost/optional.hpp>
42#include <boost/thread.hpp>
43
45
46using namespace std::chrono_literals;
47using namespace lely;
48
49namespace ros2_canopen
50{
52{
53 bool is_tpdo;
54 bool is_rpdo;
55};
56
57typedef std::map<uint16_t, std::map<uint8_t, pdo_mapping>> PDOMap;
58class DriverDictionary : public lely::CODev
59{
60public:
61 DriverDictionary(std::string eds_file) : lely::CODev(eds_file.c_str()) {}
63 {
64 // lely::CODev::~CODev();
65 }
66
67 std::shared_ptr<PDOMap> createPDOMapping()
68 {
69 std::shared_ptr<PDOMap> pdo_map = std::make_shared<PDOMap>();
70 fetchRPDO(pdo_map);
71 fetchTPDO(pdo_map);
72 return pdo_map;
73 // COObj * first = co_dev_first_obj((lely::CODev *)this);
74 // COObj * last = co_dev_last_obj((lely::CODev *)this);
75 // if (first == nullptr || last == nullptr)
76 // {
77 // std::cout << "No objects found in dictionary" << std::endl;
78 // return pdo_map;
79 // }
80 // COObj * current = first;
81 // while (current != last)
82 // {
83 // uint16_t index = co_obj_get_idx(current);
84 // auto subids = current->getSubidx();
85 // bool created = false;
86 // for (auto subid : subids)
87 // {
88 // bool is_rpdo = checkObjRPDO(index, subid);
89 // bool is_tpdo = checkObjTPDO(index, subid);
90 // std::cout << "Found subobject: index=" << std::hex << (int)index
91 // << " subindex=" << (int)subid << (is_rpdo ? " rpdo" : "")
92 // << (is_tpdo ? " tpdo" : "") << std::endl;
93 // if (is_rpdo || is_tpdo)
94 // {
95 // pdo_mapping mapping;
96 // mapping.is_rpdo = is_rpdo;
97 // mapping.is_tpdo = is_tpdo;
98 // if (!created)
99 // {
100 // pdo_map->emplace(index, std::map<uint8_t, pdo_mapping>());
101 // created = true;
102 // }
103 // (*pdo_map)[index].emplace(subid, mapping);
104 // }
105 // }
106 // current = co_obj_next(current);
107 // }
108 // return pdo_map;
109 }
110
111 void fetchRPDO(std::shared_ptr<PDOMap> map)
112 {
113 for (int index = 0; index < 256; index++)
114 {
115 for (int subindex = 1; subindex < 9; subindex++)
116 {
117 auto obj = find(0x1600 + index, subindex);
118 if (obj == nullptr)
119 {
120 continue;
121 }
122 uint32_t data;
123 {
124 data = obj->getVal<CO_DEFTYPE_UNSIGNED32>();
125 }
126 uint8_t tmps = (data >> 8) & 0xFF;
127 uint16_t tmpi = (data >> 16) & 0xFFFF;
128 if (tmpi == 0U)
129 {
130 continue;
131 }
132 pdo_mapping mapping;
133 mapping.is_rpdo = true;
134 mapping.is_tpdo = false;
135 (*map)[tmpi][tmps] = mapping;
136 std::cout << "Found rpdo mapped object: index=" << std::hex << (int)tmpi
137 << " subindex=" << (int)tmps << std::endl;
138 }
139 }
140 }
141 void fetchTPDO(std::shared_ptr<PDOMap> map)
142 {
143 for (int index = 0; index < 256; index++)
144 {
145 for (int subindex = 1; subindex < 9; subindex++)
146 {
147 auto obj = find(0x1A00 + index, subindex);
148 if (obj == nullptr)
149 {
150 continue;
151 }
152 uint32_t data;
153 {
154 data = obj->getVal<CO_DEFTYPE_UNSIGNED32>();
155 }
156 uint8_t tmps = (data >> 8) & 0xFF;
157 uint16_t tmpi = (data >> 16) & 0xFFFF;
158 if (tmpi == 0U)
159 {
160 continue;
161 }
162
163 pdo_mapping mapping;
164 mapping.is_rpdo = false;
165 mapping.is_tpdo = true;
166 (*map)[tmpi][tmps] = mapping;
167 std::cout << "Found tpdo mapped object: index=" << std::hex << (int)tmpi
168 << " subindex=" << (int)tmps << std::endl;
169 }
170 }
171 }
172
173 bool checkObjRPDO(uint16_t idx, uint8_t subidx)
174 {
175 // std::cout << "Checking for rpo mapping of object: index=" << std::hex << (int)idx
176 // << " subindex=" << (int)subidx << std::endl;
177 for (int i = 0; i < 256; i++)
178 {
179 if (this->checkObjInPDO(i, 0x1600, idx, subidx))
180 {
181 return true;
182 }
183 }
184 return false;
185 }
186
187 bool checkObjTPDO(uint16_t idx, uint8_t subidx)
188 {
189 // std::cout << "Checking for rpo mapping of object: index=" << std::hex << (int)idx
190 // << " subindex=" << (int)subidx << std::endl;
191 for (int i = 0; i < 256; i++)
192 {
193 if (this->checkObjInPDO(i, 0x1A00, idx, subidx))
194 {
195 return true;
196 }
197 }
198 return false;
199 }
200
201 bool checkObjInPDO(uint8_t pdo, uint16_t mapping_idx, uint16_t idx, uint8_t subindex)
202 {
203 for (int i = 1; i < 9; i++)
204 {
205 auto obj = find(mapping_idx + pdo, i);
206 if (obj == nullptr)
207 {
208 return false;
209 }
210 uint32_t data;
211 {
212 data = obj->getVal<CO_DEFTYPE_UNSIGNED32>();
213 }
214 uint8_t tmps = (data >> 8) & 0xFF;
215 uint16_t tmpi = (data >> 16) & 0xFFFF;
216
217 if (tmps == subindex && tmpi == idx)
218 {
219 std::cout << "Found object in pdo: " << (int)pdo << std::endl;
220 return true;
221 }
222 }
223
224 return false;
225 }
226};
227
247
248struct LelyBridgeErrCategory : std::error_category
249{
250 const char * name() const noexcept override;
251 std::string message(int ev) const override;
252};
253} // namespace ros2_canopen
254
255namespace std
256{
257template <>
258struct is_error_code_enum<ros2_canopen::LelyBridgeErrc> : true_type
259{
260};
262} // namespace std
263
264namespace ros2_canopen
265{
276class LelyDriverBridge : public canopen::FiberDriver
277{
278protected:
279 // Dictionary for driver based on DCF and BIN files.
280 std::unique_ptr<DriverDictionary> dictionary_;
282 std::shared_ptr<PDOMap> pdo_map_;
283
284 // SDO Read synchronisation items
285 std::shared_ptr<std::promise<COData>> sdo_read_data_promise;
286 std::shared_ptr<std::promise<bool>> sdo_write_data_promise;
287 std::mutex sdo_mutex;
289 std::condition_variable sdo_cond;
290
291 // NMT synchronisation items
292 std::promise<canopen::NmtState> nmt_state_promise;
293 std::atomic<bool> nmt_state_is_set;
294 std::mutex nmt_mtex;
295
296 // RPDO synchronisation items
297 std::promise<COData> rpdo_promise;
298 std::atomic<bool> rpdo_is_set;
299 std::mutex pdo_mtex;
300 std::shared_ptr<SafeQueue<COData>> rpdo_queue;
301
302 // EMCY synchronisation items
303 std::promise<COEmcy> emcy_promise;
304 std::atomic<bool> emcy_is_set;
305 std::mutex emcy_mtex;
306 std::shared_ptr<SafeQueue<COEmcy>> emcy_queue;
307
308 // BOOT synchronisation items
309 std::atomic<bool> booted;
311 std::string boot_what;
312 canopen::NmtState boot_state;
313 std::condition_variable boot_cond;
314 std::mutex boot_mtex;
315 std::chrono::milliseconds boot_timeout_;
316
317 uint8_t nodeid;
318 std::string name_;
319
320 std::chrono::milliseconds sdo_timeout;
321
322 std::function<void()> on_sync_function_;
323
324 // void set_sync_function(std::function<void()> on_sync_function)
325 // {
326 // on_sync_function_ = on_sync_function;
327 // }
328
329 // void unset_sync_function()
330 // {
331 // on_sync_function_ = std::function<void()>();
332 // }
333
334 void OnSync(uint8_t cnt, const time_point & t) noexcept override
335 {
336 if (on_sync_function_ != nullptr)
337 {
338 try
339 {
340 on_sync_function_();
341 }
342 catch (...)
343 {
344 }
345 }
346 }
347
356 void OnState(canopen::NmtState state) noexcept override;
357
368 virtual void OnBoot(canopen::NmtState st, char es, const ::std::string & what) noexcept override;
369
380 void OnRpdoWrite(uint16_t idx, uint8_t subidx) noexcept override;
381
390 void OnEmcy(uint16_t eec, uint8_t er, uint8_t msef[5]) noexcept override;
391
392 // void OnConfig(::std::function<void(::std::error_code ec)> res) noexcept override;
393
394public:
395 using FiberDriver::FiberDriver;
396
409 ev_exec_t * exec, canopen::AsyncMaster & master, uint8_t id, std::string name, std::string eds,
410 std::string bin, std::chrono::milliseconds timeout = 20ms,
411 std::chrono::milliseconds boot_timeout = 20ms)
412 : FiberDriver(exec, master, id),
413 rpdo_queue(new SafeQueue<COData>()),
414 emcy_queue(new SafeQueue<COEmcy>())
415 {
416 nodeid = id;
417 running = false;
418 name_ = name;
419 dictionary_ = std::make_unique<DriverDictionary>(eds.c_str());
420 struct stat buffer;
421 if (stat(bin.c_str(), &buffer) == 0)
422 {
423 co_unsigned16_t * a = NULL;
424 co_unsigned16_t * b = NULL;
425 dictionary_->readDCF(a, b, bin.c_str());
426 }
427 pdo_map_ = dictionary_->createPDOMapping();
428 sdo_timeout = timeout;
429 boot_timeout_ = boot_timeout;
430 }
431
445 std::future<bool> async_sdo_write(COData data);
446
447 template <typename T>
448 std::future<bool> async_sdo_write_typed(uint16_t idx, uint8_t subidx, T value)
449 {
450 std::unique_lock<std::mutex> lck(sdo_mutex);
451 if (running)
452 {
453 sdo_cond.wait(lck);
454 }
455 running = true;
456
457 auto prom = std::make_shared<std::promise<bool>>();
458 lely::COSub * sub = this->dictionary_->find(idx, subidx);
459 if (sub == nullptr)
460 {
461 std::cout << "async_sdo_write_typed: id=" << (unsigned int)this->get_id() << " index=0x"
462 << std::hex << (unsigned int)idx << " subindex=" << (unsigned int)subidx
463 << " object does not exist" << std::endl;
464 prom->set_value(false);
465 this->running = false;
466 this->sdo_cond.notify_one();
467 return prom->get_future();
468 }
469
470 this->SubmitWrite(
471 idx, subidx, value,
472 [this, value, prom](uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec) mutable
473 {
474 if (ec)
475 {
476 prom->set_exception(
477 lely::canopen::make_sdo_exception_ptr(id, idx, subidx, ec, "AsyncDownload"));
478 }
479 else
480 {
481 std::scoped_lock<std::mutex> lck(this->dictionary_mutex_);
482 this->dictionary_->setVal<T>(idx, subidx, value);
483 prom->set_value(true);
484 }
485 std::unique_lock<std::mutex> lck(this->sdo_mutex);
486 this->running = false;
487 this->sdo_cond.notify_one();
488 },
489 this->sdo_timeout);
490 return prom->get_future();
491 }
492
493 template <typename T>
495 uint16_t idx, uint8_t subidx, T value, std::chrono::milliseconds timeout)
496 {
497 auto fut = async_sdo_write_typed(idx, subidx, value);
498 auto wait_res = fut.wait_for(timeout);
499 if (wait_res == std::future_status::timeout)
500 {
501 std::cout << "sync_sdo_write_typed: id=" << (unsigned int)this->get_id() << " index=0x"
502 << std::hex << (unsigned int)idx << " subindex=" << (unsigned int)subidx
503 << " timed out." << std::endl;
504 return false;
505 }
506 bool res = false;
507 try
508 {
509 res = fut.get();
510 }
511 catch (std::exception & e)
512 {
513 RCLCPP_ERROR(rclcpp::get_logger(name_), e.what());
514 }
515 return res;
516 }
517
531 std::future<COData> async_sdo_read(COData data);
532
533 template <typename T>
534 std::future<T> async_sdo_read_typed(uint16_t idx, uint8_t subidx)
535 {
536 std::unique_lock<std::mutex> lck(sdo_mutex);
537 if (running)
538 {
539 sdo_cond.wait(lck);
540 }
541 running = true;
542
543 auto prom = std::make_shared<std::promise<T>>();
544 lely::COSub * sub = this->dictionary_->find(idx, subidx);
545 if (sub == nullptr)
546 {
547 std::cout << "async_sdo_read: id=" << (unsigned int)this->get_id() << " index=0x" << std::hex
548 << (unsigned int)idx << " subindex=" << (unsigned int)subidx
549 << " object does not exist" << std::endl;
550 try
551 {
552 throw lely::canopen::SdoError(this->get_id(), idx, subidx, lely::canopen::SdoErrc::NO_OBJ);
553 }
554 catch (...)
555 {
556 prom->set_exception(std::current_exception());
557 }
558 this->running = false;
559 this->sdo_cond.notify_one();
560 return prom->get_future();
561 }
562 this->SubmitRead<T>(
563 idx, subidx,
564 [this, prom](uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec, T value) mutable
565 {
566 if (ec)
567 {
568 prom->set_exception(
569 lely::canopen::make_sdo_exception_ptr(id, idx, subidx, ec, "AsyncUpload"));
570 }
571 else
572 {
573 std::scoped_lock<std::mutex> lck(this->dictionary_mutex_);
574 this->dictionary_->setVal<T>(idx, subidx, value);
575 prom->set_value(value);
576 }
577 std::unique_lock<std::mutex> lck(this->sdo_mutex);
578 this->running = false;
579 this->sdo_cond.notify_one();
580 },
581 this->sdo_timeout);
582 return prom->get_future();
583 }
584
585 template <typename T>
587 uint16_t idx, uint8_t subidx, T & value, std::chrono::milliseconds timeout)
588 {
589 auto fut = async_sdo_read_typed<T>(idx, subidx);
590 auto wait_res = fut.wait_for(timeout);
591 if (wait_res == std::future_status::timeout)
592 {
593 std::cout << "sync_sdo_read_typed: id=" << (unsigned int)this->get_id() << " index=0x"
594 << std::hex << (unsigned int)idx << " subindex=" << (unsigned int)subidx
595 << " timed out." << std::endl;
596 return false;
597 }
598 bool res = false;
599 try
600 {
601 value = fut.get();
602 res = true;
603 }
604 catch (std::exception & e)
605 {
606 RCLCPP_ERROR(rclcpp::get_logger(name_), e.what());
607 res = false;
608 }
609 return res;
610 }
611
621 std::future<canopen::NmtState> async_request_nmt();
622
634 std::shared_ptr<SafeQueue<COData>> get_rpdo_queue();
635
643 std::shared_ptr<SafeQueue<COEmcy>> get_emcy_queue();
644
655
664 void nmt_command(canopen::NmtCommand command);
665
671 uint8_t get_id();
672
680 {
681 if (booted.load()) return true;
682
683 std::unique_lock<std::mutex> lck(boot_mtex);
684 auto status = boot_cond.wait_for(lck, boot_timeout_);
685
686 if (status == std::cv_status::timeout)
687 {
688 throw std::system_error(
689 static_cast<int>(LelyBridgeErrc::TimeOut), LelyBridgeErrCategory(), "Boot Timeout");
690 }
691
692 if ((boot_status != 0) && (boot_status != 'L'))
693 {
694 throw std::system_error(static_cast<int>(boot_status), LelyBridgeErrCategory(), "Boot Issue");
695 }
696
697 booted.store(true);
698 return true;
699 }
700
701 void set_sync_function(std::function<void()> on_sync_function)
702 {
703 on_sync_function_ = on_sync_function;
704 }
705
706 void unset_sync_function() { on_sync_function_ = std::function<void()>(); }
707
712 void Boot()
713 {
714 booted.store(false);
715 FiberDriver::Boot();
716 }
717
724 bool is_booted() { return booted.load(); }
725
726 template <typename T>
728 {
729 T value = 0;
730 std::memcpy(&value, &data.data_, sizeof(value));
731
732 this->SubmitWrite(
733 data.index_, data.subindex_, value,
734 [this, value](uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec) mutable
735 {
736 if (ec)
737 {
738 this->sdo_write_data_promise->set_exception(
739 lely::canopen::make_sdo_exception_ptr(id, idx, subidx, ec, "AsyncDownload"));
740 }
741 else
742 {
743 std::scoped_lock<std::mutex> lck(this->dictionary_mutex_);
744 this->dictionary_->setVal<T>(idx, subidx, value);
745 this->sdo_write_data_promise->set_value(true);
746 }
747 std::unique_lock<std::mutex> lck(this->sdo_mutex);
748 this->running = false;
749 this->sdo_cond.notify_one();
750 },
751 this->sdo_timeout);
752 }
753
754 template <typename T>
756 {
757 this->SubmitRead<T>(
758 data.index_, data.subindex_,
759 [this](uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec, T value) mutable
760 {
761 if (ec)
762 {
763 this->sdo_read_data_promise->set_exception(
764 lely::canopen::make_sdo_exception_ptr(id, idx, subidx, ec, "AsyncUpload"));
765 }
766 else
767 {
768 std::scoped_lock<std::mutex> lck(this->dictionary_mutex_);
769 this->dictionary_->setVal<T>(idx, subidx, value);
770 COData d = {idx, subidx, 0};
771 std::memcpy(&d.data_, &value, sizeof(T));
772 this->sdo_read_data_promise->set_value(d);
773 }
774 std::unique_lock<std::mutex> lck(this->sdo_mutex);
775 this->running = false;
776 this->sdo_cond.notify_one();
777 },
778 this->sdo_timeout);
779 }
780
781 template <typename T>
782 const T universal_get_value(uint16_t index, uint8_t subindex)
783 {
784 T value = 0;
785 bool is_tpdo = false;
786 if (this->pdo_map_->find(index) != this->pdo_map_->end())
787 {
788 auto object = this->pdo_map_->at(index);
789 if (object.find(subindex) != object.end())
790 {
791 auto entry = object.at(subindex);
792 is_tpdo = entry.is_tpdo;
793 }
794 }
795 if (!is_tpdo)
796 {
797 if (sync_sdo_read_typed<T>(index, subindex, value, this->sdo_timeout))
798 {
799 return value;
800 }
801 }
802
803 std::scoped_lock<std::mutex> lck(this->dictionary_mutex_);
804 if (typeid(T) == typeid(uint8_t))
805 {
806 value = this->dictionary_->getVal<CO_DEFTYPE_UNSIGNED8>(index, subindex);
807 }
808 if (typeid(T) == typeid(uint16_t))
809 {
810 value = this->dictionary_->getVal<CO_DEFTYPE_UNSIGNED16>(index, subindex);
811 }
812 if (typeid(T) == typeid(uint32_t))
813 {
814 value = this->dictionary_->getVal<CO_DEFTYPE_UNSIGNED32>(index, subindex);
815 }
816 if (typeid(T) == typeid(int8_t))
817 {
818 value = this->dictionary_->getVal<CO_DEFTYPE_INTEGER8>(index, subindex);
819 }
820 if (typeid(T) == typeid(int16_t))
821 {
822 value = this->dictionary_->getVal<CO_DEFTYPE_INTEGER16>(index, subindex);
823 }
824 if (typeid(T) == typeid(int32_t))
825 {
826 value = this->dictionary_->getVal<CO_DEFTYPE_INTEGER32>(index, subindex);
827 }
828
829 return value;
830 }
831
832 template <typename T>
833 void universal_set_value(uint16_t index, uint8_t subindex, T value)
834 {
835 bool is_rpdo = false;
836 if (this->pdo_map_->find(index) != this->pdo_map_->end())
837 {
838 auto object = this->pdo_map_->at(index);
839 if (object.find(subindex) != object.end())
840 {
841 auto entry = object.at(subindex);
842 is_rpdo = entry.is_rpdo;
843 }
844 }
845 if (is_rpdo)
846 {
847 std::scoped_lock<std::mutex> lck(this->dictionary_mutex_);
848 this->dictionary_->setVal<T>(index, subindex, value);
849 this->tpdo_mapped[index][subindex] = value;
850 this->tpdo_mapped[index][subindex].WriteEvent();
851 }
852 else
853 {
854 sync_sdo_write_typed(index, subindex, value, this->sdo_timeout);
855 }
856 }
857};
858
859} // namespace ros2_canopen
860
861#endif // CANOPEN_BASE_DRIVER__LELY_BRIDGE_HPP_
Definition lely_driver_bridge.hpp:59
~DriverDictionary()
Definition lely_driver_bridge.hpp:62
DriverDictionary(std::string eds_file)
Definition lely_driver_bridge.hpp:61
bool checkObjTPDO(uint16_t idx, uint8_t subidx)
Definition lely_driver_bridge.hpp:187
bool checkObjInPDO(uint8_t pdo, uint16_t mapping_idx, uint16_t idx, uint8_t subindex)
Definition lely_driver_bridge.hpp:201
std::shared_ptr< PDOMap > createPDOMapping()
Definition lely_driver_bridge.hpp:67
void fetchTPDO(std::shared_ptr< PDOMap > map)
Definition lely_driver_bridge.hpp:141
void fetchRPDO(std::shared_ptr< PDOMap > map)
Definition lely_driver_bridge.hpp:111
bool checkObjRPDO(uint16_t idx, uint8_t subidx)
Definition lely_driver_bridge.hpp:173
Lely Driver Bridge.
Definition lely_driver_bridge.hpp:277
std::shared_ptr< SafeQueue< COEmcy > > get_emcy_queue()
Asynchronous request for EMCY.
std::atomic< bool > emcy_is_set
Definition lely_driver_bridge.hpp:304
std::mutex sdo_mutex
Definition lely_driver_bridge.hpp:287
void universal_set_value(uint16_t index, uint8_t subindex, T value)
Definition lely_driver_bridge.hpp:833
bool is_booted()
Indicates if Device is booted.
Definition lely_driver_bridge.hpp:724
std::mutex boot_mtex
Definition lely_driver_bridge.hpp:314
bool sync_sdo_write_typed(uint16_t idx, uint8_t subidx, T value, std::chrono::milliseconds timeout)
Definition lely_driver_bridge.hpp:494
std::promise< COData > rpdo_promise
Definition lely_driver_bridge.hpp:297
bool running
Definition lely_driver_bridge.hpp:288
bool sync_sdo_read_typed(uint16_t idx, uint8_t subidx, T &value, std::chrono::milliseconds timeout)
Definition lely_driver_bridge.hpp:586
std::shared_ptr< std::promise< bool > > sdo_write_data_promise
Definition lely_driver_bridge.hpp:286
std::shared_ptr< PDOMap > pdo_map_
Definition lely_driver_bridge.hpp:282
std::unique_ptr< DriverDictionary > dictionary_
Definition lely_driver_bridge.hpp:280
std::atomic< bool > rpdo_is_set
Definition lely_driver_bridge.hpp:298
std::condition_variable sdo_cond
Definition lely_driver_bridge.hpp:289
void unset_sync_function()
Definition lely_driver_bridge.hpp:706
std::mutex emcy_mtex
Definition lely_driver_bridge.hpp:305
void OnRpdoWrite(uint16_t idx, uint8_t subidx) noexcept override
OnRpdoWrite Callback.
std::future< T > async_sdo_read_typed(uint16_t idx, uint8_t subidx)
Definition lely_driver_bridge.hpp:534
virtual void OnBoot(canopen::NmtState st, char es, const ::std::string &what) noexcept override
OnBoot Callback This callback is called when the Boot process of the slave that was initiated by the ...
void nmt_command(canopen::NmtCommand command)
Executes a NMT Command.
void set_sync_function(std::function< void()> on_sync_function)
Definition lely_driver_bridge.hpp:701
std::string boot_what
Definition lely_driver_bridge.hpp:311
std::mutex nmt_mtex
Definition lely_driver_bridge.hpp:294
std::future< canopen::NmtState > async_request_nmt()
Asynchronous request for NMT.
std::promise< canopen::NmtState > nmt_state_promise
Definition lely_driver_bridge.hpp:292
std::chrono::milliseconds sdo_timeout
Definition lely_driver_bridge.hpp:320
std::future< bool > async_sdo_write_typed(uint16_t idx, uint8_t subidx, T value)
Definition lely_driver_bridge.hpp:448
std::shared_ptr< SafeQueue< COData > > get_rpdo_queue()
Asynchronous request for RPDO.
std::future< COData > async_sdo_read(COData data)
Aynchronous SDO Read.
void submit_read(COData data)
Definition lely_driver_bridge.hpp:755
std::atomic< bool > nmt_state_is_set
Definition lely_driver_bridge.hpp:293
std::function< void()> on_sync_function_
Definition lely_driver_bridge.hpp:322
uint8_t get_id()
Get the nodeid.
void OnEmcy(uint16_t eec, uint8_t er, uint8_t msef[5]) noexcept override
void submit_write(COData data)
Definition lely_driver_bridge.hpp:727
LelyDriverBridge(ev_exec_t *exec, canopen::AsyncMaster &master, uint8_t id, std::string name, std::string eds, std::string bin, std::chrono::milliseconds timeout=20ms, std::chrono::milliseconds boot_timeout=20ms)
Construct a new Lely Bridge object.
Definition lely_driver_bridge.hpp:408
const T universal_get_value(uint16_t index, uint8_t subindex)
Definition lely_driver_bridge.hpp:782
std::shared_ptr< SafeQueue< COData > > rpdo_queue
Definition lely_driver_bridge.hpp:300
std::mutex pdo_mtex
Definition lely_driver_bridge.hpp:299
void Boot()
Request master to boot device.
Definition lely_driver_bridge.hpp:712
bool wait_for_boot()
Wait for device to be booted.
Definition lely_driver_bridge.hpp:679
std::atomic< bool > booted
Definition lely_driver_bridge.hpp:309
std::shared_ptr< std::promise< COData > > sdo_read_data_promise
Definition lely_driver_bridge.hpp:285
std::chrono::milliseconds boot_timeout_
Definition lely_driver_bridge.hpp:315
std::promise< COEmcy > emcy_promise
Definition lely_driver_bridge.hpp:303
std::condition_variable boot_cond
Definition lely_driver_bridge.hpp:313
std::future< bool > async_sdo_write(COData data)
Asynchronous SDO Write.
void tpdo_transmit(COData data)
Executes a TPDO transmission.
char boot_status
Definition lely_driver_bridge.hpp:310
std::shared_ptr< SafeQueue< COEmcy > > emcy_queue
Definition lely_driver_bridge.hpp:306
void OnSync(uint8_t cnt, const time_point &t) noexcept override
Definition lely_driver_bridge.hpp:334
std::mutex dictionary_mutex_
Definition lely_driver_bridge.hpp:281
canopen::NmtState boot_state
Definition lely_driver_bridge.hpp:312
uint8_t nodeid
Definition lely_driver_bridge.hpp:317
std::string name_
Definition lely_driver_bridge.hpp:318
void OnState(canopen::NmtState state) noexcept override
OnState Callback.
Thread Safe Queue for CANOpen Data Exchange.
Definition exchange.hpp:49
Definition configuration_manager.hpp:28
std::map< uint16_t, std::map< uint8_t, pdo_mapping > > PDOMap
Definition lely_driver_bridge.hpp:57
LelyBridgeErrc
Definition lely_driver_bridge.hpp:229
Definition lely_driver_bridge.hpp:256
std::error_code make_error_code(ros2_canopen::LelyBridgeErrc)
Definition exchange.hpp:26
uint32_t data_
Definition exchange.hpp:30
uint8_t subindex_
Definition exchange.hpp:29
uint16_t index_
Definition exchange.hpp:28
Definition exchange.hpp:34
Definition lely_driver_bridge.hpp:249
const char * name() const noexcept override
std::string message(int ev) const override
Definition lely_driver_bridge.hpp:52
bool is_rpdo
Definition lely_driver_bridge.hpp:54
bool is_tpdo
Definition lely_driver_bridge.hpp:53