Apollo 9.0
自动驾驶开放平台
hybrid_transmitter.h
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
17#ifndef CYBER_TRANSPORT_TRANSMITTER_HYBRID_TRANSMITTER_H_
18#define CYBER_TRANSPORT_TRANSMITTER_HYBRID_TRANSMITTER_H_
19
20#include <chrono>
21#include <map>
22#include <memory>
23#include <set>
24#include <string>
25#include <unordered_map>
26#include <vector>
27
29#include "cyber/common/log.h"
30#include "cyber/common/types.h"
31#include "cyber/proto/role_attributes.pb.h"
32#include "cyber/proto/transport_conf.pb.h"
33#include "cyber/task/task.h"
40
41namespace apollo {
42namespace cyber {
43namespace transport {
44
48
49template <typename M>
50class HybridTransmitter : public Transmitter<M> {
51 public:
52 using MessagePtr = std::shared_ptr<M>;
53 using HistoryPtr = std::shared_ptr<History<M>>;
54 using TransmitterPtr = std::shared_ptr<Transmitter<M>>;
56 std::unordered_map<OptionalMode, TransmitterPtr, std::hash<int>>;
58 std::unordered_map<OptionalMode, std::set<uint64_t>, std::hash<int>>;
59 using CommunicationModePtr = std::shared_ptr<proto::CommunicationMode>;
61 std::unordered_map<Relation, OptionalMode, std::hash<int>>;
62
64 const ParticipantPtr& participant);
65 virtual ~HybridTransmitter();
66
67 void Enable() override;
68 void Disable() override;
69 void Enable(const RoleAttributes& opposite_attr) override;
70 void Disable(const RoleAttributes& opposite_attr) override;
71
72 bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) override;
73
74 bool AcquireMessage(std::shared_ptr<M>& msg);
75
76 private:
77 void InitMode();
78 void ObtainConfig();
79 void InitHistory();
80 void InitTransmitters();
81 void ClearTransmitters();
82 void InitReceivers();
83 void ClearReceivers();
84 void TransmitHistoryMsg(const RoleAttributes& opposite_attr);
85 void ThreadFunc(const RoleAttributes& opposite_attr,
86 const std::vector<typename History<M>::CachedMessage>& msgs);
87 Relation GetRelation(const RoleAttributes& opposite_attr);
88
89 HistoryPtr history_;
90 TransmitterMap transmitters_;
91 ReceiverMap receivers_;
92 std::mutex mutex_;
93
95 MappingTable mapping_table_;
96
97 ParticipantPtr participant_;
98};
99
100template <typename M>
102 const ParticipantPtr& participant)
103 : Transmitter<M>(attr),
104 history_(nullptr),
105 mode_(nullptr),
106 participant_(participant) {
107 InitMode();
108 ObtainConfig();
109 InitHistory();
110 InitTransmitters();
111 InitReceivers();
112}
113
114template <typename M>
116 ClearReceivers();
117 ClearTransmitters();
118}
119
120template <typename M>
122 std::lock_guard<std::mutex> lock(mutex_);
123 for (auto& item : transmitters_) {
124 item.second->Enable();
125 }
126}
127
128template <typename M>
130 std::lock_guard<std::mutex> lock(mutex_);
131 for (auto& item : transmitters_) {
132 item.second->Disable();
133 }
134}
135
136template <typename M>
138 auto relation = GetRelation(opposite_attr);
139 if (relation == NO_RELATION) {
140 return;
141 }
142
143 uint64_t id = opposite_attr.id();
144 std::lock_guard<std::mutex> lock(mutex_);
145 receivers_[mapping_table_[relation]].insert(id);
146 transmitters_[mapping_table_[relation]]->Enable(opposite_attr);
147 TransmitHistoryMsg(opposite_attr);
148}
149
150template <typename M>
152 auto relation = GetRelation(opposite_attr);
153 if (relation == NO_RELATION) {
154 return;
155 }
156
157 uint64_t id = opposite_attr.id();
158 std::lock_guard<std::mutex> lock(mutex_);
159 receivers_[mapping_table_[relation]].erase(id);
160 transmitters_[mapping_table_[relation]]->Disable(opposite_attr);
161}
162
163template <typename M>
165 const MessageInfo& msg_info) {
166 std::lock_guard<std::mutex> lock(mutex_);
167 history_->Add(msg, msg_info);
168 for (auto& item : transmitters_) {
169 item.second->Transmit(msg, msg_info);
170 }
171 return true;
172}
173
174template <typename M>
175bool HybridTransmitter<M>::AcquireMessage(std::shared_ptr<M>& msg) {
176 bool result = false;
177 for (auto& item : transmitters_) {
178 result = item.second->AcquireMessage(msg);
179 if (result) {
180 return true;
181 }
182 }
183 return false;
184}
185
186template <typename M>
188 mode_ = std::make_shared<proto::CommunicationMode>();
189 mapping_table_[SAME_PROC] = mode_->same_proc();
190 mapping_table_[DIFF_PROC] = mode_->diff_proc();
191 mapping_table_[DIFF_HOST] = mode_->diff_host();
192}
193
194template <typename M>
195void HybridTransmitter<M>::ObtainConfig() {
196 auto& global_conf = common::GlobalData::Instance()->Config();
197 if (!global_conf.has_transport_conf()) {
198 return;
199 }
200 if (!global_conf.transport_conf().has_communication_mode()) {
201 return;
202 }
203 mode_->CopyFrom(global_conf.transport_conf().communication_mode());
204
205 mapping_table_[SAME_PROC] = mode_->same_proc();
206 mapping_table_[DIFF_PROC] = mode_->diff_proc();
207 mapping_table_[DIFF_HOST] = mode_->diff_host();
208}
209
210template <typename M>
211void HybridTransmitter<M>::InitHistory() {
212 HistoryAttributes history_attr(this->attr_.qos_profile().history(),
213 this->attr_.qos_profile().depth());
214 history_ = std::make_shared<History<M>>(history_attr);
215 if (this->attr_.qos_profile().durability() ==
216 QosDurabilityPolicy::DURABILITY_TRANSIENT_LOCAL) {
217 history_->Enable();
218 }
219}
220
221template <typename M>
222void HybridTransmitter<M>::InitTransmitters() {
223 std::set<OptionalMode> modes;
224 modes.insert(mode_->same_proc());
225 modes.insert(mode_->diff_proc());
226 modes.insert(mode_->diff_host());
227 for (auto& mode : modes) {
228 switch (mode) {
229 case OptionalMode::INTRA:
230 transmitters_[mode] =
231 std::make_shared<IntraTransmitter<M>>(this->attr_);
232 break;
233 case OptionalMode::SHM:
234 transmitters_[mode] = std::make_shared<ShmTransmitter<M>>(this->attr_);
235 break;
236 default:
237 transmitters_[mode] =
238 std::make_shared<RtpsTransmitter<M>>(this->attr_, participant_);
239 break;
240 }
241 }
242}
243
244template <typename M>
245void HybridTransmitter<M>::ClearTransmitters() {
246 for (auto& item : transmitters_) {
247 item.second->Disable();
248 }
249 transmitters_.clear();
250}
251
252template <typename M>
253void HybridTransmitter<M>::InitReceivers() {
254 std::set<uint64_t> empty;
255 for (auto& item : transmitters_) {
256 receivers_[item.first] = empty;
257 }
258}
259
260template <typename M>
261void HybridTransmitter<M>::ClearReceivers() {
262 receivers_.clear();
263}
264
265template <typename M>
266void HybridTransmitter<M>::TransmitHistoryMsg(
267 const RoleAttributes& opposite_attr) {
268 // check qos
269 if (this->attr_.qos_profile().durability() !=
270 QosDurabilityPolicy::DURABILITY_TRANSIENT_LOCAL) {
271 return;
272 }
273
274 // get unsent messages
275 std::vector<typename History<M>::CachedMessage> unsent_msgs;
276 history_->GetCachedMessage(&unsent_msgs);
277 if (unsent_msgs.empty()) {
278 return;
279 }
280
281 auto attr = opposite_attr;
282 cyber::Async(&HybridTransmitter<M>::ThreadFunc, this, attr, unsent_msgs);
283}
284
285template <typename M>
286void HybridTransmitter<M>::ThreadFunc(
287 const RoleAttributes& opposite_attr,
288 const std::vector<typename History<M>::CachedMessage>& msgs) {
289 // create transmitter to transmit msgs
290 RoleAttributes new_attr;
291 new_attr.CopyFrom(this->attr_);
292 std::string new_channel_name =
293 std::to_string(this->attr_.id()) + std::to_string(opposite_attr.id());
294 uint64_t channel_id = common::GlobalData::RegisterChannel(new_channel_name);
295 new_attr.set_channel_name(new_channel_name);
296 new_attr.set_channel_id(channel_id);
297 auto new_transmitter =
298 std::make_shared<RtpsTransmitter<M>>(new_attr, participant_);
299 new_transmitter->Enable();
300
301 for (auto& item : msgs) {
302 new_transmitter->Transmit(item.msg, item.msg_info);
303 cyber::USleep(1000);
304 }
305 new_transmitter->Disable();
306 ADEBUG << "trans threadfunc exit.";
307}
308
309template <typename M>
310Relation HybridTransmitter<M>::GetRelation(
311 const RoleAttributes& opposite_attr) {
312 if (opposite_attr.channel_name() != this->attr_.channel_name()) {
313 return NO_RELATION;
314 }
315 if (opposite_attr.host_ip() != this->attr_.host_ip()) {
316 return DIFF_HOST;
317 }
318 if (opposite_attr.process_id() != this->attr_.process_id()) {
319 return DIFF_PROC;
320 }
321
322 return SAME_PROC;
323}
324
325} // namespace transport
326} // namespace cyber
327} // namespace apollo
328
329#endif // CYBER_TRANSPORT_TRANSMITTER_HYBRID_TRANSMITTER_H_
static uint64_t RegisterChannel(const std::string &channel)
std::unordered_map< OptionalMode, std::set< uint64_t >, std::hash< int > > ReceiverMap
std::unordered_map< OptionalMode, TransmitterPtr, std::hash< int > > TransmitterMap
std::unordered_map< Relation, OptionalMode, std::hash< int > > MappingTable
bool Transmit(const MessagePtr &msg, const MessageInfo &msg_info) override
std::shared_ptr< Transmitter< M > > TransmitterPtr
HybridTransmitter(const RoleAttributes &attr, const ParticipantPtr &participant)
std::shared_ptr< History< M > > HistoryPtr
std::shared_ptr< proto::CommunicationMode > CommunicationModePtr
bool AcquireMessage(std::shared_ptr< M > &msg)
#define ADEBUG
Definition log.h:41
std::shared_ptr< Participant > ParticipantPtr
Definition participant.h:37
Relation
Describe relation between nodes, writers/readers...
Definition types.h:36
@ NO_RELATION
Definition types.h:37
class register implement