EduArt Sensor Ring Library 4.0.0
Loading...
Searching...
No Matches
Group.hpp
Go to the documentation of this file.
1// Copyright (c) 2026 EduArt Robotik GmbH
2
9
10#pragma once
11
12#include <cstddef>
13#include <functional>
14#include <memory>
15#include <type_traits>
16#include <vector>
17
20
21namespace eduart {
22
23namespace sensorring {
24
25namespace device {
26
37template <typename T> class Group {
38public:
40 class iterator {
41 typename std::vector<T*>::iterator _it;
42
43 public:
44 iterator(typename std::vector<T*>::iterator it)
45 : _it(it) {}
46 T& operator*() const { return **_it; }
47 T* operator->() const { return *_it; }
48 iterator& operator++() {
49 ++_it;
50 return *this;
51 }
52 bool operator!=(const iterator& other) const { return _it != other._it; }
53 bool operator==(const iterator& other) const { return _it == other._it; }
54 };
55
60 class const_iterator {
61 typename std::vector<T*>::const_iterator _it;
62
63 public:
64 const_iterator(typename std::vector<T*>::const_iterator it)
65 : _it(it) {}
66 const T& operator*() const { return **_it; }
67 const T* operator->() const { return *_it; }
68 const_iterator& operator++() {
69 ++_it;
70 return *this;
71 }
72 bool operator!=(const const_iterator& other) const { return _it != other._it; }
73 bool operator==(const const_iterator& other) const { return _it == other._it; }
74 };
75
76 Group() = default;
77 explicit Group(std::vector<T*> devices)
78 : _devices(std::move(devices)) {}
79
81 T& operator[](std::size_t i) { return *_devices[i]; }
82 const T& operator[](std::size_t i) const { return *_devices[i]; }
83
85 std::size_t size() const { return _devices.size(); }
86
88 bool empty() const { return _devices.empty(); }
89
91 std::vector<T*> get() const { return _devices; }
92
94 iterator begin() { return iterator(_devices.begin()); }
96 iterator end() { return iterator(_devices.end()); }
98 const_iterator begin() const { return const_iterator(_devices.begin()); }
100 const_iterator end() const { return const_iterator(_devices.end()); }
101
113 template <typename U = T, typename = typename U::MeasurementType> subscription::Subscription subscribe(std::function<void(const typename U::MeasurementType&)> callback) {
114 auto subs = std::make_shared<std::vector<subscription::Subscription> >();
115 for (auto* dev : _devices) {
116 subs->push_back(dev->subscribe(callback));
117 }
119 return subscription::Subscription(token, [subs]() {
120 for (auto& s : *subs)
121 s.cancel();
122 subs->clear();
123 });
124 }
125
139 template <typename U = T, typename = typename U::MeasurementType> subscription::Subscription subscribeAll(std::function<void(const std::vector<typename U::MeasurementType>&)> callback) {
140 const std::size_t n = _devices.size();
141
142 struct FrameState {
143 std::vector<typename U::MeasurementType> buffer;
144 std::vector<bool> received;
145 std::size_t count = 0;
146 std::size_t expected = 0;
147 std::function<void(const std::vector<typename U::MeasurementType>&)> callback;
148 };
149
150 auto state = std::make_shared<FrameState>();
151 state->buffer.resize(n);
152 state->received.resize(n, false);
153 state->count = 0;
154 state->expected = n;
155 state->callback = std::move(callback);
156
157 auto subs = std::make_shared<std::vector<subscription::Subscription> >();
158 for (std::size_t i = 0; i < n; ++i) {
159 subs->push_back(_devices[i]->subscribe([state, i](const typename U::MeasurementType& m) {
160 state->buffer[i] = m;
161 if (!state->received[i]) {
162 state->received[i] = true;
163 state->count++;
164 }
165 if (state->count == state->expected) {
166 state->callback(state->buffer);
167 // Reset for next frame
168 std::fill(state->received.begin(), state->received.end(), false);
169 state->count = 0;
170 }
171 }));
172 }
173
175 return subscription::Subscription(token, [subs]() {
176 for (auto& s : *subs)
177 s.cancel();
178 subs->clear();
179 });
180 }
181
182private:
183 std::vector<T*> _devices;
184};
185
186} // namespace device
187
188} // namespace sensorring
189
190} // namespace eduart
Opaque token identifying a subscription.
RAII wrapper pairing a SubscriberToken with its cancel function.
Const dereferencing iterator so range-for over a const Group<T> yields const T&.
Definition Group.hpp:60
iterator end()
Past-the-end iterator (mutable).
Definition Group.hpp:96
std::vector< T * > get() const
Get the underlying vector of device pointers.
Definition Group.hpp:91
const_iterator begin() const
Begin iterator (const).
Definition Group.hpp:98
subscription::Subscription subscribe(std::function< void(const typename U::MeasurementType &)> callback)
Subscribe to all devices in the group.
Definition Group.hpp:113
T & operator[](std::size_t i)
Access device by index (returns reference).
Definition Group.hpp:81
iterator begin()
Begin iterator (mutable).
Definition Group.hpp:94
std::size_t size() const
Number of devices in this group.
Definition Group.hpp:85
const_iterator end() const
Past-the-end iterator (const).
Definition Group.hpp:100
bool empty() const
Whether the group is empty.
Definition Group.hpp:88
subscription::Subscription subscribeAll(std::function< void(const std::vector< typename U::MeasurementType > &)> callback)
Subscribe to all devices in the group with synchronized frame delivery.
Definition Group.hpp:139
Move-only RAII wrapper that pairs a SubscriberToken with an unsubscribe callable. Destroying a Subscr...
Definition Subscription.hpp:32
static SubscriberToken getNextToken() noexcept
Get the next token.
Definition SubscriberToken.hpp:43