Goby3 3.7.0
2026.11.12
Loading...
Searching...
No Matches
driver_thread.h
Go to the documentation of this file.
1// Copyright 2019-2026:
2// GobySoft, LLC (2013-)
3// Community contributors (see AUTHORS file)
4// File authors:
5// Toby Schneider <toby@gobysoft.org>
6//
7//
8// This file is part of the Goby Underwater Autonomy Project Libraries
9// ("The Goby Libraries").
10//
11// The Goby Libraries are free software: you can redistribute them and/or modify
12// them under the terms of the GNU Lesser General Public License as published by
13// the Free Software Foundation, either version 2.1 of the License, or
14// (at your option) any later version.
15//
16// The Goby Libraries are distributed in the hope that they will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public License
22// along with Goby. If not, see <http://www.gnu.org/licenses/>.
23
24#ifndef GOBY_MIDDLEWARE_TRANSPORT_INTERVEHICLE_DRIVER_THREAD_H
25#define GOBY_MIDDLEWARE_TRANSPORT_INTERVEHICLE_DRIVER_THREAD_H
26
27#include <cstddef>
28#include <map>
29#include <memory>
30#include <ostream>
31#include <set>
32#include <string>
33#include <vector>
34
35#include <boost/units/quantity.hpp>
36
51#include "goby/time/convert.h"
54#include "goby/time/types.h"
56
57namespace goby
58{
59namespace acomms
60{
61namespace protobuf
62{
63class ModemTransmission;
64} // namespace protobuf
65} // namespace acomms
66
67namespace middleware
68{
69template <typename Data> class Publisher;
70
71namespace protobuf
72{
73inline size_t data_size(const SerializerTransporterMessage& msg) { return msg.data().size(); }
74
76{
77 return (a.key().serialize_time() == b.key().serialize_time() &&
79 a.key().type() == b.key().type() && a.key().group() == b.key().group() &&
80 a.data() == b.data());
81}
82
84{
85 if (a.key().serialize_time() != b.key().serialize_time())
86 return a.key().serialize_time() < b.key().serialize_time();
87 else if (a.key().marshalling_scheme() != b.key().marshalling_scheme())
88 return a.key().marshalling_scheme() < b.key().marshalling_scheme();
89 else if (a.key().type() != b.key().type())
90 return a.key().type() < b.key().type();
91 else if (a.key().group() != b.key().group())
92 return a.key().group() < b.key().group();
93 else
94 return a.data() < b.data();
95}
96
97} // namespace protobuf
98
99namespace intervehicle
100{
101namespace protobuf
102{
103inline bool operator==(const TransporterConfig& a, const TransporterConfig& b)
104{
105 return a.SerializeAsString() == b.SerializeAsString();
106}
107
108} // namespace protobuf
109
110template <typename Data>
111std::shared_ptr<goby::middleware::protobuf::SerializerTransporterMessage>
112serialize_publication(const Data& d, const Group& group, const Publisher<Data>& publisher)
113{
115 auto* sbytes = new std::string(bytes.begin(), bytes.end());
116 auto msg = std::make_shared<goby::middleware::protobuf::SerializerTransporterMessage>();
117
118 auto* key = msg->mutable_key();
119 key->set_marshalling_scheme(MarshallingScheme::DCCL);
121 key->set_group(std::string(group));
122 key->set_group_numeric(group.numeric());
123 auto now = goby::time::SystemClock::now<goby::time::MicroTime>();
124 key->set_serialize_time_with_units(now);
125 *key->mutable_cfg() = publisher.cfg();
126 msg->set_allocated_data(sbytes);
127 return msg;
128}
129
133template <typename ImplementationTag>
135 intervehicle::protobuf::PortalConfig::LinkConfig,
136 InterProcessForwarder<InterThreadTransporter, ImplementationTag>>
137{
138 public:
143
145 void loop() override;
146 int tx_queue_size() { return buffer_.size(); }
147
148 private:
149 void finalize() override;
151 void _buffer_message(
152 const std::shared_ptr<const goby::middleware::protobuf::SerializerTransporterMessage>& msg);
153 void _receive(const goby::acomms::protobuf::ModemTransmission& rx_msg);
154 void _forward_subscription(intervehicle::protobuf::Subscription subscription);
155 void _accept_subscription(const intervehicle::protobuf::Subscription& subscription);
156 void _ack_value(intervehicle::protobuf::AckMessagePair& ack_pair,
159 void _expire_value(const goby::time::SteadyClock::time_point now,
162 void _erase_pending_ack(
164 void _discard_superseded(
166 std::vector<buffer_value_type> _take_superseded(const buffer_value_type& value);
167
168 subbuffer_id_type _create_buffer_id(unsigned dccl_id, unsigned group);
169
171 _create_buffer_id(const goby::middleware::protobuf::SerializerTransporterKey& key)
172 {
173 return _create_buffer_id(detail::DCCLSerializerParserHelperBase::id(key.type()),
174 key.group_numeric());
175 }
176
177 subbuffer_id_type _create_buffer_id(const intervehicle::protobuf::Subscription& subscription)
178 {
179 return _create_buffer_id(subscription.dccl_id(), subscription.group());
180 }
181
182 void _try_create_or_update_buffer(modem_id_type dest_id, const subbuffer_id_type& buffer_id);
183
184 modem_id_type _broadcast_id() { return this->cfg().modem_id() & this->cfg().subnet_mask(); }
185
186 // id within subnet
187 modem_id_type _id_within_subnet(modem_id_type id) { return id - _broadcast_id(); }
188
189 // full id
190 modem_id_type _full_id(modem_id_type id_in_subnet) { return id_in_subnet + _broadcast_id(); }
191
192 bool _dest_is_in_subnet(modem_id_type dest_id)
193 {
194 bool dest_in_subnet = (dest_id & this->cfg().subnet_mask()) ==
195 (this->cfg().modem_id() & this->cfg().subnet_mask());
196 if (!dest_in_subnet)
198 goby::glog << "Dest: " << dest_id
199 << " is not in subnet (our id: " << this->cfg().modem_id()
200 << ", mask: " << this->cfg().subnet_mask() << ")" << std::endl;
201
202 return dest_in_subnet;
203 }
204
205 void _publish_subscription_report(const intervehicle::protobuf::Subscription& changed);
206 void _create_driver();
207 bool _try_driver_startup();
208 // returns false if the failure should instead terminate the portal
209 bool _restart_on_failure(const goby::acomms::ModemDriverException& e);
210 void _publish_modem_report();
211
212 private:
213 std::unique_ptr<InterThreadTransporter> interthread_;
214 std::unique_ptr<InterProcessForwarder<InterThreadTransporter, ImplementationTag>> interprocess_;
215
216 std::multimap<subbuffer_id_type, goby::middleware::protobuf::SerializerTransporterKey>
217 publisher_buffer_cfg_;
218
219 std::map<modem_id_type, std::multimap<subbuffer_id_type, intervehicle::protobuf::Subscription>>
220 subscriber_buffer_cfg_;
221
222 std::map<subbuffer_id_type, std::set<modem_id_type>> subbuffers_created_;
223
225 std::set<modem_id_type> subscription_subbuffers_;
226 struct QueuedSubscription
227 {
228 intervehicle::protobuf::Subscription subscription;
229 buffer_data_type data;
230 // equivalent subscriptions (possibly from other local subscribers) that this one replaced
231 // and now stands in for: they are acked or expired along with it
232 std::vector<buffer_value_type> superseded;
233 };
234 // subscriptions queued or awaiting ack per destination, so a newer equivalent one can replace them
235 std::map<modem_id_type, std::vector<QueuedSubscription>> queued_subscriptions_;
236
238
239 using frame_type = int;
240 std::map<frame_type, std::vector<goby::acomms::DynamicBuffer<buffer_data_type>::Value>>
241 pending_ack_;
242
243 std::unique_ptr<goby::acomms::ModemDriverBase> driver_;
245
246 std::string glog_group_;
247
248 goby::time::SteadyClock::time_point next_modem_report_time_;
249 const goby::time::SteadyClock::duration modem_report_interval_;
250
251 bool driver_started_{false};
254 goby::time::SteadyClock::time_point next_restart_attempt_;
255};
256
257} // namespace intervehicle
258} // namespace middleware
259} // namespace goby
260
261#endif
Represents a time-dependent priority queue for several groups of messages (multiple DynamicSubBuffers...
provides an API to the goby-acomms MAC library. MACManager is essentially a std::list<protobuf::Modem...
Definition mac_manager.h:50
Class for grouping publications in the Goby middleware. Analogous to "topics" in ROS,...
Definition group.h:60
Class that holds additional metadata and callback functions related to a publication (and is optional...
Definition publisher.h:40
const goby::middleware::protobuf::TransporterConfig & cfg() const
Returns the metadata configuration.
Definition publisher.h:108
Represents a thread of execution within the Goby middleware, interleaving periodic events (loop()) wi...
Definition thread.h:61
Provides the modem driver thread used by InterVehiclePortal, templated on ImplementationTag so it use...
goby::acomms::DynamicBuffer< buffer_data_type >::Value buffer_value_type
ModemDriverThread(const intervehicle::protobuf::PortalConfig::LinkConfig &cfg)
goby::acomms::DynamicBuffer< buffer_data_type >::modem_id_type modem_id_type
goby::acomms::DynamicBuffer< buffer_data_type >::subbuffer_id_type subbuffer_id_type
goby::middleware::protobuf::SerializerTransporterMessage buffer_data_type
const ::goby::middleware::protobuf::SerializerTransporterKey & key() const
goby::util::logger::GroupSetter group(std::string n)
bool operator==(const TransporterConfig &a, const TransporterConfig &b)
std::shared_ptr< goby::middleware::protobuf::SerializerTransporterMessage > serialize_publication(const Data &d, const Group &group, const Publisher< Data > &publisher)
bool operator<(const TCPEndPoint &ep_a, const TCPEndPoint &ep_b)
size_t data_size(const SerializerTransporterMessage &msg)
bool operator==(const TCPEndPoint &ep_a, const TCPEndPoint &ep_b)
The global namespace for the Goby project.
extern ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< ::PROTOBUF_NAMESPACE_ID::MessageOptions, ::PROTOBUF_NAMESPACE_ID::internal::MessageTypeTraits< ::goby::GobyMessageOptions >, 11, false > msg
util::FlexOstream glog
Access the Goby logger through this object.
Class for parsing and serializing a given marshalling scheme. Must be specialized for a particular sc...
Definition interface.h:98
static unsigned id(CharIterator begin, CharIterator end)
std::chrono::time_point< SteadyClock > time_point
std::chrono::microseconds duration
Duration type.